From 7f81597a8146e0fa5f062cf42a30c86914877ec5 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 13 Apr 2009 15:49:26 -0400 Subject: isReadOnly() now takes arguments Add an array of arguments to isReadOnly() method of actions, to let them change their results depending on what actions are called. Primarily used by the 'api' action. Ideally in the future that will be multiple actions. But this might still be useful. --- lib/action.php | 5 ++++- lib/error.php | 2 +- lib/galleryaction.php | 2 +- lib/peoplesearchresults.php | 2 +- lib/personal.php | 2 +- lib/searchaction.php | 2 +- 6 files changed, 9 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/action.php b/lib/action.php index cc98d4445..673549246 100644 --- a/lib/action.php +++ b/lib/action.php @@ -791,9 +791,12 @@ class Action extends HTMLOutputter // lawsuit * * MAY override * + * @param array $args other arguments + * * @return boolean is read only action? */ - function isReadOnly() + + function isReadOnly($args)($args) { return false; } diff --git a/lib/error.php b/lib/error.php index 526d9f81b..282682133 100644 --- a/lib/error.php +++ b/lib/error.php @@ -93,7 +93,7 @@ class ErrorAction extends Action return $this->message; } - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/lib/galleryaction.php b/lib/galleryaction.php index 8e21d7393..0484918ce 100644 --- a/lib/galleryaction.php +++ b/lib/galleryaction.php @@ -76,7 +76,7 @@ class GalleryAction extends Action return true; } - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/lib/peoplesearchresults.php b/lib/peoplesearchresults.php index f8ab7cf3b..d3f840852 100644 --- a/lib/peoplesearchresults.php +++ b/lib/peoplesearchresults.php @@ -67,7 +67,7 @@ class PeopleSearchResults extends ProfileList return preg_replace($this->pattern, '\\1', htmlspecialchars($text)); } - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/lib/personal.php b/lib/personal.php index e46350c63..f92732375 100644 --- a/lib/personal.php +++ b/lib/personal.php @@ -47,7 +47,7 @@ class PersonalAction extends Action var $user = null; - function isReadOnly() + function isReadOnly($args) { return true; } diff --git a/lib/searchaction.php b/lib/searchaction.php index e7ad4affd..e74450e11 100644 --- a/lib/searchaction.php +++ b/lib/searchaction.php @@ -51,7 +51,7 @@ class SearchAction extends Action * * @return boolean true */ - function isReadOnly() + function isReadOnly($args) { return true; } -- cgit v1.2.3-54-g00ecf From 1bae34e24fe87ed1abcd5c27e183e8a826fbf775 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 13 Apr 2009 15:54:16 -0400 Subject: typo in lib action --- lib/action.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/action.php b/lib/action.php index 673549246..1ba062812 100644 --- a/lib/action.php +++ b/lib/action.php @@ -796,7 +796,7 @@ class Action extends HTMLOutputter // lawsuit * @return boolean is read only action? */ - function isReadOnly($args)($args) + function isReadOnly($args) { return false; } -- cgit v1.2.3-54-g00ecf From cd9a24798001cfa5e6ecfbfbccc5c0ce07726846 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 13 Apr 2009 15:03:34 -0700 Subject: Fix bad dates in API's JSON search results --- lib/jsonsearchresultslist.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/jsonsearchresultslist.php b/lib/jsonsearchresultslist.php index 0cdcf0c51..f786c20a8 100644 --- a/lib/jsonsearchresultslist.php +++ b/lib/jsonsearchresultslist.php @@ -232,7 +232,7 @@ class ResultItem $this->profile_image_url = ($avatar) ? $avatar->displayUrl() : Avatar::defaultImage(AVATAR_STREAM_SIZE); - $this->created_at = date('r', $this->notice->created); + $this->created_at = common_date_rfc2822($this->notice->created); } /** -- cgit v1.2.3-54-g00ecf From ff7d71181038ba1e97e9bbcaa7901638aa715574 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 15 Apr 2009 10:05:16 -0400 Subject: add user id to statistics --- lib/profileaction.php | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'lib') diff --git a/lib/profileaction.php b/lib/profileaction.php index c81924e31..1f2e30994 100644 --- a/lib/profileaction.php +++ b/lib/profileaction.php @@ -179,6 +179,11 @@ class ProfileAction extends Action $this->element('h2', null, _('Statistics')); // Other stats...? + $this->elementStart('dl', 'entity_user-id'); + $this->element('dt', null, _('User ID')); + $this->element('dd', null, $this->profile->id); + $this->elementEnd('dl'); + $this->elementStart('dl', 'entity_member-since'); $this->element('dt', null, _('Member since')); $this->element('dd', null, date('j M Y', -- cgit v1.2.3-54-g00ecf From ed0556971661de1b8748882f48c316afac20b8be Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Thu, 16 Apr 2009 17:58:52 +0000 Subject: Add an even (hook): StartPersonalGroupNav. --- lib/personalgroupnav.php | 68 +++++++++++++++++++++++++----------------------- 1 file changed, 35 insertions(+), 33 deletions(-) (limited to 'lib') diff --git a/lib/personalgroupnav.php b/lib/personalgroupnav.php index 63e6138df..acc033667 100644 --- a/lib/personalgroupnav.php +++ b/lib/personalgroupnav.php @@ -93,43 +93,45 @@ class PersonalGroupNav extends Widget $this->out->elementStart('ul', array('class' => 'nav')); - $this->out->menuItem(common_local_url('all', array('nickname' => - $nickname)), - _('Personal'), - sprintf(_('%s and friends'), (($user_profile && $user_profile->fullname) ? $user_profile->fullname : $nickname)), - $action == 'all', 'nav_timeline_personal'); - $this->out->menuItem(common_local_url('replies', array('nickname' => - $nickname)), - _('Replies'), - sprintf(_('Replies to %s'), (($user_profile && $user_profile->fullname) ? $user_profile->fullname : $nickname)), - $action == 'replies', 'nav_timeline_replies'); - $this->out->menuItem(common_local_url('showstream', array('nickname' => - $nickname)), - _('Profile'), - ($user_profile && $user_profile->fullname) ? $user_profile->fullname : $nickname, - $action == 'showstream', 'nav_profile'); - $this->out->menuItem(common_local_url('showfavorites', array('nickname' => - $nickname)), - _('Favorites'), - sprintf(_('%s\'s favorite notices'), ($user_profile) ? $user_profile->getBestName() : _('User')), - $action == 'showfavorites', 'nav_timeline_favorites'); + if (Event::handle('StartPersonalGroupNav', array($this))) { + $this->out->menuItem(common_local_url('all', array('nickname' => + $nickname)), + _('Personal'), + sprintf(_('%s and friends'), (($user_profile && $user_profile->fullname) ? $user_profile->fullname : $nickname)), + $action == 'all', 'nav_timeline_personal'); + $this->out->menuItem(common_local_url('replies', array('nickname' => + $nickname)), + _('Replies'), + sprintf(_('Replies to %s'), (($user_profile && $user_profile->fullname) ? $user_profile->fullname : $nickname)), + $action == 'replies', 'nav_timeline_replies'); + $this->out->menuItem(common_local_url('showstream', array('nickname' => + $nickname)), + _('Profile'), + ($user_profile && $user_profile->fullname) ? $user_profile->fullname : $nickname, + $action == 'showstream', 'nav_profile'); + $this->out->menuItem(common_local_url('showfavorites', array('nickname' => + $nickname)), + _('Favorites'), + sprintf(_('%s\'s favorite notices'), ($user_profile) ? $user_profile->getBestName() : _('User')), + $action == 'showfavorites', 'nav_timeline_favorites'); - $cur = common_current_user(); + $cur = common_current_user(); - if ($cur && $cur->id == $user->id) { + if ($cur && $cur->id == $user->id) { - $this->out->menuItem(common_local_url('inbox', array('nickname' => - $nickname)), - _('Inbox'), - _('Your incoming messages'), - $action == 'inbox'); - $this->out->menuItem(common_local_url('outbox', array('nickname' => - $nickname)), - _('Outbox'), - _('Your sent messages'), - $action == 'outbox'); + $this->out->menuItem(common_local_url('inbox', array('nickname' => + $nickname)), + _('Inbox'), + _('Your incoming messages'), + $action == 'inbox'); + $this->out->menuItem(common_local_url('outbox', array('nickname' => + $nickname)), + _('Outbox'), + _('Your sent messages'), + $action == 'outbox'); + } + Event::handle('EndPersonalGroupNav', array($this)); } - $this->out->elementEnd('ul'); } } -- cgit v1.2.3-54-g00ecf From 4d0e4f733bdfa281487f370b70f5f7440a7ef931 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 16 Apr 2009 14:40:57 -0700 Subject: Make API dates more compatible with Twitter - ticket 1432 --- lib/twitterapi.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/twitterapi.php b/lib/twitterapi.php index b8357c688..6a90b4e28 100644 --- a/lib/twitterapi.php +++ b/lib/twitterapi.php @@ -418,7 +418,7 @@ class TwitterapiAction extends Action function date_twitter($dt) { $t = strtotime($dt); - return date("D M d G:i:s O Y", $t); + return date("D M d H:i:s O Y", $t); } // XXX: Candidate for a general utility method somewhere? -- cgit v1.2.3-54-g00ecf From 21873b806d6c5cf3e55ea10e49959c944f708688 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Fri, 17 Apr 2009 16:46:49 +0000 Subject: cosmetic fixes. --- lib/searchaction.php | 2 +- lib/tagcloudsection.php | 124 ------------------------------------------------ lib/util.php | 3 +- 3 files changed, 3 insertions(+), 126 deletions(-) delete mode 100644 lib/tagcloudsection.php (limited to 'lib') diff --git a/lib/searchaction.php b/lib/searchaction.php index e74450e11..e7ad4affd 100644 --- a/lib/searchaction.php +++ b/lib/searchaction.php @@ -51,7 +51,7 @@ class SearchAction extends Action * * @return boolean true */ - function isReadOnly($args) + function isReadOnly() { return true; } diff --git a/lib/tagcloudsection.php b/lib/tagcloudsection.php deleted file mode 100644 index ff2aca6d6..000000000 --- a/lib/tagcloudsection.php +++ /dev/null @@ -1,124 +0,0 @@ -. - * - * @category Widget - * @package Laconica - * @author Evan Prodromou - * @copyright 2009 Control Yourself, Inc. - * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 - * @link http://laconi.ca/ - */ - -if (!defined('LACONICA')) { - exit(1); -} - -define('TAGS_PER_SECTION', 20); - -/** - * Base class for sections - * - * These are the widgets that show interesting data about a person - * group, or site. - * - * @category Widget - * @package Laconica - * @author Evan Prodromou - * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 - * @link http://laconi.ca/ - */ - -class TagCloudSection extends Section -{ - function showContent() - { - $tags = $this->getTags(); - - if (!$tags) { - $this->out->element('p', null, _('None')); - return false; - } - - $cnt = 0; - - $tw = array(); - $sum = 0; - - while ($tags->fetch() && ++$cnt <= TAGS_PER_SECTION) { - $tw[$tags->tag] = $tags->weight; - $sum += $tags->weight; - } - - if ($cnt == 0) { - $this->out->element('p', null, _('(None)')); - return false; - } - - ksort($tw); - - $this->out->elementStart('ul', 'tags xoxo tag-cloud'); - foreach ($tw as $tag => $weight) { - $this->showTag($tag, $weight, ($sum == 0) ? 0 : $weight/$sum); - } - $this->out->elementEnd('ul'); - - return ($cnt > TAGS_PER_SECTION); - } - - function getTags() - { - return null; - } - - function showTag($tag, $weight, $relative) - { - if ($relative > 0.1) { - $rel = 'tag-cloud-7'; - } else if ($relative > 0.05) { - $rel = 'tag-cloud-6'; - } else if ($relative > 0.02) { - $rel = 'tag-cloud-5'; - } else if ($relative > 0.01) { - $rel = 'tag-cloud-4'; - } else if ($relative > 0.005) { - $rel = 'tag-cloud-3'; - } else if ($relative > 0.002) { - $rel = 'tag-cloud-2'; - } else { - $rel = 'tag-cloud-1'; - } - - $this->out->elementStart('li', $rel); - $this->out->element('a', array('href' => $this->tagUrl($tag)), - $tag); - $this->out->elementEnd('li'); - } - - function tagUrl($tag) - { - return common_local_url('tag', array('tag' => $tag)); - } - - function divId() - { - return 'tagcloud'; - } -} diff --git a/lib/util.php b/lib/util.php index 675ff51f0..5d16e39b5 100644 --- a/lib/util.php +++ b/lib/util.php @@ -1333,4 +1333,5 @@ function common_database_tablename($tablename) } //table prefixes could be added here later return $tablename; -} \ No newline at end of file +} + -- cgit v1.2.3-54-g00ecf From c024ee935a638d2daf3d54374564a1956916857b Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Fri, 17 Apr 2009 17:23:12 +0000 Subject: file was removed by mistake. --- lib/tagcloudsection.php | 142 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 lib/tagcloudsection.php (limited to 'lib') diff --git a/lib/tagcloudsection.php b/lib/tagcloudsection.php new file mode 100644 index 000000000..f5c305c65 --- /dev/null +++ b/lib/tagcloudsection.php @@ -0,0 +1,142 @@ +. + * + * @category Widget + * @package Laconica + * @author Evan Prodromou + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +define('TAGS_PER_SECTION', 20); + +/** + * Base class for sections + * + * These are the widgets that show interesting data about a person + * group, or site. + * + * @category Widget + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +class TagCloudSection extends Section +{ + function showContent() + { + $tags = $this->getAllTags(); + + if (!$tags) { + $this->out->element('p', null, _('None')); + return false; + } + + $cnt = count($tags); + + if ($cnt == 0) { + $this->out->element('p', null, _('(None)')); + return false; + } + + ksort($tags); + + $this->out->elementStart('ul', 'tags xoxo tag-cloud'); + foreach ($tags as $tag => $weight) { + $this->showTag($tag, $weight, ($sum == 0) ? 0 : $weight/$sum); + } + $this->out->elementEnd('ul'); + + return ($cnt > TAGS_PER_SECTION); + } + + function getTags($lst, $usr) + { + $profile_tag = new Profile_tag; + $profile_tag->selectAdd(); + $profile_tag->selectAdd('tag'); + $profile_tag->selectAdd('count(tag) as weight'); + $profile_tag->groupBy('tag'); + $profile_tag->orderBy('weight DESC'); + $cnt = $profile_tag->find(); + + $profile_tag->query(" +SELECT tag, count(tag) as weight from profile_tag, (SELECT subscriber, subscribed from subscription where subscriber=$usr and subscribed != subscriber) as t where tagger=subscriber and tagged=subscribed group by tag order by weight dest"); + + $tags = array(); + while ($profile_tag->fetch()) { +// var_dump($profile_tag); + $tags[$profile_tag->tag] = $profile_tag->weight; + } + $profile_tag->free(); + if (0) { + echo 'tags:
';
+            var_dump($tags);
+            echo '
'; + } + return $tags; + } + + function getAllTags() { + return null; + } + + function showTag($tag, $weight, $relative) + { + if ($relative > 0.1) { + $rel = 'tag-cloud-7'; + } else if ($relative > 0.05) { + $rel = 'tag-cloud-6'; + } else if ($relative > 0.02) { + $rel = 'tag-cloud-5'; + } else if ($relative > 0.01) { + $rel = 'tag-cloud-4'; + } else if ($relative > 0.005) { + $rel = 'tag-cloud-3'; + } else if ($relative > 0.002) { + $rel = 'tag-cloud-2'; + } else { + $rel = 'tag-cloud-1'; + } + + $this->out->elementStart('li', $rel); + $this->out->element('a', array('href' => $this->tagUrl($tag)), + $tag); + $this->out->elementEnd('li'); + } + + function tagUrl($tag) + { + return common_local_url('tag', array('tag' => $tag)); + } + + function divId() + { + return 'tagcloud'; + } +} -- cgit v1.2.3-54-g00ecf From 2e06d5a2cb0d05d944bd0f969dbf5a0b10a1d48e Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Fri, 17 Apr 2009 17:24:41 +0000 Subject: file was removed by mistake. --- lib/tagcloudsection.php | 142 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 lib/tagcloudsection.php (limited to 'lib') diff --git a/lib/tagcloudsection.php b/lib/tagcloudsection.php new file mode 100644 index 000000000..f5c305c65 --- /dev/null +++ b/lib/tagcloudsection.php @@ -0,0 +1,142 @@ +. + * + * @category Widget + * @package Laconica + * @author Evan Prodromou + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +define('TAGS_PER_SECTION', 20); + +/** + * Base class for sections + * + * These are the widgets that show interesting data about a person + * group, or site. + * + * @category Widget + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +class TagCloudSection extends Section +{ + function showContent() + { + $tags = $this->getAllTags(); + + if (!$tags) { + $this->out->element('p', null, _('None')); + return false; + } + + $cnt = count($tags); + + if ($cnt == 0) { + $this->out->element('p', null, _('(None)')); + return false; + } + + ksort($tags); + + $this->out->elementStart('ul', 'tags xoxo tag-cloud'); + foreach ($tags as $tag => $weight) { + $this->showTag($tag, $weight, ($sum == 0) ? 0 : $weight/$sum); + } + $this->out->elementEnd('ul'); + + return ($cnt > TAGS_PER_SECTION); + } + + function getTags($lst, $usr) + { + $profile_tag = new Profile_tag; + $profile_tag->selectAdd(); + $profile_tag->selectAdd('tag'); + $profile_tag->selectAdd('count(tag) as weight'); + $profile_tag->groupBy('tag'); + $profile_tag->orderBy('weight DESC'); + $cnt = $profile_tag->find(); + + $profile_tag->query(" +SELECT tag, count(tag) as weight from profile_tag, (SELECT subscriber, subscribed from subscription where subscriber=$usr and subscribed != subscriber) as t where tagger=subscriber and tagged=subscribed group by tag order by weight dest"); + + $tags = array(); + while ($profile_tag->fetch()) { +// var_dump($profile_tag); + $tags[$profile_tag->tag] = $profile_tag->weight; + } + $profile_tag->free(); + if (0) { + echo 'tags:
';
+            var_dump($tags);
+            echo '
'; + } + return $tags; + } + + function getAllTags() { + return null; + } + + function showTag($tag, $weight, $relative) + { + if ($relative > 0.1) { + $rel = 'tag-cloud-7'; + } else if ($relative > 0.05) { + $rel = 'tag-cloud-6'; + } else if ($relative > 0.02) { + $rel = 'tag-cloud-5'; + } else if ($relative > 0.01) { + $rel = 'tag-cloud-4'; + } else if ($relative > 0.005) { + $rel = 'tag-cloud-3'; + } else if ($relative > 0.002) { + $rel = 'tag-cloud-2'; + } else { + $rel = 'tag-cloud-1'; + } + + $this->out->elementStart('li', $rel); + $this->out->element('a', array('href' => $this->tagUrl($tag)), + $tag); + $this->out->elementEnd('li'); + } + + function tagUrl($tag) + { + return common_local_url('tag', array('tag' => $tag)); + } + + function divId() + { + return 'tagcloud'; + } +} -- cgit v1.2.3-54-g00ecf From 2873940265611d6556eaee7a01dd53587d7ef446 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Fri, 17 Apr 2009 17:31:22 +0000 Subject: Fixed file that was removed by mistake. --- lib/tagcloudsection.php | 44 +++++++++++++------------------------------- 1 file changed, 13 insertions(+), 31 deletions(-) (limited to 'lib') diff --git a/lib/tagcloudsection.php b/lib/tagcloudsection.php index f5c305c65..ff2aca6d6 100644 --- a/lib/tagcloudsection.php +++ b/lib/tagcloudsection.php @@ -50,24 +50,32 @@ class TagCloudSection extends Section { function showContent() { - $tags = $this->getAllTags(); + $tags = $this->getTags(); if (!$tags) { $this->out->element('p', null, _('None')); return false; } - $cnt = count($tags); + $cnt = 0; + + $tw = array(); + $sum = 0; + + while ($tags->fetch() && ++$cnt <= TAGS_PER_SECTION) { + $tw[$tags->tag] = $tags->weight; + $sum += $tags->weight; + } if ($cnt == 0) { $this->out->element('p', null, _('(None)')); return false; } - ksort($tags); + ksort($tw); $this->out->elementStart('ul', 'tags xoxo tag-cloud'); - foreach ($tags as $tag => $weight) { + foreach ($tw as $tag => $weight) { $this->showTag($tag, $weight, ($sum == 0) ? 0 : $weight/$sum); } $this->out->elementEnd('ul'); @@ -75,34 +83,8 @@ class TagCloudSection extends Section return ($cnt > TAGS_PER_SECTION); } - function getTags($lst, $usr) + function getTags() { - $profile_tag = new Profile_tag; - $profile_tag->selectAdd(); - $profile_tag->selectAdd('tag'); - $profile_tag->selectAdd('count(tag) as weight'); - $profile_tag->groupBy('tag'); - $profile_tag->orderBy('weight DESC'); - $cnt = $profile_tag->find(); - - $profile_tag->query(" -SELECT tag, count(tag) as weight from profile_tag, (SELECT subscriber, subscribed from subscription where subscriber=$usr and subscribed != subscriber) as t where tagger=subscriber and tagged=subscribed group by tag order by weight dest"); - - $tags = array(); - while ($profile_tag->fetch()) { -// var_dump($profile_tag); - $tags[$profile_tag->tag] = $profile_tag->weight; - } - $profile_tag->free(); - if (0) { - echo 'tags:
';
-            var_dump($tags);
-            echo '
'; - } - return $tags; - } - - function getAllTags() { return null; } -- cgit v1.2.3-54-g00ecf From cb645558a511e0f4a03923a988bda78ceae5ff0d Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Fri, 17 Apr 2009 17:35:51 +0000 Subject: Fixed file that was removed by mistake. --- lib/tagcloudsection.php | 44 +++++++++++++------------------------------- 1 file changed, 13 insertions(+), 31 deletions(-) (limited to 'lib') diff --git a/lib/tagcloudsection.php b/lib/tagcloudsection.php index f5c305c65..ff2aca6d6 100644 --- a/lib/tagcloudsection.php +++ b/lib/tagcloudsection.php @@ -50,24 +50,32 @@ class TagCloudSection extends Section { function showContent() { - $tags = $this->getAllTags(); + $tags = $this->getTags(); if (!$tags) { $this->out->element('p', null, _('None')); return false; } - $cnt = count($tags); + $cnt = 0; + + $tw = array(); + $sum = 0; + + while ($tags->fetch() && ++$cnt <= TAGS_PER_SECTION) { + $tw[$tags->tag] = $tags->weight; + $sum += $tags->weight; + } if ($cnt == 0) { $this->out->element('p', null, _('(None)')); return false; } - ksort($tags); + ksort($tw); $this->out->elementStart('ul', 'tags xoxo tag-cloud'); - foreach ($tags as $tag => $weight) { + foreach ($tw as $tag => $weight) { $this->showTag($tag, $weight, ($sum == 0) ? 0 : $weight/$sum); } $this->out->elementEnd('ul'); @@ -75,34 +83,8 @@ class TagCloudSection extends Section return ($cnt > TAGS_PER_SECTION); } - function getTags($lst, $usr) + function getTags() { - $profile_tag = new Profile_tag; - $profile_tag->selectAdd(); - $profile_tag->selectAdd('tag'); - $profile_tag->selectAdd('count(tag) as weight'); - $profile_tag->groupBy('tag'); - $profile_tag->orderBy('weight DESC'); - $cnt = $profile_tag->find(); - - $profile_tag->query(" -SELECT tag, count(tag) as weight from profile_tag, (SELECT subscriber, subscribed from subscription where subscriber=$usr and subscribed != subscriber) as t where tagger=subscriber and tagged=subscribed group by tag order by weight dest"); - - $tags = array(); - while ($profile_tag->fetch()) { -// var_dump($profile_tag); - $tags[$profile_tag->tag] = $profile_tag->weight; - } - $profile_tag->free(); - if (0) { - echo 'tags:
';
-            var_dump($tags);
-            echo '
'; - } - return $tags; - } - - function getAllTags() { return null; } -- cgit v1.2.3-54-g00ecf From 7196410bb0398c15fbab767a9b7cedc513e6520b Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Sat, 18 Apr 2009 19:00:20 +0200 Subject: shortening links in notices from XMPP This patch enables shortening of links, that where send from XMPP. The problem was, that in util.php common_current_user() is not finding the user account from which is posted, so the service to shorten is not known, so no shortening at all... This patch cleans up the xmppdaemon a little bit and hard codes ur1.ca as shortening service _if_ the user is not set. Ugly but working. --- lib/util.php | 20 ++++++-------------- scripts/xmppdaemon.php | 17 +++++------------ 2 files changed, 11 insertions(+), 26 deletions(-) (limited to 'lib') diff --git a/lib/util.php b/lib/util.php index 675ff51f0..ab5e99593 100644 --- a/lib/util.php +++ b/lib/util.php @@ -519,11 +519,16 @@ function common_shorten_links($text) function common_shorten_link($url, $reverse = false) { + static $url_cache = array(); if ($reverse) return isset($url_cache[$url]) ? $url_cache[$url] : $url; $user = common_current_user(); - + if (!isset($user)) { + // common current user does not find a user when called from the XMPP daemon + // therefore we'll set one here fix, so that XMPP given URLs may be shortened + $user->urlshorteningservice = 'ur1.ca'; + } $curlh = curl_init(); curl_setopt($curlh, CURLOPT_CONNECTTIMEOUT, 20); // # seconds to wait curl_setopt($curlh, CURLOPT_USERAGENT, 'Laconica'); @@ -1321,16 +1326,3 @@ function common_compatible_license($from, $to) // XXX: better compatibility check needed here! return ($from == $to); } - -/** - * returns a quoted table name, if required according to config - */ -function common_database_tablename($tablename) -{ - - if(common_config('db','quote_identifiers')) { - $tablename = '"'. $tablename .'"'; - } - //table prefixes could be added here later - return $tablename; -} \ No newline at end of file diff --git a/scripts/xmppdaemon.php b/scripts/xmppdaemon.php index ef3f8c63d..5711f715d 100755 --- a/scripts/xmppdaemon.php +++ b/scripts/xmppdaemon.php @@ -152,11 +152,6 @@ class XMPPDaemon extends Daemon $body = preg_replace('/d[\ ]*('. $to .')[\ ]*/', '', $pl['body']); $this->add_direct($user, $body, $to, $from); } else { - $len = mb_strlen($pl['body']); - if($len > 140) { - $this->from_site($from, 'Message too long - maximum is 140 characters, you sent ' . $len); - return; - } $this->add_notice($user, $pl); } @@ -255,15 +250,13 @@ class XMPPDaemon extends Daemon function add_notice(&$user, &$pl) { $body = trim($pl['body']); - $content_shortened = common_shorten_link($body); + $content_shortened = common_shorten_links($body); if (mb_strlen($content_shortened) > 140) { - $content = trim(mb_substr($body, 0, 140)); - $content_shortened = common_shorten_link($content); - } - else { - $content = $body; + $from = jabber_normalize_jid($pl['from']); + $this->from_site($from, "Message too long - maximum is 140 characters, you sent ".mb_strlen($content_shortened)); + return; } - $notice = Notice::saveNew($user->id, $content, 'xmpp'); + $notice = Notice::saveNew($user->id, $content_shortened, 'xmpp'); if (is_string($notice)) { $this->log(LOG_ERR, $notice); return; -- cgit v1.2.3-54-g00ecf From 4b54a418f3f26b44defdb42b8168ae43f4d1c66c Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Sat, 18 Apr 2009 19:08:33 +0000 Subject: trac#1215, 1216, 1217 and 1219: subscribers/subscriptions people tagclouds --- actions/subscribers.php | 10 ++++ actions/subscriptions.php | 10 ++++ lib/subpeopletagcloudsection.php | 76 ++++++++++++++++++++++++++ lib/subscriberspeopleselftagcloudsection.php | 54 ++++++++++++++++++ lib/subscriberspeopletagcloudsection.php | 60 ++++++++++++++++++++ lib/subscriptionspeopleselftagcloudsection.php | 54 ++++++++++++++++++ lib/subscriptionspeopletagcloudsection.php | 59 ++++++++++++++++++++ 7 files changed, 323 insertions(+) create mode 100644 lib/subpeopletagcloudsection.php create mode 100644 lib/subscriberspeopleselftagcloudsection.php create mode 100644 lib/subscriberspeopletagcloudsection.php create mode 100644 lib/subscriptionspeopleselftagcloudsection.php create mode 100644 lib/subscriptionspeopletagcloudsection.php (limited to 'lib') diff --git a/actions/subscribers.php b/actions/subscribers.php index d91a7d4fd..4482de9a7 100644 --- a/actions/subscribers.php +++ b/actions/subscribers.php @@ -118,6 +118,16 @@ class SubscribersAction extends GalleryAction $this->raw(common_markup_to_html($message)); $this->elementEnd('div'); } + + function showSections() + { + parent::showSections(); + $cloud = new SubscribersPeopleTagCloudSection($this); + $cloud->show(); + + $cloud2 = new SubscribersPeopleSelfTagCloudSection($this); + $cloud2->show(); + } } class SubscribersList extends ProfileList diff --git a/actions/subscriptions.php b/actions/subscriptions.php index e6f3c54db..095b18ad8 100644 --- a/actions/subscriptions.php +++ b/actions/subscriptions.php @@ -125,6 +125,16 @@ class SubscriptionsAction extends GalleryAction $this->raw(common_markup_to_html($message)); $this->elementEnd('div'); } + + function showSections() + { + parent::showSections(); + $cloud = new SubscriptionsPeopleTagCloudSection($this); + $cloud->show(); + + $cloud2 = new SubscriptionsPeopleSelfTagCloudSection($this); + $cloud2->show(); + } } class SubscriptionsList extends ProfileList diff --git a/lib/subpeopletagcloudsection.php b/lib/subpeopletagcloudsection.php new file mode 100644 index 000000000..d98f28afa --- /dev/null +++ b/lib/subpeopletagcloudsection.php @@ -0,0 +1,76 @@ +. + * + * @category Widget + * @package Laconica + * @author Evan Prodromou + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +/** + * Personal tag cloud section + * + * @category Widget + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +class SubPeopleTagCloudSection extends TagCloudSection +{ + function getTags() + { + $qry = $this->query(); + $limit = TAGS_PER_SECTION; + $offset = 0; + + if (common_config('db','type') == 'pgsql') { + $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset; + } else { + $qry .= ' LIMIT ' . $offset . ', ' . $limit; + } + + $profile_tag = Memcached_DataObject::cachedQuery('Profile_tag', + sprintf($qry, + $this->out->user->id)); + return $profile_tag; + } + + function tagUrl($tag) { + return common_local_url('peopletag', array('tag' => $tag)); + } + + function showTag($tag, $weight, $relative) { + $rel = 'tag-cloud-'; + $rel .= 1+intval(7 * $relative * $weight - 0.01); + + $this->out->elementStart('li', $rel); + $this->out->element('a', array('href' => $this->tagUrl($tag)), $tag); + $this->out->elementEnd('li'); + } +} diff --git a/lib/subscriberspeopleselftagcloudsection.php b/lib/subscriberspeopleselftagcloudsection.php new file mode 100644 index 000000000..b5a39c6de --- /dev/null +++ b/lib/subscriberspeopleselftagcloudsection.php @@ -0,0 +1,54 @@ +. + * + * @category Widget + * @package Laconica + * @author Evan Prodromou + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +/** + * Personal tag cloud section + * + * @category Widget + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +class SubscribersPeopleSelfTagCloudSection extends SubPeopleTagCloudSection +{ + function title() + { + return _('People Tagcloud as self-tagged'); + } + + function query() { + return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscriber where subscribed=%d and subscribed != subscriber and tagger = tagged group by tag order by weight desc'; + } +} diff --git a/lib/subscriberspeopletagcloudsection.php b/lib/subscriberspeopletagcloudsection.php new file mode 100644 index 000000000..23011efdd --- /dev/null +++ b/lib/subscriberspeopletagcloudsection.php @@ -0,0 +1,60 @@ +. + * + * @category Widget + * @package Laconica + * @author Evan Prodromou + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +/** + * Personal tag cloud section + * + * @category Widget + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +class SubscribersPeopleTagCloudSection extends SubPeopleTagCloudSection +{ + function title() + { + return _('People Tagcloud as tagged'); + } + + function tagUrl($tag) { + $nickname = $this->out->profile->nickname; + return common_local_url('subscribers', array('nickname' => $nickname, 'tag' => $tag)); + } + + + function query() { + return 'select tag, count(tag) as weight from subscription left join profile_tag on subscriber=tagged and subscribed=tagger where subscribed=%d and subscriber != subscribed group by tag order by weight desc'; + } +} diff --git a/lib/subscriptionspeopleselftagcloudsection.php b/lib/subscriptionspeopleselftagcloudsection.php new file mode 100644 index 000000000..8ac65adb0 --- /dev/null +++ b/lib/subscriptionspeopleselftagcloudsection.php @@ -0,0 +1,54 @@ +. + * + * @category Widget + * @package Laconica + * @author Evan Prodromou + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +/** + * Personal tag cloud section + * + * @category Widget + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +class SubscriptionsPeopleSelfTagCloudSection extends SubPeopleTagCloudSection +{ + function title() + { + return _('People Tagcloud as self-tagged'); + } + + function query() { + return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscriber where subscribed=%d and subscriber != subscribed and tagger = tagged group by tag order by weight desc'; + } +} diff --git a/lib/subscriptionspeopletagcloudsection.php b/lib/subscriptionspeopletagcloudsection.php new file mode 100644 index 000000000..c3f7d1763 --- /dev/null +++ b/lib/subscriptionspeopletagcloudsection.php @@ -0,0 +1,59 @@ +. + * + * @category Widget + * @package Laconica + * @author Evan Prodromou + * @copyright 2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +/** + * Personal tag cloud section + * + * @category Widget + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +class SubscriptionsPeopleTagCloudSection extends SubPeopleTagCloudSection +{ + function title() + { + return _('People Tagcloud as tagged'); + } + + function tagUrl($tag) { + $nickname = $this->out->profile->nickname; + return common_local_url('subscriptions', array('nickname' => $nickname, 'tag' => $tag)); + } + + function query() { + return 'select tag, count(tag) as weight from subscription left join profile_tag on subscriber=tagger and subscribed=tagged where subscriber=%d and subscriber != subscribed group by tag order by weight desc'; + } +} -- cgit v1.2.3-54-g00ecf From 90fb7be99a74689de0d0e2409230d8bd515ac5c3 Mon Sep 17 00:00:00 2001 From: Dan Moore Date: Sat, 18 Apr 2009 15:33:36 -0400 Subject: Bringing the presentation of boolean variables (favorited, truncated, profile_background_tile) and the result from friendships/exist in JSON results from the Twitter Compatible API in line with what the real Twitter API does. Currently, laconica returns text strings enclosed in quotes instead of bare Javascript booleans. This change fixes that. See http://laconi.ca/trac/ticket/1326 for one open issue related to this. --- actions/twitapifriendships.php | 6 +----- actions/twitapiusers.php | 2 +- lib/twitterapi.php | 29 ++++++++++++++++++++++++----- 3 files changed, 26 insertions(+), 11 deletions(-) (limited to 'lib') diff --git a/actions/twitapifriendships.php b/actions/twitapifriendships.php index c50c5e84a..2f8250e0d 100644 --- a/actions/twitapifriendships.php +++ b/actions/twitapifriendships.php @@ -133,11 +133,7 @@ class TwitapifriendshipsAction extends TwitterapiAction return; } - if ($user_a->isSubscribed($user_b)) { - $result = 'true'; - } else { - $result = 'false'; - } + $result = $user_a->isSubscribed($user_b); switch ($apidata['content-type']) { case 'xml': diff --git a/actions/twitapiusers.php b/actions/twitapiusers.php index 2894b7486..41d0d955b 100644 --- a/actions/twitapiusers.php +++ b/actions/twitapiusers.php @@ -83,7 +83,7 @@ class TwitapiusersAction extends TwitterapiAction $twitter_user['profile_link_color'] = ''; $twitter_user['profile_sidebar_fill_color'] = ''; $twitter_user['profile_sidebar_border_color'] = ''; - $twitter_user['profile_background_tile'] = 'false'; + $twitter_user['profile_background_tile'] = false; $faves = DB_DataObject::factory('fave'); $faves->user_id = $user->id; diff --git a/lib/twitterapi.php b/lib/twitterapi.php index 6a90b4e28..caf8c0716 100644 --- a/lib/twitterapi.php +++ b/lib/twitterapi.php @@ -51,6 +51,26 @@ class TwitterapiAction extends Action parent::handle($args); } + /** + * Overrides XMLOutputter::element to write booleans as strings (true|false). + * See that method's documentation for more info. + * + * @param string $tag Element type or tagname + * @param array $attrs Array of element attributes, as + * key-value pairs + * @param string $content string content of the element + * + * @return void + */ + function element($tag, $attrs=null, $content=null) + { + if (is_bool($content)) { + $content = ($content ? 'true' : 'false'); + } + + return parent::element($tag, $attrs, $content); + } + function twitter_user_array($profile, $get_notice=false) { @@ -66,7 +86,7 @@ class TwitterapiAction extends Action $avatar = $profile->getAvatar(AVATAR_STREAM_SIZE); $twitter_user['profile_image_url'] = ($avatar) ? $avatar->displayUrl() : Avatar::defaultImage(AVATAR_STREAM_SIZE); - $twitter_user['protected'] = 'false'; # not supported by Laconica yet + $twitter_user['protected'] = false; # not supported by Laconica yet $twitter_user['url'] = ($profile->homepage) ? $profile->homepage : null; if ($get_notice) { @@ -86,7 +106,7 @@ class TwitterapiAction extends Action $twitter_status = array(); $twitter_status['text'] = $notice->content; - $twitter_status['truncated'] = 'false'; # Not possible on Laconica + $twitter_status['truncated'] = false; # Not possible on Laconica $twitter_status['created_at'] = $this->date_twitter($notice->created); $twitter_status['in_reply_to_status_id'] = ($notice->reply_to) ? intval($notice->reply_to) : null; @@ -108,10 +128,9 @@ class TwitterapiAction extends Action ($replier_profile) ? $replier_profile->nickname : null; if (isset($this->auth_user)) { - $twitter_status['favorited'] = - ($this->auth_user->hasFave($notice)) ? 'true' : 'false'; + $twitter_status['favorited'] = $this->auth_user->hasFave($notice); } else { - $twitter_status['favorited'] = 'false'; + $twitter_status['favorited'] = false; } if ($include_user) { -- cgit v1.2.3-54-g00ecf From ec5e06a542d6b06ea9b1d3de7cb309dd1088b4d4 Mon Sep 17 00:00:00 2001 From: CiaranG Date: Tue, 21 Apr 2009 23:36:15 +0100 Subject: Suppress errors when checking for the existence of files that might be restricted by open_basedir - should resolve issue #1310 --- lib/common.php | 2 +- lib/util.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/common.php b/lib/common.php index b3882d207..f983c4d16 100644 --- a/lib/common.php +++ b/lib/common.php @@ -192,7 +192,7 @@ $_config_files[] = INSTALLDIR.'/config.php'; $_have_a_config = false; foreach ($_config_files as $_config_file) { - if (file_exists($_config_file)) { + if (@file_exists($_config_file)) { include_once($_config_file); $_have_a_config = true; } diff --git a/lib/util.php b/lib/util.php index e0eda0114..e1dd238ba 100644 --- a/lib/util.php +++ b/lib/util.php @@ -966,7 +966,7 @@ function common_root_url($ssl=false) function common_good_rand($bytes) { // XXX: use random.org...? - if (file_exists('/dev/urandom')) { + if (@file_exists('/dev/urandom')) { return common_urandom($bytes); } else { // FIXME: this is probably not good enough return common_mtrand($bytes); -- cgit v1.2.3-54-g00ecf From 640628de2d593933e810b4785dfe38923b979713 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 23 Apr 2009 05:03:19 -0400 Subject: A queuehandler for blowing caches offline We add a queuehandler for blowing the memcached caches off-line. This should speed up the processing of new notices. --- classes/Notice.php | 25 ++++++++++++++++- lib/util.php | 14 ++++++++-- scripts/memcachedqueuehandler.php | 58 +++++++++++++++++++++++++++++++++++++++ scripts/startdaemons.sh | 3 +- scripts/stopdaemons.sh | 2 +- 5 files changed, 97 insertions(+), 5 deletions(-) create mode 100644 scripts/memcachedqueuehandler.php (limited to 'lib') diff --git a/classes/Notice.php b/classes/Notice.php index 5fa0d79a1..fbfeb9489 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -207,7 +207,11 @@ class Notice extends Memcached_DataObject # XXX: someone clever could prepend instead of clearing the cache if (common_config('memcached', 'enabled')) { - $notice->blowCaches(); + if (common_config('queues', 'enabled')) { + $notice->blowAuthorCaches(); + } else { + $notice->blowCaches(); + } } return $notice; @@ -271,6 +275,25 @@ class Notice extends Memcached_DataObject $this->blowGroupCache($blowLast); } + function blowAuthorCaches($blowLast=false) + { + // Clear the user's cache + $cache = common_memcache(); + if ($cache) { + $user = User::staticGet($this->profile_id); + if (!empty($user)) { + $cache->delete(common_cache_key('user:notices_with_friends:' . $user->id)); + if ($blowLast) { + $cache->delete(common_cache_key('user:notices_with_friends:' . $user->id . ';last')); + } + } + $user->free(); + unset($user); + } + $this->blowNoticeCache($blowLast); + $this->blowPublicCache($blowLast); + } + function blowGroupCache($blowLast=false) { $cache = common_memcache(); diff --git a/lib/util.php b/lib/util.php index e0eda0114..12797891c 100644 --- a/lib/util.php +++ b/lib/util.php @@ -879,7 +879,17 @@ function common_broadcast_notice($notice, $remote=false) function common_enqueue_notice($notice) { - foreach (array('jabber', 'omb', 'sms', 'public', 'twitter', 'facebook', 'ping') as $transport) { + $transports = array('omb', 'sms', 'twitter', 'facebook', 'ping'); + + if (common_config('xmpp', 'enabled')) { + $transports = array_merge($transports, array('jabber', 'public')); + } + + if (common_config('memcached', 'enabled')) { + $transports[] = 'memcached'; + } + + foreach ($transports as $transport) { $qi = new Queue_item(); $qi->notice_id = $notice->id; $qi->transport = $transport; @@ -1332,7 +1342,7 @@ function common_compatible_license($from, $to) */ function common_database_tablename($tablename) { - + if(common_config('db','quote_identifiers')) { $tablename = '"'. $tablename .'"'; } diff --git a/scripts/memcachedqueuehandler.php b/scripts/memcachedqueuehandler.php new file mode 100644 index 000000000..3fcebcfc3 --- /dev/null +++ b/scripts/memcachedqueuehandler.php @@ -0,0 +1,58 @@ +#!/usr/bin/env php +. + */ + +// Abort if called from a web server + +if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { + print "This script must be run from the command line\n"; + exit(); +} + +define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); +define('LACONICA', true); + +require_once(INSTALLDIR . '/lib/common.php'); + +set_error_handler('common_error_handler'); + +class MemcachedQueueHandler extends QueueHandler +{ + function transport() + { + return 'memcached'; + } + + function handle_notice($notice) + { + // XXX: fork here + common_log(LOG_INFO, "Blowing memcached for $notice->id\n"; + $notice->blowCaches(); + return true; + } +} + +ini_set("max_execution_time", "0"); +ini_set("max_input_time", "0"); +set_time_limit(0); +mb_internal_encoding('UTF-8'); + +$handler = new MemcachedQueueHandler($resource); + +$handler->runOnce(); diff --git a/scripts/startdaemons.sh b/scripts/startdaemons.sh index c3729761d..08de6d954 100755 --- a/scripts/startdaemons.sh +++ b/scripts/startdaemons.sh @@ -24,7 +24,8 @@ DIR=`dirname $0` for f in xmppdaemon.php jabberqueuehandler.php publicqueuehandler.php \ xmppconfirmhandler.php smsqueuehandler.php ombqueuehandler.php \ - twitterqueuehandler.php facebookqueuehandler.php pingqueuehandler.php; do + twitterqueuehandler.php facebookqueuehandler.php pingqueuehandler.php \ + memcachedqueuehandler.php; do echo -n "Starting $f..."; php $DIR/$f diff --git a/scripts/stopdaemons.sh b/scripts/stopdaemons.sh index 2bb8f9ecb..e5a181cd1 100755 --- a/scripts/stopdaemons.sh +++ b/scripts/stopdaemons.sh @@ -24,7 +24,7 @@ SDIR=`dirname $0` DIR=`php $SDIR/getpiddir.php` for f in jabberhandler ombhandler publichandler smshandler pinghandler \ - xmppconfirmhandler xmppdaemon twitterhandler facebookhandler ; do + xmppconfirmhandler xmppdaemon twitterhandler facebookhandler memcachedhandler; do FILES="$DIR/$f.*.pid" for ff in "$FILES" ; do -- cgit v1.2.3-54-g00ecf From aee45ea91dcec4736d8b9befe17e030b873d9226 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 23 Apr 2009 05:08:48 -0400 Subject: Add an inbox queue handler Handle distributing a notice to multiple inboxes in a queue handler rather than in the Web action. --- classes/Notice.php | 5 +++- lib/util.php | 4 +++ scripts/inboxqueuehandler.php | 57 +++++++++++++++++++++++++++++++++++++++++++ scripts/startdaemons.sh | 2 +- scripts/stopdaemons.sh | 3 ++- 5 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 scripts/inboxqueuehandler.php (limited to 'lib') diff --git a/classes/Notice.php b/classes/Notice.php index fbfeb9489..ff00f2a94 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -197,7 +197,10 @@ class Notice extends Memcached_DataObject $notice->saveTags(); $notice->saveGroups(); - $notice->addToInboxes(); + if (!common_config('queues', 'enabled')) { + $notice->addToInboxes(); + } + $notice->query('COMMIT'); Event::handle('EndNoticeSave', array($notice)); diff --git a/lib/util.php b/lib/util.php index 12797891c..9b6d2941a 100644 --- a/lib/util.php +++ b/lib/util.php @@ -889,6 +889,10 @@ function common_enqueue_notice($notice) $transports[] = 'memcached'; } + if (common_config('queues', 'enabled')) { + $transports[] = 'inbox'; + } + foreach ($transports as $transport) { $qi = new Queue_item(); $qi->notice_id = $notice->id; diff --git a/scripts/inboxqueuehandler.php b/scripts/inboxqueuehandler.php new file mode 100644 index 000000000..16e334b83 --- /dev/null +++ b/scripts/inboxqueuehandler.php @@ -0,0 +1,57 @@ +#!/usr/bin/env php +. + */ + +// Abort if called from a web server + +if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { + print "This script must be run from the command line\n"; + exit(); +} + +define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); +define('LACONICA', true); + +require_once(INSTALLDIR . '/lib/common.php'); + +set_error_handler('common_error_handler'); + +class InboxQueueHandler extends QueueHandler +{ + function transport() + { + return 'inbox'; + } + + function handle_notice($notice) + { + common_log(LOG_INFO, "Distributing notice to inboxes for $notice->id"); + $notice->addToInboxes(); + return true; + } +} + +ini_set("max_execution_time", "0"); +ini_set("max_input_time", "0"); +set_time_limit(0); +mb_internal_encoding('UTF-8'); + +$handler = new InboxQueueHandler($resource); + +$handler->runOnce(); diff --git a/scripts/startdaemons.sh b/scripts/startdaemons.sh index 08de6d954..66f9ed4e0 100755 --- a/scripts/startdaemons.sh +++ b/scripts/startdaemons.sh @@ -25,7 +25,7 @@ DIR=`dirname $0` for f in xmppdaemon.php jabberqueuehandler.php publicqueuehandler.php \ xmppconfirmhandler.php smsqueuehandler.php ombqueuehandler.php \ twitterqueuehandler.php facebookqueuehandler.php pingqueuehandler.php \ - memcachedqueuehandler.php; do + memcachedqueuehandler.php inboxqueuehandler.php; do echo -n "Starting $f..."; php $DIR/$f diff --git a/scripts/stopdaemons.sh b/scripts/stopdaemons.sh index e5a181cd1..196991de0 100755 --- a/scripts/stopdaemons.sh +++ b/scripts/stopdaemons.sh @@ -24,7 +24,8 @@ SDIR=`dirname $0` DIR=`php $SDIR/getpiddir.php` for f in jabberhandler ombhandler publichandler smshandler pinghandler \ - xmppconfirmhandler xmppdaemon twitterhandler facebookhandler memcachedhandler; do + xmppconfirmhandler xmppdaemon twitterhandler facebookhandler \ + memcachedhandler inboxhandler; do FILES="$DIR/$f.*.pid" for ff in "$FILES" ; do -- cgit v1.2.3-54-g00ecf From ece70bf326fa680ec7acdef00751e2bb71bceee1 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 23 Apr 2009 09:35:10 +0000 Subject: incorrect config setting for inboxes --- lib/util.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/util.php b/lib/util.php index af4db4f02..d77039b74 100644 --- a/lib/util.php +++ b/lib/util.php @@ -889,7 +889,8 @@ function common_enqueue_notice($notice) $transports[] = 'memcached'; } - if (common_config('queues', 'enabled')) { + if (common_config('inboxes', 'enabled') === true || + common_config('inboxes', 'enabled') === 'transitional') { $transports[] = 'inbox'; } -- cgit v1.2.3-54-g00ecf From 7c383dc1d46cae8abc6d1e5c7eb93ad7cdd91f63 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 23 Apr 2009 10:08:26 +0000 Subject: alert to what transport we're checking for --- lib/queuehandler.php | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'lib') diff --git a/lib/queuehandler.php b/lib/queuehandler.php index 9ce9e32b3..fde650d9e 100644 --- a/lib/queuehandler.php +++ b/lib/queuehandler.php @@ -36,7 +36,7 @@ class QueueHandler extends Daemon $this->set_id($id); } } - + function class_name() { return ucfirst($this->transport()) . 'Handler'; @@ -46,7 +46,7 @@ class QueueHandler extends Daemon { return strtolower($this->class_name().'.'.$this->get_id()); } - + function get_id() { return $this->_id; @@ -56,16 +56,16 @@ class QueueHandler extends Daemon { $this->_id = $id; } - + function transport() { return null; } - + function start() { } - + function finish() { } @@ -74,14 +74,14 @@ class QueueHandler extends Daemon { return true; } - + function run() { if (!$this->start()) { return false; } - $this->log(LOG_INFO, 'checking for queued notices'); $transport = $this->transport(); + $this->log(LOG_INFO, 'checking for queued notices for "' . $transport . '"'); do { $qi = Queue_item::top($transport); if ($qi) { @@ -113,7 +113,7 @@ class QueueHandler extends Daemon } else { $this->clear_old_claims(); $this->idle(5); - } + } } while (true); if (!$this->finish()) { return false; @@ -127,7 +127,7 @@ class QueueHandler extends Daemon sleep($timeout); } } - + function clear_old_claims() { $qi = new Queue_item(); @@ -137,10 +137,9 @@ class QueueHandler extends Daemon $qi->free(); unset($qi); } - + function log($level, $msg) { common_log($level, $this->class_name() . ' ('. $this->get_id() .'): '.$msg); } } - \ No newline at end of file -- cgit v1.2.3-54-g00ecf From 1c0d82de3bb7f75649a017a7d5632a6e070876c2 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 23 Apr 2009 10:09:08 +0000 Subject: 8-char limit on transports --- lib/util.php | 3 ++- scripts/memcachedqueuehandler.php | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/util.php b/lib/util.php index d77039b74..f862d7fcc 100644 --- a/lib/util.php +++ b/lib/util.php @@ -886,7 +886,8 @@ function common_enqueue_notice($notice) } if (common_config('memcached', 'enabled')) { - $transports[] = 'memcached'; + // Note: limited to 8 chars + $transports[] = 'memcache'; } if (common_config('inboxes', 'enabled') === true || diff --git a/scripts/memcachedqueuehandler.php b/scripts/memcachedqueuehandler.php index 6e819b41f..185b781f7 100755 --- a/scripts/memcachedqueuehandler.php +++ b/scripts/memcachedqueuehandler.php @@ -37,7 +37,7 @@ class MemcachedQueueHandler extends QueueHandler { function transport() { - return 'memcached'; + return 'memcache'; } function start() { -- cgit v1.2.3-54-g00ecf From c008c0d4a56ec265ba6e10d208f9954510296f12 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Fri, 24 Apr 2009 20:01:03 +0000 Subject: fixed trac#1215, 1216, 1217 and 1219: subscribers/subscriptions people tagclouds. --- lib/subpeopletagcloudsection.php | 1 + lib/subscriberspeopleselftagcloudsection.php | 10 +++++++++- lib/subscriberspeopletagcloudsection.php | 5 +++-- lib/subscriptionspeopleselftagcloudsection.php | 9 ++++++++- lib/subscriptionspeopletagcloudsection.php | 4 +++- 5 files changed, 24 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/subpeopletagcloudsection.php b/lib/subpeopletagcloudsection.php index d98f28afa..9f6948dc9 100644 --- a/lib/subpeopletagcloudsection.php +++ b/lib/subpeopletagcloudsection.php @@ -74,3 +74,4 @@ class SubPeopleTagCloudSection extends TagCloudSection $this->out->elementEnd('li'); } } + diff --git a/lib/subscriberspeopleselftagcloudsection.php b/lib/subscriberspeopleselftagcloudsection.php index b5a39c6de..115241a53 100644 --- a/lib/subscriberspeopleselftagcloudsection.php +++ b/lib/subscriberspeopleselftagcloudsection.php @@ -49,6 +49,14 @@ class SubscribersPeopleSelfTagCloudSection extends SubPeopleTagCloudSection } function query() { - return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscriber where subscribed=%d and subscribed != subscriber and tagger = tagged group by tag order by weight desc'; +// return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscriber where subscribed=%d and subscribed != subscriber and tagger = tagged group by tag order by weight desc'; + + + return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscriber where subscribed=%d and subscribed != subscriber and tagger = tagged and tag is not null group by tag order by weight desc'; + +// return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscribed where subscriber=%d and subscribed != subscriber and tagger = tagged and tag is not null group by tag order by weight desc'; + + } } + diff --git a/lib/subscriberspeopletagcloudsection.php b/lib/subscriberspeopletagcloudsection.php index 23011efdd..4dafbc1c7 100644 --- a/lib/subscriberspeopletagcloudsection.php +++ b/lib/subscriberspeopletagcloudsection.php @@ -53,8 +53,9 @@ class SubscribersPeopleTagCloudSection extends SubPeopleTagCloudSection return common_local_url('subscribers', array('nickname' => $nickname, 'tag' => $tag)); } - function query() { - return 'select tag, count(tag) as weight from subscription left join profile_tag on subscriber=tagged and subscribed=tagger where subscribed=%d and subscriber != subscribed group by tag order by weight desc'; +// return 'select tag, count(tag) as weight from subscription left join profile_tag on subscriber=tagged and subscribed=tagger where subscribed=%d and subscriber != subscribed group by tag order by weight desc'; + return 'select tag, count(tag) as weight from subscription left join profile_tag on subscriber=tagged and subscribed=tagger where subscribed=%d and subscriber != subscribed and tag is not null group by tag order by weight desc'; } } + diff --git a/lib/subscriptionspeopleselftagcloudsection.php b/lib/subscriptionspeopleselftagcloudsection.php index 8ac65adb0..3896294d2 100644 --- a/lib/subscriptionspeopleselftagcloudsection.php +++ b/lib/subscriptionspeopleselftagcloudsection.php @@ -49,6 +49,13 @@ class SubscriptionsPeopleSelfTagCloudSection extends SubPeopleTagCloudSection } function query() { - return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscriber where subscribed=%d and subscriber != subscribed and tagger = tagged group by tag order by weight desc'; +// return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscriber where subscribed=%d and subscriber != subscribed and tagger = tagged group by tag order by weight desc'; + + + + return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscribed where subscriber=%d and subscribed != subscriber and tagger = tagged and tag is not null group by tag order by weight desc'; + +// return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscriber where subscribed=%d and subscribed != subscriber and tagger = tagged and tag is not null group by tag order by weight desc'; } } + diff --git a/lib/subscriptionspeopletagcloudsection.php b/lib/subscriptionspeopletagcloudsection.php index c3f7d1763..f9c8672e3 100644 --- a/lib/subscriptionspeopletagcloudsection.php +++ b/lib/subscriptionspeopletagcloudsection.php @@ -54,6 +54,8 @@ class SubscriptionsPeopleTagCloudSection extends SubPeopleTagCloudSection } function query() { - return 'select tag, count(tag) as weight from subscription left join profile_tag on subscriber=tagger and subscribed=tagged where subscriber=%d and subscriber != subscribed group by tag order by weight desc'; +// return 'select tag, count(tag) as weight from subscription left join profile_tag on subscriber=tagger and subscribed=tagged where subscriber=%d and subscriber != subscribed group by tag order by weight desc'; + return 'select tag, count(tag) as weight from subscription left join profile_tag on subscriber=tagger and subscribed=tagged where subscriber=%d and subscriber != subscribed and tag is not null group by tag order by weight desc'; } } + -- cgit v1.2.3-54-g00ecf From d71fbe9d9693cd5426be74807ff8f18fc6376c56 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Fri, 24 Apr 2009 20:28:39 +0000 Subject: fixed subscriptions dropdown action --- lib/galleryaction.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/galleryaction.php b/lib/galleryaction.php index 0484918ce..8fa11a756 100644 --- a/lib/galleryaction.php +++ b/lib/galleryaction.php @@ -134,9 +134,11 @@ class GalleryAction extends Action $this->elementStart('li', array('id'=>'filter_tags_item')); $this->elementStart('form', array('name' => 'bytag', 'id' => 'bytag', + 'action' => common_path('?action=' . $this->trimmed('action')), 'method' => 'post')); $this->dropdown('tag', _('Tag'), $content, _('Choose a tag to narrow list'), false, $tag); + $this->hidden('nickname', $this->user->nickname); $this->submit('submit', _('Go')); $this->elementEnd('form'); $this->elementEnd('li'); @@ -169,4 +171,4 @@ class GalleryAction extends Action { return array(); } -} \ No newline at end of file +} -- cgit v1.2.3-54-g00ecf From e85cddba45c2ce02d135f00acdcfa37cb9168130 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Tue, 28 Apr 2009 23:31:00 -0700 Subject: Ticket #1428 - Changed replies API method to "mentions". --- actions/twitapistatuses.php | 38 +++++++++++++++++++++----------------- lib/router.php | 4 ++-- 2 files changed, 23 insertions(+), 19 deletions(-) (limited to 'lib') diff --git a/actions/twitapistatuses.php b/actions/twitapistatuses.php index 323c4f1f8..3abeba367 100644 --- a/actions/twitapistatuses.php +++ b/actions/twitapistatuses.php @@ -144,10 +144,10 @@ class TwitapistatusesAction extends TwitterapiAction break; case 'atom': if (isset($apidata['api_arg'])) { - $selfuri = $selfuri = common_root_url() . + $selfuri = common_root_url() . 'api/statuses/friends_timeline/' . $apidata['api_arg'] . '.atom'; } else { - $selfuri = $selfuri = common_root_url() . + $selfuri = common_root_url() . 'api/statuses/friends_timeline.atom'; } $this->show_atom_timeline($notice, $title, $id, $link, $subtitle, null, $selfuri); @@ -231,10 +231,10 @@ class TwitapistatusesAction extends TwitterapiAction break; case 'atom': if (isset($apidata['api_arg'])) { - $selfuri = $selfuri = common_root_url() . + $selfuri = common_root_url() . 'api/statuses/user_timeline/' . $apidata['api_arg'] . '.atom'; } else { - $selfuri = $selfuri = common_root_url() . + $selfuri = common_root_url() . 'api/statuses/user_timeline.atom'; } $this->show_atom_timeline($notice, $title, $id, $link, $subtitle, $suplink, $selfuri); @@ -344,7 +344,7 @@ class TwitapistatusesAction extends TwitterapiAction $this->show($args, $apidata); } - function replies($args, $apidata) + function mentions($args, $apidata) { parent::handle($args); @@ -360,11 +360,13 @@ class TwitapistatusesAction extends TwitterapiAction $profile = $user->getProfile(); $sitename = common_config('site', 'name'); - $title = sprintf(_('%1$s / Updates replying to %2$s'), $sitename, $user->nickname); + $title = sprintf(_('%1$s / Updates mentioning %2$s'), + $sitename, $user->nickname); $taguribase = common_config('integration', 'taguri'); - $id = "tag:$taguribase:Replies:".$user->id; + $id = "tag:$taguribase:Mentions:".$user->id; $link = common_local_url('replies', array('nickname' => $user->nickname)); - $subtitle = sprintf(_('%1$s updates that reply to updates from %2$s / %3$s.'), $sitename, $user->nickname, $profile->getBestName()); + $subtitle = sprintf(_('%1$s updates that reply to updates from %2$s / %3$s.'), + $sitename, $user->nickname, $profile->getBestName()); if (!$page) { $page = 1; @@ -385,7 +387,8 @@ class TwitapistatusesAction extends TwitterapiAction $since = strtotime($this->arg('since')); - $notice = $user->getReplies((($page-1)*20), $count, $since_id, $before_id, $since); + $notice = $user->getReplies((($page-1)*20), + $count, $since_id, $before_id, $since); $notices = array(); while ($notice->fetch()) { @@ -400,14 +403,10 @@ class TwitapistatusesAction extends TwitterapiAction $this->show_rss_timeline($notices, $title, $link, $subtitle); break; case 'atom': - if (isset($apidata['api_arg'])) { - $selfuri = $selfuri = common_root_url() . - 'api/statuses/replies/' . $apidata['api_arg'] . '.atom'; - } else { - $selfuri = $selfuri = common_root_url() . - 'api/statuses/replies.atom'; - } - $this->show_atom_timeline($notices, $title, $id, $link, $subtitle, null, $selfuri); + $selfuri = common_root_url() . + ltrim($_SERVER['QUERY_STRING'], 'p='); + $this->show_atom_timeline($notices, $title, $id, $link, $subtitle, + null, $selfuri); break; case 'json': $this->show_json_timeline($notices); @@ -418,6 +417,11 @@ class TwitapistatusesAction extends TwitterapiAction } + function replies($args, $apidata) + { + call_user_func(array($this, 'mentions'), $args, $apidata); + } + function show($args, $apidata) { parent::handle($args); diff --git a/lib/router.php b/lib/router.php index 6fb2f9487..12590b790 100644 --- a/lib/router.php +++ b/lib/router.php @@ -231,12 +231,12 @@ class Router $m->connect('api/statuses/:method', array('action' => 'api', 'apiaction' => 'statuses'), - array('method' => '(public_timeline|friends_timeline|user_timeline|update|replies|friends|followers|featured)(\.(atom|rss|xml|json))?')); + array('method' => '(public_timeline|friends_timeline|user_timeline|update|replies|mentions|friends|followers|featured)(\.(atom|rss|xml|json))?')); $m->connect('api/statuses/:method/:argument', array('action' => 'api', 'apiaction' => 'statuses'), - array('method' => '(user_timeline|friends_timeline|replies|show|destroy|friends|followers)')); + array('method' => '(user_timeline|friends_timeline|replies|mentions|show|destroy|friends|followers)')); // users -- cgit v1.2.3-54-g00ecf From bc190595d1dfd56bf7e68597b3d574909eb27260 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 7 May 2009 02:07:31 -0700 Subject: Added TwitterStatusFetcher into daemon startup and shutdown subsystem --- config.php.sample | 3 +++ lib/common.php | 2 ++ scripts/getvaliddaemons.php | 3 +++ scripts/stopdaemons.sh | 2 +- scripts/twitterstatusfetcher.php | 10 ++++++---- 5 files changed, 15 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/config.php.sample b/config.php.sample index b8ed45fa8..6d6a9b533 100644 --- a/config.php.sample +++ b/config.php.sample @@ -150,6 +150,9 @@ $config['sphinx']['port'] = 3312; #$config['memcached']['server'] = 'localhost'; #$config['memcached']['port'] = 11211; +# Enable bidirectional Twitter bridge +#$config['twitterbridge']['enabled'] = true; + #Twitter integration source attribute. Note: default is Laconica #$config['integration']['source'] = 'Laconica'; diff --git a/lib/common.php b/lib/common.php index 00e5b0bc2..abdc22c0e 100644 --- a/lib/common.php +++ b/lib/common.php @@ -143,6 +143,8 @@ $config = array('piddir' => '/var/run', 'user' => false, 'group' => false), + 'twitterbridge' => + array('enabled' => false), 'integration' => array('source' => 'Laconica', # source attribute for Twitter 'taguri' => $_server.',2009'), # base for tag URIs diff --git a/scripts/getvaliddaemons.php b/scripts/getvaliddaemons.php index 482e63af7..a10233e69 100755 --- a/scripts/getvaliddaemons.php +++ b/scripts/getvaliddaemons.php @@ -44,6 +44,9 @@ if(common_config('xmpp','enabled')) { if(common_config('memcached','enabled')) { echo "memcachedqueuehandler.php "; } +if(common_config('twitterbridge','enabled')) { + echo "twitterstatusfetcher.php "; +} echo "ombqueuehandler.php "; echo "twitterqueuehandler.php "; echo "facebookqueuehandler.php "; diff --git a/scripts/stopdaemons.sh b/scripts/stopdaemons.sh index f6d71eddf..764037e8f 100755 --- a/scripts/stopdaemons.sh +++ b/scripts/stopdaemons.sh @@ -25,7 +25,7 @@ DIR=`php $SDIR/getpiddir.php` for f in jabberhandler ombhandler publichandler smshandler pinghandler \ xmppconfirmhandler xmppdaemon twitterhandler facebookhandler \ - memcachehandler inboxhandler; do + memcachehandler inboxhandler twitterstatusfetcher; do FILES="$DIR/$f.*.pid" for ff in "$FILES" ; do diff --git a/scripts/twitterstatusfetcher.php b/scripts/twitterstatusfetcher.php index e8819f665..9dfadc760 100755 --- a/scripts/twitterstatusfetcher.php +++ b/scripts/twitterstatusfetcher.php @@ -32,7 +32,7 @@ define('LACONICA', true); define('MAXCHILDREN', 2); define('POLL_INTERVAL', 60); // in seconds -// Uncomment this to get useful console output +// Uncomment this to get useful logging define('SCRIPT_DEBUG', true); require_once(INSTALLDIR . '/lib/common.php'); @@ -45,7 +45,7 @@ class TwitterStatusFetcher extends Daemon function name() { - return 'twitterstatusfetcher'; + return ('twitterstatusfetcher.generic'); } function run() @@ -130,7 +130,9 @@ class TwitterStatusFetcher extends Daemon ' secs before hitting Twitter again.'); } - sleep(POLL_INTERVAL); + if (POLL_INTERVAL > 0) { + sleep(POLL_INTERVAL); + } } while (true); } @@ -282,7 +284,7 @@ class TwitterStatusFetcher extends Daemon // XXX: Figure out a better way to link Twitter replies? $notice->saveReplies(); - // XXX: Do we want to polute our tag cloud with + // XXX: Do we want to pollute our tag cloud with // hashtags from Twitter? $notice->saveTags(); $notice->saveGroups(); -- cgit v1.2.3-54-g00ecf From d010d811ba812ccc8fbb1a49fcba7a30226ea779 Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Mon, 11 May 2009 13:45:00 -0400 Subject: db stuff for URLs: redirections, oembed, etc. --- actions/newnotice.php | 33 ++++++++++++ classes/File.php | 47 +++++++++++++++++ classes/File_oembed.php | 53 +++++++++++++++++++ classes/File_redirection.php | 45 ++++++++++++++++ classes/File_thumbnail.php | 45 ++++++++++++++++ classes/File_to_post.php | 43 +++++++++++++++ classes/laconica.ini | 123 +++++++++++++++++++++++++++++++++++++++++++ classes/laconica.links.ini | 71 +++++++++++++++++++++++++ lib/util.php | 8 ++- 9 files changed, 466 insertions(+), 2 deletions(-) create mode 100644 classes/File.php create mode 100644 classes/File_oembed.php create mode 100644 classes/File_redirection.php create mode 100644 classes/File_thumbnail.php create mode 100644 classes/File_to_post.php mode change 100755 => 100644 classes/laconica.ini (limited to 'lib') diff --git a/actions/newnotice.php b/actions/newnotice.php index cbd04c58b..8b03abc62 100644 --- a/actions/newnotice.php +++ b/actions/newnotice.php @@ -166,6 +166,8 @@ class NewnoticeAction extends Action return; } + $this->saveUrls($notice); + common_broadcast_notice($notice); if ($this->boolean('ajax')) { @@ -191,6 +193,37 @@ class NewnoticeAction extends Action } } + /** save all urls in the notice to the db + * + * follow redirects and save all available file information + * (mimetype, date, size, oembed, etc.) + * + * @param class $notice Notice to pull URLs from + * + * @return void + */ + function saveUrls($notice) { + common_debug("Saving all URLs"); + common_replace_urls_callback($notice->content, array($this, 'saveUrl'), $notice->id); + } + + function saveUrl($data) { + list($url, $notice_id) = $data; + common_debug("Saving $url for $notice_id"); + $file = File::staticGet('url', $url); + if (empty($file)) { + common_debug('unknown file/url'); + $file = new File; + $file->url = $url; + $file->insert(); + } + common_debug('File: ' . print_r($file, true)); + $f2p = new File_to_post; + $f2p->file_id = $file->id; + $f2p->post_id = $notice_id; + $f2p->insert(); + } + /** * Show an Ajax-y error message * diff --git a/classes/File.php b/classes/File.php new file mode 100644 index 000000000..8dd017b79 --- /dev/null +++ b/classes/File.php @@ -0,0 +1,47 @@ +. + */ + +if (!defined('LACONICA')) { exit(1); } + +require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; + +/** + * Table Definition for file + */ + +class File extends Memcached_DataObject +{ + ###START_AUTOCODE + /* the code below is auto generated do not remove the above tag */ + + public $__table = 'file'; // table name + public $id; // int(11) not_null primary_key group_by + public $url; // varchar(255) unique_key + public $mimetype; // varchar(50) + public $size; // int(11) group_by + public $title; // varchar(255) + public $date; // int(11) group_by + public $protected; // int(1) group_by + + /* Static get */ + function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('File',$k,$v); } + + /* the code above is auto generated do not remove the tag below */ + ###END_AUTOCODE +} diff --git a/classes/File_oembed.php b/classes/File_oembed.php new file mode 100644 index 000000000..33dd8200c --- /dev/null +++ b/classes/File_oembed.php @@ -0,0 +1,53 @@ +. + */ + +if (!defined('LACONICA')) { exit(1); } + +require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; + +/** + * Table Definition for file_oembed + */ + +class File_oembed extends Memcached_DataObject +{ + ###START_AUTOCODE + /* the code below is auto generated do not remove the above tag */ + + public $__table = 'file_oembed'; // table name + public $id; // int(11) not_null primary_key group_by + public $file_id; // int(11) unique_key group_by + public $version; // varchar(20) + public $type; // varchar(20) + public $provider; // varchar(50) + public $provider_url; // varchar(255) + public $width; // int(11) group_by + public $height; // int(11) group_by + public $html; // blob(65535) blob + public $title; // varchar(255) + public $author_name; // varchar(50) + public $author_url; // varchar(255) + public $url; // varchar(255) + + /* Static get */ + function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('File_oembed',$k,$v); } + + /* the code above is auto generated do not remove the tag below */ + ###END_AUTOCODE +} diff --git a/classes/File_redirection.php b/classes/File_redirection.php new file mode 100644 index 000000000..e2d1e69c3 --- /dev/null +++ b/classes/File_redirection.php @@ -0,0 +1,45 @@ +. + */ + +if (!defined('LACONICA')) { exit(1); } + +require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; + +/** + * Table Definition for file_redirection + */ + +class File_redirection extends Memcached_DataObject +{ + ###START_AUTOCODE + /* the code below is auto generated do not remove the above tag */ + + public $__table = 'file_redirection'; // table name + public $id; // int(11) not_null primary_key group_by + public $url; // varchar(255) unique_key + public $file_id; // int(11) group_by + public $redirections; // int(11) group_by + public $httpcode; // int(11) group_by + + /* Static get */ + function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('File_redirection',$k,$v); } + + /* the code above is auto generated do not remove the tag below */ + ###END_AUTOCODE +} diff --git a/classes/File_thumbnail.php b/classes/File_thumbnail.php new file mode 100644 index 000000000..7b906a07c --- /dev/null +++ b/classes/File_thumbnail.php @@ -0,0 +1,45 @@ +. + */ + +if (!defined('LACONICA')) { exit(1); } + +require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; + +/** + * Table Definition for file_thumbnail + */ + +class File_thumbnail extends Memcached_DataObject +{ + ###START_AUTOCODE + /* the code below is auto generated do not remove the above tag */ + + public $__table = 'file_thumbnail'; // table name + public $id; // int(11) not_null primary_key group_by + public $file_id; // int(11) unique_key group_by + public $url; // varchar(255) unique_key + public $width; // int(11) group_by + public $height; // int(11) group_by + + /* Static get */ + function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('File_thumbnail',$k,$v); } + + /* the code above is auto generated do not remove the tag below */ + ###END_AUTOCODE +} diff --git a/classes/File_to_post.php b/classes/File_to_post.php new file mode 100644 index 000000000..bd0528d98 --- /dev/null +++ b/classes/File_to_post.php @@ -0,0 +1,43 @@ +. + */ + +if (!defined('LACONICA')) { exit(1); } + +require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; + +/** + * Table Definition for file_to_post + */ + +class File_to_post extends Memcached_DataObject +{ + ###START_AUTOCODE + /* the code below is auto generated do not remove the above tag */ + + public $__table = 'file_to_post'; // table name + public $id; // int(11) not_null primary_key group_by + public $file_id; // int(11) multiple_key group_by + public $post_id; // int(11) group_by + + /* Static get */ + function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('File_to_post',$k,$v); } + + /* the code above is auto generated do not remove the tag below */ + ###END_AUTOCODE +} diff --git a/classes/laconica.ini b/classes/laconica.ini old mode 100755 new mode 100644 index 5a905a4bb..00a1b8936 --- a/classes/laconica.ini +++ b/classes/laconica.ini @@ -1,4 +1,67 @@ +[file] +id = 129 +url = 2 +mimetype = 2 +size = 1 +title = 2 +date = 1 +protected = 17 + +[file__keys] +id = K +url = U + +[file_oembed] +id = 129 +file_id = 1 +version = 2 +type = 2 +provider = 2 +provider_url = 2 +width = 1 +height = 1 +html = 66 +title = 2 +author_name = 2 +author_url = 2 +url = 2 + +[file_oembed__keys] +id = K +file_id = U + +[file_redirection] +id = 129 +url = 2 +file_id = 1 +redirections = 1 +httpcode = 1 + +[file_redirection__keys] +id = K +url = U + +[file_thumbnail] +id = 129 +file_id = 1 +url = 2 +width = 1 +height = 1 + +[file_thumbnail__keys] +id = K +file_id = U +url = U + +[file_to_post] +id = 129 +file_id = 1 +post_id = 1 + +[file_to_post__keys] +id = K + [avatar] profile_id = 129 original = 17 @@ -393,3 +456,63 @@ modified = 384 [user_openid__keys] canonical = K display = U + +[file] +id = 129 +url = 2 +mimetype = 2 +size = 1 +title = 2 +date = 1 +protected = 1 + +[file__keys] +id = N + +[file_oembed] +id = 129 +file_id = 129 +version = 2 +type = 2 +provider = 2 +provider_url = 2 +width = 1 +height = 1 +html = 34 +title = 2 +author_name = 2 +author_url = 2 +url = 2 + +[file_oembed__keys] +id = N + +[file_redirection] +id = 129 +url = 2 +file_id = 129 +redirections = 1 +httpcode = 1 + +[file_redirection__keys] +id = N + +[file_thumbnail] +id = 129 +file_id = 129 +url = 2 +width = 1 +height = 1 + +[file_thumbnail__keys] +id = N + +[file_to_post] +id = 129 +file_id = 129 +post_id = 129 + +[file_to_post__keys] +id = N + + diff --git a/classes/laconica.links.ini b/classes/laconica.links.ini index 173b18726..bc52ce578 100644 --- a/classes/laconica.links.ini +++ b/classes/laconica.links.ini @@ -41,3 +41,74 @@ subscribed = profile:id [fave] notice_id = notice:id user_id = user:id + +[file_oembed] +file_id = file:id + +[file_redirection] +file_id = file:id + +[file_thumbnail] +file_id = file:id + +[file_to_post] +file_id = file:id +post_id = post:id + +[avatar] +profile_id = profile:id + +[user] +id = profile:id +carrier = sms_carrier:id + +[remote_profile] +id = profile:id + +[notice] +profile_id = profile:id +reply_to = notice:id + +[reply] +notice_id = notice:id +profile_id = profile:id + +[token] +consumer_key = consumer:consumer_key + +[nonce] +consumer_key,token = token:consumer_key,token + +[user_openid] +user_id = user:id + +[confirm_address] +user_id = user:id + +[remember_me] +user_id = user:id + +[queue_item] +notice_id = notice:id + +[subscription] +subscriber = profile:id +subscribed = profile:id + +[fave] +notice_id = notice:id +user_id = user:id + +[file_oembed] +file_id = file:id + +[file_redirection] +file_id = file:id + +[file_thumbnail] +file_id = file:id + +[file_to_post] +file_id = file:id +post_id = post:id + diff --git a/lib/util.php b/lib/util.php index 198185338..c4a63a441 100644 --- a/lib/util.php +++ b/lib/util.php @@ -395,7 +395,7 @@ function common_render_text($text) return $r; } -function common_replace_urls_callback($text, $callback) { +function common_replace_urls_callback($text, $callback, $notice_id = null) { // Start off with a regex $regex = '#'. '(?:'. @@ -466,7 +466,11 @@ function common_replace_urls_callback($text, $callback) { $url = (mb_strpos($orig_url, htmlspecialchars($url)) === FALSE) ? $url:htmlspecialchars($url); // Call user specified func - $modified_url = call_user_func($callback, $url); + if (isset($notice_id)) { + $modified_url = call_user_func($callback, array($url, $notice_id)); + } else { + $modified_url = call_user_func($callback, $url); + } // Replace it! $start = mb_strpos($text, $url, $offset); -- cgit v1.2.3-54-g00ecf From 3b7ee5a5f9a2cd3066aff8a7a12d09878be3b06c Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Wed, 13 May 2009 14:27:32 -0400 Subject: rewrote short url stuff to handle new file/url classes (redirections, oembed, mimetypes, etc.) --- actions/newnotice.php | 18 +--- classes/File.php | 65 ++++++++++++ classes/File_oembed.php | 43 ++++++++ classes/File_redirection.php | 231 +++++++++++++++++++++++++++++++++++++++++++ classes/File_to_post.php | 17 ++++ classes/Notice.php | 6 +- classes/laconica.ini | 64 ------------ classes/laconica.links.ini | 59 +---------- lib/Shorturl_api.php | 3 +- lib/util.php | 112 ++++----------------- 10 files changed, 382 insertions(+), 236 deletions(-) (limited to 'lib') diff --git a/actions/newnotice.php b/actions/newnotice.php index 8b03abc62..ae0ff9636 100644 --- a/actions/newnotice.php +++ b/actions/newnotice.php @@ -158,7 +158,8 @@ class NewnoticeAction extends Action $replyto = 'false'; } - $notice = Notice::saveNew($user->id, $content, 'web', 1, +// $notice = Notice::saveNew($user->id, $content_shortened, 'web', 1, + $notice = Notice::saveNew($user->id, $content_shortened, 'web', 1, ($replyto == 'false') ? null : $replyto); if (is_string($notice)) { @@ -203,25 +204,12 @@ class NewnoticeAction extends Action * @return void */ function saveUrls($notice) { - common_debug("Saving all URLs"); common_replace_urls_callback($notice->content, array($this, 'saveUrl'), $notice->id); } function saveUrl($data) { list($url, $notice_id) = $data; - common_debug("Saving $url for $notice_id"); - $file = File::staticGet('url', $url); - if (empty($file)) { - common_debug('unknown file/url'); - $file = new File; - $file->url = $url; - $file->insert(); - } - common_debug('File: ' . print_r($file, true)); - $f2p = new File_to_post; - $f2p->file_id = $file->id; - $f2p->post_id = $notice_id; - $f2p->insert(); + $zzz = File::processNew($url, $notice_id); } /** diff --git a/classes/File.php b/classes/File.php index 8dd017b79..2ddc5deb8 100644 --- a/classes/File.php +++ b/classes/File.php @@ -20,6 +20,11 @@ if (!defined('LACONICA')) { exit(1); } require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; +require_once INSTALLDIR.'/classes/File_redirection.php'; +require_once INSTALLDIR.'/classes/File_oembed.php'; +require_once INSTALLDIR.'/classes/File_thumbnail.php'; +require_once INSTALLDIR.'/classes/File_to_post.php'; +//require_once INSTALLDIR.'/classes/File_redirection.php'; /** * Table Definition for file @@ -44,4 +49,64 @@ class File extends Memcached_DataObject /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE + + function isProtected($url) { + return 'http://www.facebook.com/login.php' === $url; + } + + function saveNew($redir_data, $given_url) { + $x = new File; + $x->url = $given_url; + if (!empty($redir_data['protected'])) $x->protected = $redir_data['protected']; + if (!empty($redir_data['title'])) $x->title = $redir_data['title']; + if (!empty($redir_data['type'])) $x->mimetype = $redir_data['type']; + if (!empty($redir_data['size'])) $x->size = intval($redir_data['size']); + if (isset($redir_data['time']) && $redir_data['time'] > 0) $x->date = intval($redir_data['time']); + $file_id = $x->insert(); + + if (isset($redir_data['type']) + && ('text/html' === substr($redir_data['type'], 0, 9)) + && ($oembed_data = File_oembed::_getOembed($given_url)) + && isset($oembed_data['json'])) { + + File_oembed::saveNew($oembed_data['json'], $file_id); + } + return $x; + } + + function processNew($given_url, $notice_id) { + if (empty($given_url)) return -1; // error, no url to process + $given_url = File_redirection::_canonUrl($given_url); + if (empty($given_url)) return -1; // error, no url to process + $file = File::staticGet('url', $given_url); + if (empty($file->id)) { + $file_redir = File_redirection::staticGet('url', $given_url); + if (empty($file_redir->id)) { + $redir_data = File_redirection::where($given_url); + $redir_url = $redir_data['url']; + if ($redir_url === $given_url) { + $x = File::saveNew($redir_data, $given_url); + $file_id = $x->id; + + } else { + $x = File::processNew($redir_url, $notice_id); + $file_id = $x->id; + File_redirection::saveNew($redir_data, $file_id, $given_url); + } + } else { + $file_id = $file_redir->file_id; + } + } else { + $file_id = $file->id; + $x = $file; + } + + if (empty($x)) { + $x = File::staticGet($file_id); + if (empty($x)) die('Impossible!'); + } + + File_to_post::processNew($file_id, $notice_id); + return $x; + } } diff --git a/classes/File_oembed.php b/classes/File_oembed.php index 33dd8200c..2846f49db 100644 --- a/classes/File_oembed.php +++ b/classes/File_oembed.php @@ -50,4 +50,47 @@ class File_oembed extends Memcached_DataObject /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE + + + function _getOembed($url, $maxwidth = 500, $maxheight = 400, $format = 'json') { + $cmd = 'http://oohembed.com/oohembed/?url=' . urlencode($url); + if (is_int($maxwidth)) $cmd .= "&maxwidth=$maxwidth"; + if (is_int($maxheight)) $cmd .= "&maxheight=$maxheight"; + if (is_string($format)) $cmd .= "&format=$format"; + $oe = @file_get_contents($cmd); + if (false === $oe) return false; + return array($format => (('json' === $format) ? json_decode($oe, true) : $oe)); + } + + function saveNew($data, $file_id) { + $file_oembed = new File_oembed; + $file_oembed->file_id = $file_id; + $file_oembed->version = $data['version']; + $file_oembed->type = $data['type']; + if (!empty($data['provider_name'])) $file_oembed->provider = $data['provider_name']; + if (!isset($file_oembed->provider) && !empty($data['provide'])) $file_oembed->provider = $data['provider']; + if (!empty($data['provide_url'])) $file_oembed->provider_url = $data['provider_url']; + if (!empty($data['width'])) $file_oembed->width = intval($data['width']); + if (!empty($data['height'])) $file_oembed->height = intval($data['height']); + if (!empty($data['html'])) $file_oembed->html = $data['html']; + if (!empty($data['title'])) $file_oembed->title = $data['title']; + if (!empty($data['author_name'])) $file_oembed->author_name = $data['author_name']; + if (!empty($data['author_url'])) $file_oembed->author_url = $data['author_url']; + if (!empty($data['url'])) $file_oembed->url = $data['url']; + $file_oembed->insert(); + + if (!empty($data['thumbnail_url'])) { + $tn = new File_thumbnail; + $tn->file_id = $file_id; + $tn->url = $data['thumbnail_url']; + $tn->width = intval($data['thumbnail_width']); + $tn->height = intval($data['thumbnail_height']); + $tn->insert(); + } + + + + } } + + diff --git a/classes/File_redirection.php b/classes/File_redirection.php index e2d1e69c3..a71d1c083 100644 --- a/classes/File_redirection.php +++ b/classes/File_redirection.php @@ -20,6 +20,11 @@ if (!defined('LACONICA')) { exit(1); } require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; +require_once INSTALLDIR.'/classes/File.php'; +require_once INSTALLDIR.'/classes/File_oembed.php'; + +define('USER_AGENT', 'Laconica user agent / file probe'); + /** * Table Definition for file_redirection @@ -42,4 +47,230 @@ class File_redirection extends Memcached_DataObject /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE + + + + function _commonCurl($url, $redirs) { + $curlh = curl_init(); + curl_setopt($curlh, CURLOPT_URL, $url); + curl_setopt($curlh, CURLOPT_AUTOREFERER, true); // # setup referer header when folowing redirects + curl_setopt($curlh, CURLOPT_CONNECTTIMEOUT, 10); // # seconds to wait + curl_setopt($curlh, CURLOPT_MAXREDIRS, $redirs); // # max number of http redirections to follow + curl_setopt($curlh, CURLOPT_USERAGENT, USER_AGENT); + curl_setopt($curlh, CURLOPT_FOLLOWLOCATION, true); // Follow redirects + curl_setopt($curlh, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curlh, CURLOPT_FILETIME, true); + curl_setopt($curlh, CURLOPT_HEADER, true); // Include header in output + return $curlh; + } + + function _redirectWhere_imp($short_url, $redirs = 10, $protected = false) { + if ($redirs < 0) return false; + + // let's see if we know this... + $a = File::staticGet('url', $short_url); + if (empty($a->id)) { + $b = File_redirection::staticGet('url', $short_url); + if (empty($b->id)) { + // we'll have to figure it out + } else { + // this is a redirect to $b->file_id + $a = File::staticGet($b->file_id); + $url = $a->url; + } + } else { + // this is a direct link to $a->url + $url = $a->url; + } + if (isset($url)) { + return $url; + } + + + + $curlh = File_redirection::_commonCurl($short_url, $redirs); + // Don't include body in output + curl_setopt($curlh, CURLOPT_NOBODY, true); + curl_exec($curlh); + $info = curl_getinfo($curlh); + curl_close($curlh); + + if (405 == $info['http_code']) { + $curlh = File_redirection::_commonCurl($short_url, $redirs); + curl_exec($curlh); + $info = curl_getinfo($curlh); + curl_close($curlh); + } + + if (!empty($info['redirect_count']) && File::isProtected($info['url'])) { + return File_redirection::_redirectWhere_imp($short_url, $info['redirect_count'] - 1, true); + } + + $ret = array('code' => $info['http_code'] + , 'redirects' => $info['redirect_count'] + , 'url' => $info['url']); + + if (!empty($info['content_type'])) $ret['type'] = $info['content_type']; + if ($protected) $ret['protected'] = true; + if (!empty($info['download_content_length'])) $ret['size'] = $info['download_content_length']; + if (isset($info['filetime']) && ($info['filetime'] > 0)) $ret['time'] = $info['filetime']; + return $ret; + } + + function where($in_url) { + $ret = File_redirection::_redirectWhere_imp($in_url); + return $ret; + } + + function makeShort($long_url) { + $long_url = File_redirection::_canonUrl($long_url); + // do we already know this long_url and have a short redirection for it? + $file = new File; + $file_redir = new File_redirection; + $file->url = $long_url; + $file->joinAdd($file_redir); + $file->selectAdd('length(file_redirection.url) as len'); + $file->limit(1); + $file->orderBy('len'); + $file->find(true); + if (!empty($file->id)) { + return $file->url; + } + + // if yet unknown, we must find a short url according to user settings + $short_url = File_redirection::_userMakeShort($long_url, common_current_user()); + return $short_url; + } + + function _userMakeShort($long_url, $user) { + if (empty($user)) { + // common current user does not find a user when called from the XMPP daemon + // therefore we'll set one here fix, so that XMPP given URLs may be shortened + $user->urlshorteningservice = 'ur1.ca'; + } + $curlh = curl_init(); + curl_setopt($curlh, CURLOPT_CONNECTTIMEOUT, 20); // # seconds to wait + curl_setopt($curlh, CURLOPT_USERAGENT, 'Laconica'); + curl_setopt($curlh, CURLOPT_RETURNTRANSFER, true); + + switch($user->urlshorteningservice) { + case 'ur1.ca': + require_once INSTALLDIR.'/lib/Shorturl_api.php'; + $short_url_service = new LilUrl; + $short_url = $short_url_service->shorten($long_url); + break; + + case '2tu.us': + $short_url_service = new TightUrl; + require_once INSTALLDIR.'/lib/Shorturl_api.php'; + $short_url = $short_url_service->shorten($long_url); + break; + + case 'ptiturl.com': + require_once INSTALLDIR.'/lib/Shorturl_api.php'; + $short_url_service = new PtitUrl; + $short_url = $short_url_service->shorten($long_url); + break; + + case 'bit.ly': + curl_setopt($curlh, CURLOPT_URL, 'http://bit.ly/api?method=shorten&long_url='.urlencode($long_url)); + $short_url = current(json_decode(curl_exec($curlh))->results)->hashUrl; + break; + + case 'is.gd': + curl_setopt($curlh, CURLOPT_URL, 'http://is.gd/api.php?longurl='.urlencode($long_url)); + $short_url = curl_exec($curlh); + break; + case 'snipr.com': + curl_setopt($curlh, CURLOPT_URL, 'http://snipr.com/site/snip?r=simple&link='.urlencode($long_url)); + $short_url = curl_exec($curlh); + break; + case 'metamark.net': + curl_setopt($curlh, CURLOPT_URL, 'http://metamark.net/api/rest/simple?long_url='.urlencode($long_url)); + $short_url = curl_exec($curlh); + break; + case 'tinyurl.com': + curl_setopt($curlh, CURLOPT_URL, 'http://tinyurl.com/api-create.php?url='.urlencode($long_url)); + $short_url = curl_exec($curlh); + break; + default: + $short_url = false; + } + + curl_close($curlh); + + if ($short_url) { + $short_url = (string)$short_url; +if(1) { + // store it + $file = File::staticGet('url', $long_url); + if (empty($file)) { + $redir_data = File_redirection::where($long_url); + $file = File::saveNew($redir_data, $long_url); + $file_id = $file->id; + if (!empty($redir_data['oembed']['json'])) { + File_oembed::saveNew($redir_data['oembed']['json'], $file_id); + } + } else { + $file_id = $file->id; + } + $file_redir = File_redirection::staticGet('url', $short_url); + if (empty($file_redir)) { + $file_redir = new File_redirection; + $file_redir->url = $short_url; + $file_redir->file_id = $file_id; + $file_redir->insert(); + } } + return $short_url; + } + return $long_url; + } + + function _canonUrl($in_url, $default_scheme = 'http://') { + if (empty($in_url)) return false; + $out_url = $in_url; + $p = parse_url($out_url); + if (empty($p['host']) || empty($p['scheme'])) { + list($scheme) = explode(':', $in_url, 2); + switch ($scheme) { + case 'fax': + case 'tel': + $out_url = str_replace('.-()', '', $out_url); + break; + + case 'mailto': + case 'aim': + case 'jabber': + case 'xmpp': + // don't touch anything + break; + + default: + $out_url = $default_scheme . ltrim($out_url, '/'); + $p = parse_url($out_url); + if (empty($p['scheme'])) return false; + break; + } + } + + if (('ftp' == $p['scheme']) || ('http' == $p['scheme']) || ('https' == $p['scheme'])) { + if (empty($p['host'])) return false; + if (empty($p['path'])) { + $out_url .= '/'; + } + } + + return $out_url; + } + + function saveNew($data, $file_id, $url) { + $file_redir = new File_redirection; + $file_redir->url = $url; + $file_redir->file_id = $file_id; + $file_redir->redirections = intval($data['redirects']); + $file_redir->httpcode = intval($data['code']); + $file_redir->insert(); + } +} + diff --git a/classes/File_to_post.php b/classes/File_to_post.php index bd0528d98..00ddebe6b 100644 --- a/classes/File_to_post.php +++ b/classes/File_to_post.php @@ -40,4 +40,21 @@ class File_to_post extends Memcached_DataObject /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE + + function processNew($file_id, $notice_id) { + static $seen = array(); + if (empty($seen[$notice_id]) || !in_array($file_id, $seen[$notice_id])) { + $f2p = new File_to_post; + $f2p->file_id = $file_id; + $f2p->post_id = $notice_id; + $f2p->insert(); + if (empty($seen[$notice_id])) { + $seen[$notice_id] = array($file_id); + } else { + $seen[$notice_id][] = $file_id; + } + } + + } } + diff --git a/classes/Notice.php b/classes/Notice.php index 382d160ab..c2fa2d19e 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -124,7 +124,7 @@ class Notice extends Memcached_DataObject $profile = Profile::staticGet($profile_id); - $final = common_shorten_links($content); +// $final = common_shorten_links($content); if (!$profile) { common_log(LOG_ERR, 'Problem saving notice. Unknown user.'); @@ -167,8 +167,8 @@ class Notice extends Memcached_DataObject $notice->reply_to = $reply_to; $notice->created = common_sql_now(); - $notice->content = $final; - $notice->rendered = common_render_content($final, $notice); + $notice->content = $content; + $notice->rendered = common_render_content($content, $notice); $notice->source = $source; $notice->uri = $uri; diff --git a/classes/laconica.ini b/classes/laconica.ini index 00a1b8936..316923af0 100644 --- a/classes/laconica.ini +++ b/classes/laconica.ini @@ -1,67 +1,3 @@ - -[file] -id = 129 -url = 2 -mimetype = 2 -size = 1 -title = 2 -date = 1 -protected = 17 - -[file__keys] -id = K -url = U - -[file_oembed] -id = 129 -file_id = 1 -version = 2 -type = 2 -provider = 2 -provider_url = 2 -width = 1 -height = 1 -html = 66 -title = 2 -author_name = 2 -author_url = 2 -url = 2 - -[file_oembed__keys] -id = K -file_id = U - -[file_redirection] -id = 129 -url = 2 -file_id = 1 -redirections = 1 -httpcode = 1 - -[file_redirection__keys] -id = K -url = U - -[file_thumbnail] -id = 129 -file_id = 1 -url = 2 -width = 1 -height = 1 - -[file_thumbnail__keys] -id = K -file_id = U -url = U - -[file_to_post] -id = 129 -file_id = 1 -post_id = 1 - -[file_to_post__keys] -id = K - [avatar] profile_id = 129 original = 17 diff --git a/classes/laconica.links.ini b/classes/laconica.links.ini index bc52ce578..95c63f3c0 100644 --- a/classes/laconica.links.ini +++ b/classes/laconica.links.ini @@ -53,62 +53,5 @@ file_id = file:id [file_to_post] file_id = file:id -post_id = post:id - -[avatar] -profile_id = profile:id - -[user] -id = profile:id -carrier = sms_carrier:id - -[remote_profile] -id = profile:id - -[notice] -profile_id = profile:id -reply_to = notice:id - -[reply] -notice_id = notice:id -profile_id = profile:id - -[token] -consumer_key = consumer:consumer_key - -[nonce] -consumer_key,token = token:consumer_key,token - -[user_openid] -user_id = user:id - -[confirm_address] -user_id = user:id - -[remember_me] -user_id = user:id - -[queue_item] -notice_id = notice:id - -[subscription] -subscriber = profile:id -subscribed = profile:id - -[fave] -notice_id = notice:id -user_id = user:id - -[file_oembed] -file_id = file:id - -[file_redirection] -file_id = file:id - -[file_thumbnail] -file_id = file:id - -[file_to_post] -file_id = file:id -post_id = post:id +post_id = notice:id diff --git a/lib/Shorturl_api.php b/lib/Shorturl_api.php index fe106cb83..924aa93a8 100644 --- a/lib/Shorturl_api.php +++ b/lib/Shorturl_api.php @@ -22,6 +22,7 @@ if (!defined('LACONICA')) { exit(1); } class ShortUrlApi { protected $service_url; + protected $long_limit = 27; function __construct($service_url) { @@ -39,7 +40,7 @@ class ShortUrlApi } private function is_long($url) { - return strlen($url) >= 30; + return strlen($url) >= $this->long_limit; } protected function http_post($data) { diff --git a/lib/util.php b/lib/util.php index c4a63a441..25c0fb0a1 100644 --- a/lib/util.php +++ b/lib/util.php @@ -466,10 +466,10 @@ function common_replace_urls_callback($text, $callback, $notice_id = null) { $url = (mb_strpos($orig_url, htmlspecialchars($url)) === FALSE) ? $url:htmlspecialchars($url); // Call user specified func - if (isset($notice_id)) { - $modified_url = call_user_func($callback, array($url, $notice_id)); - } else { + if (empty($notice_id)) { $modified_url = call_user_func($callback, $url); + } else { + $modified_url = call_user_func($callback, array($url, $notice_id)); } // Replace it! @@ -485,107 +485,29 @@ function common_linkify($url) { // It comes in special'd, so we unspecial it before passing to the stringifying // functions $url = htmlspecialchars_decode($url); - $display = $url; - $url = (!preg_match('#^([a-z]+://|(mailto|aim|tel):)#i', $url)) ? 'http://'.$url : $url; - - $attrs = array('href' => $url, 'rel' => 'external'); + $display = File_redirection::_canonUrl($url); + $longurl_data = File_redirection::where($url); + if (is_array($longurl_data)) { + $longurl = $longurl_data['url']; + } elseif (is_string($longurl_data)) { + $longurl = $longurl_data; + } else { + die('impossible to linkify'); + } - if ($longurl = common_longurl($url)) { + $attrs = array('href' => $longurl, 'rel' => 'external'); +if(0){ + if ($longurl !== $url) { $attrs['title'] = $longurl; } - - return XMLStringer::estring('a', $attrs, $display); -} - -function common_longurl($short_url) -{ - $long_url = common_shorten_link($short_url, true); - if ($long_url === $short_url) return false; - return $long_url; } - -function common_longurl2($uri) -{ - $uri_e = urlencode($uri); - $longurl = unserialize(file_get_contents("http://api.longurl.org/v1/expand?format=php&url=$uri_e")); - if (empty($longurl['long_url']) || $uri === $longurl['long_url']) return false; - return stripslashes($longurl['long_url']); + return XMLStringer::estring('a', $attrs, $display); } function common_shorten_links($text) { if (mb_strlen($text) <= 140) return $text; - static $cache = array(); - if (isset($cache[$text])) return $cache[$text]; - // \s = not a horizontal whitespace character (since PHP 5.2.4) - return $cache[$text] = common_replace_urls_callback($text, 'common_shorten_link');; -} - -function common_shorten_link($url, $reverse = false) -{ - - static $url_cache = array(); - if ($reverse) return isset($url_cache[$url]) ? $url_cache[$url] : $url; - - $user = common_current_user(); - if (!isset($user)) { - // common current user does not find a user when called from the XMPP daemon - // therefore we'll set one here fix, so that XMPP given URLs may be shortened - $user->urlshorteningservice = 'ur1.ca'; - } - $curlh = curl_init(); - curl_setopt($curlh, CURLOPT_CONNECTTIMEOUT, 20); // # seconds to wait - curl_setopt($curlh, CURLOPT_USERAGENT, 'Laconica'); - curl_setopt($curlh, CURLOPT_RETURNTRANSFER, true); - - switch($user->urlshorteningservice) { - case 'ur1.ca': - $short_url_service = new LilUrl; - $short_url = $short_url_service->shorten($url); - break; - - case '2tu.us': - $short_url_service = new TightUrl; - $short_url = $short_url_service->shorten($url); - break; - - case 'ptiturl.com': - $short_url_service = new PtitUrl; - $short_url = $short_url_service->shorten($url); - break; - - case 'bit.ly': - curl_setopt($curlh, CURLOPT_URL, 'http://bit.ly/api?method=shorten&long_url='.urlencode($url)); - $short_url = current(json_decode(curl_exec($curlh))->results)->hashUrl; - break; - - case 'is.gd': - curl_setopt($curlh, CURLOPT_URL, 'http://is.gd/api.php?longurl='.urlencode($url)); - $short_url = curl_exec($curlh); - break; - case 'snipr.com': - curl_setopt($curlh, CURLOPT_URL, 'http://snipr.com/site/snip?r=simple&link='.urlencode($url)); - $short_url = curl_exec($curlh); - break; - case 'metamark.net': - curl_setopt($curlh, CURLOPT_URL, 'http://metamark.net/api/rest/simple?long_url='.urlencode($url)); - $short_url = curl_exec($curlh); - break; - case 'tinyurl.com': - curl_setopt($curlh, CURLOPT_URL, 'http://tinyurl.com/api-create.php?url='.urlencode($url)); - $short_url = curl_exec($curlh); - break; - default: - $short_url = false; - } - - curl_close($curlh); - - if ($short_url) { - $url_cache[(string)$short_url] = $url; - return (string)$short_url; - } - return $url; + return common_replace_urls_callback($text, array('File_redirection', 'makeShort')); } function common_xml_safe_str($str) -- cgit v1.2.3-54-g00ecf From c6816c163e813ac4bc8163cba7ab08c54d8320d5 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 15 May 2009 14:18:04 -0400 Subject: reformat action.php --- lib/action.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'lib') diff --git a/lib/action.php b/lib/action.php index 2ec9329e0..4bd41c226 100644 --- a/lib/action.php +++ b/lib/action.php @@ -98,15 +98,15 @@ class Action extends HTMLOutputter // lawsuit Event::handle('EndShowHTML', array($this)); } if (Event::handle('StartShowHead', array($this))) { - $this->showHead(); + $this->showHead(); Event::handle('EndShowHead', array($this)); } if (Event::handle('StartShowBody', array($this))) { - $this->showBody(); + $this->showBody(); Event::handle('EndShowBody', array($this)); } if (Event::handle('StartEndHTML', array($this))) { - $this->endHTML(); + $this->endHTML(); Event::handle('EndEndHTML', array($this)); } } @@ -347,7 +347,7 @@ class Action extends HTMLOutputter // lawsuit { $this->elementStart('body', (common_current_user()) ? array('id' => $this->trimmed('action'), 'class' => 'user_in') - : array('id' => $this->trimmed('action'))); + : array('id' => $this->trimmed('action'))); $this->elementStart('div', array('id' => 'wrap')); if (Event::handle('StartShowHeader', array($this))) { $this->showHeader(); @@ -431,10 +431,10 @@ class Action extends HTMLOutputter // lawsuit _('Connect'), _('Connect to SMS, Twitter'), false, 'nav_connect'); } $this->menuItem(common_local_url('invite'), - _('Invite'), - sprintf(_('Invite friends and colleagues to join you on %s'), - common_config('site', 'name')), - false, 'nav_invitecontact'); + _('Invite'), + sprintf(_('Invite friends and colleagues to join you on %s'), + common_config('site', 'name')), + false, 'nav_invitecontact'); $this->menuItem(common_local_url('logout'), _('Logout'), _('Logout from the site'), false, 'nav_logout'); } @@ -629,7 +629,7 @@ class Action extends HTMLOutputter // lawsuit $this->elementStart('div', array('id' => 'aside_primary', 'class' => 'aside')); if (Event::handle('StartShowExportData', array($this))) { - $this->showExportData(); + $this->showExportData(); Event::handle('EndShowExportData', array($this)); } if (Event::handle('StartShowSections', array($this))) { -- cgit v1.2.3-54-g00ecf From 14662354dc501e811dd714aa72fd8001842ee672 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 15 May 2009 14:22:49 -0400 Subject: add hooks for subgroupnav showing --- EVENTS.txt | 6 +++++ lib/subgroupnav.php | 68 +++++++++++++++++++++++++++++------------------------ 2 files changed, 43 insertions(+), 31 deletions(-) (limited to 'lib') diff --git a/EVENTS.txt b/EVENTS.txt index 5edf59245..07fc446c3 100644 --- a/EVENTS.txt +++ b/EVENTS.txt @@ -100,6 +100,12 @@ StartPublicGroupNav: Showing the public group nav menu EndPublicGroupNav: At the end of the public group nav menu - $action: the current action +StartSubGroupNav: Showing the subscriptions group nav menu +- $action: the current action + +EndSubGroupNav: At the end of the subscriptions group nav menu +- $action: the current action + RouterInitialized: After the router instance has been initialized - $m: the Net_URL_Mapper that has just been set up diff --git a/lib/subgroupnav.php b/lib/subgroupnav.php index 31c3ea0b5..4a9b36ae8 100644 --- a/lib/subgroupnav.php +++ b/lib/subgroupnav.php @@ -74,38 +74,44 @@ class SubGroupNav extends Widget $this->out->elementStart('ul', array('class' => 'nav')); - $this->out->menuItem(common_local_url('subscriptions', - array('nickname' => - $this->user->nickname)), - _('Subscriptions'), - sprintf(_('People %s subscribes to'), - $this->user->nickname), - $action == 'subscriptions', - 'nav_subscriptions'); - $this->out->menuItem(common_local_url('subscribers', - array('nickname' => - $this->user->nickname)), - _('Subscribers'), - sprintf(_('People subscribed to %s'), - $this->user->nickname), - $action == 'subscribers', - 'nav_subscribers'); - $this->out->menuItem(common_local_url('usergroups', - array('nickname' => - $this->user->nickname)), - _('Groups'), - sprintf(_('Groups %s is a member of'), - $this->user->nickname), - $action == 'usergroups', - 'nav_usergroups'); - if (!is_null($cur) && $this->user->id === $cur->id) { - $this->out->menuItem(common_local_url('invite'), - _('Invite'), - sprintf(_('Invite friends and colleagues to join you on %s'), - common_config('site', 'name')), - $action == 'invite', - 'nav_invite'); + if (Event::handle('StartSubGroupNav', array($this))) { + + $this->out->menuItem(common_local_url('subscriptions', + array('nickname' => + $this->user->nickname)), + _('Subscriptions'), + sprintf(_('People %s subscribes to'), + $this->user->nickname), + $action == 'subscriptions', + 'nav_subscriptions'); + $this->out->menuItem(common_local_url('subscribers', + array('nickname' => + $this->user->nickname)), + _('Subscribers'), + sprintf(_('People subscribed to %s'), + $this->user->nickname), + $action == 'subscribers', + 'nav_subscribers'); + $this->out->menuItem(common_local_url('usergroups', + array('nickname' => + $this->user->nickname)), + _('Groups'), + sprintf(_('Groups %s is a member of'), + $this->user->nickname), + $action == 'usergroups', + 'nav_usergroups'); + if (!is_null($cur) && $this->user->id === $cur->id) { + $this->out->menuItem(common_local_url('invite'), + _('Invite'), + sprintf(_('Invite friends and colleagues to join you on %s'), + common_config('site', 'name')), + $action == 'invite', + 'nav_invite'); + } + + Event::handle('EndSubGroupNav', array($this)); } + $this->out->elementEnd('ul'); } } -- cgit v1.2.3-54-g00ecf From fecb8c706dadb790c3a8c219275b4ba88e00b8ea Mon Sep 17 00:00:00 2001 From: Robin Millette Date: Fri, 15 May 2009 15:04:58 -0400 Subject: Attachments and their list now provide "ajax" view. Also added a few sidebars relating tags and attachments. --- actions/attachment.php | 250 +++++++++++++++++++++++++++++ actions/attachment_ajax.php | 141 ++++++++++++++++ actions/attachments.php | 292 ++++++++++++++++++++++++++++++++++ actions/attachments_ajax.php | 115 ++++++++++++++ actions/tag.php | 12 +- classes/File.php | 11 ++ classes/File_oembed.php | 11 +- classes/File_thumbnail.php | 10 ++ classes/Notice.php | 12 +- js/jquery.joverlay.min.js | 6 + js/util.js | 4 + lib/action.php | 12 +- lib/attachmentlist.php | 300 +++++++++++++++++++++++++++++++++++ lib/noticelist.php | 71 ++++++++- lib/router.php | 14 ++ theme/base/images/icons/clip-big.png | Bin 0 -> 11245 bytes theme/base/images/icons/clip.png | Bin 0 -> 2298 bytes 17 files changed, 1243 insertions(+), 18 deletions(-) create mode 100644 actions/attachment.php create mode 100644 actions/attachment_ajax.php create mode 100644 actions/attachments.php create mode 100644 actions/attachments_ajax.php create mode 100644 js/jquery.joverlay.min.js create mode 100644 lib/attachmentlist.php create mode 100644 theme/base/images/icons/clip-big.png create mode 100644 theme/base/images/icons/clip.png (limited to 'lib') diff --git a/actions/attachment.php b/actions/attachment.php new file mode 100644 index 000000000..981882a5b --- /dev/null +++ b/actions/attachment.php @@ -0,0 +1,250 @@ +. + * + * @category Personal + * @package Laconica + * @author Evan Prodromou + * @copyright 2008-2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +//require_once INSTALLDIR.'/lib/personalgroupnav.php'; +//require_once INSTALLDIR.'/lib/feedlist.php'; +require_once INSTALLDIR.'/lib/attachmentlist.php'; + +/** + * Show notice attachments + * + * @category Personal + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +class AttachmentAction extends Action +{ + /** + * Attachment object to show + */ + + var $attachment = null; + + /** + * Profile of the notice object + */ + +// var $profile = null; + + /** + * Avatar of the profile of the notice object + */ + +// var $avatar = null; + + /** + * Load attributes based on database arguments + * + * Loads all the DB stuff + * + * @param array $args $_REQUEST array + * + * @return success flag + */ + + function prepare($args) + { + parent::prepare($args); + + $id = $this->arg('attachment'); + + $this->attachment = File::staticGet($id); + + if (!$this->attachment) { + $this->clientError(_('No such attachment.'), 404); + return false; + } + return true; + } + + /** + * Is this action read-only? + * + * @return boolean true + */ + + function isReadOnly($args) + { + return true; + } + + /** + * Title of the page + * + * @return string title of the page + */ + function title() + { + $a = new Attachment($this->attachment); + return $a->title(); + } + + + + /** + * Last-modified date for page + * + * When was the content of this page last modified? Based on notice, + * profile, avatar. + * + * @return int last-modified date as unix timestamp + */ +/* + function lastModified() + { + return max(strtotime($this->notice->created), + strtotime($this->profile->modified), + ($this->avatar) ? strtotime($this->avatar->modified) : 0); + } +*/ + + /** + * An entity tag for this page + * + * Shows the ETag for the page, based on the notice ID and timestamps + * for the notice, profile, and avatar. It's weak, since we change + * the date text "one hour ago", etc. + * + * @return string etag + */ +/* + function etag() + { + $avtime = ($this->avatar) ? + strtotime($this->avatar->modified) : 0; + + return 'W/"' . implode(':', array($this->arg('action'), + common_language(), + $this->notice->id, + strtotime($this->notice->created), + strtotime($this->profile->modified), + $avtime)) . '"'; + } +*/ + + + /** + * Handle input + * + * Only handles get, so just show the page. + * + * @param array $args $_REQUEST data (unused) + * + * @return void + */ + + function handle($args) + { + parent::handle($args); + $this->showPage(); + } + + /** + * Don't show local navigation + * + * @return void + */ + + function showLocalNavBlock() + { + } + + /** + * Fill the content area of the page + * + * Shows a single notice list item. + * + * @return void + */ + + function showContent() + { + $this->elementStart('ul', array('class' => 'attachments')); + $ali = new Attachment($this->attachment, $this); + $cnt = $ali->show(); + $this->elementEnd('ul'); + } + + /** + * Don't show page notice + * + * @return void + */ + + function showPageNoticeBlock() + { + } + + /** + * Show aside: this attachments appears in what notices + * + * @return void + */ + + function showAside() { + $notice = new Notice; + $f2p = new File_to_post; + $f2p->file_id = $this->attachment->id; + $notice->joinAdd($f2p); + $notice->orderBy('created desc'); + $x = $notice->find(); + $this->elementStart('ol'); + while($notice->fetch()) { + $this->elementStart('li'); + $profile = $notice->getProfile(); + $this->element('a', array('href' => $notice->uri), $profile->nickname . ' on ' . $notice->created); + $this->elementEnd('li'); + } + $this->elementEnd('ol'); + $notice->free(); + $f2p->free(); + + $notice_tag = new Notice_tag; + $attachment = new File; + + $query = 'select tag,count(tag) as c from notice_tag join file_to_post on (notice_tag.notice_id=post_id) join notice on notice_id = notice.id where file_id=' . $notice_tag->escape($this->attachment->id) . ' group by tag order by c desc'; + + $notice_tag->query($query); + $this->elementStart('ol'); + while($notice_tag->fetch()) { + $this->elementStart('li'); + $href = common_local_url('tag', array('tag' => $notice_tag->tag)); + $this->element('a', array('href' => $href), $notice_tag->tag . ' (' . $notice_tag->c . ')'); + $this->elementEnd('li'); + } + $this->elementEnd('ol'); + } +} diff --git a/actions/attachment_ajax.php b/actions/attachment_ajax.php new file mode 100644 index 000000000..1620b27dd --- /dev/null +++ b/actions/attachment_ajax.php @@ -0,0 +1,141 @@ +. + * + * @category Personal + * @package Laconica + * @author Evan Prodromou + * @copyright 2008-2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +require_once INSTALLDIR.'/actions/attachment.php'; + +/** + * Show notice attachments + * + * @category Personal + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +class Attachment_ajaxAction extends AttachmentAction +{ + /** + * Load attributes based on database arguments + * + * Loads all the DB stuff + * + * @param array $args $_REQUEST array + * + * @return success flag + */ + + function prepare($args) + { + parent::prepare($args); + if (!$this->attachment) { + $this->clientError(_('No such attachment.'), 404); + return false; + } + return true; + } + + /** + * Show page, a template method. + * + * @return nothing + */ + function showPage() + { + if (Event::handle('StartShowBody', array($this))) { + $this->showCore(); + Event::handle('EndShowBody', array($this)); + } + } + + /** + * Show core. + * + * Shows local navigation, content block and aside. + * + * @return nothing + */ + function showCore() + { + $this->elementStart('div', array('id' => 'core')); + if (Event::handle('StartShowContentBlock', array($this))) { + $this->showContentBlock(); + Event::handle('EndShowContentBlock', array($this)); + } + $this->elementEnd('div'); + } + + + + /** + * Last-modified date for page + * + * When was the content of this page last modified? Based on notice, + * profile, avatar. + * + * @return int last-modified date as unix timestamp + */ +/* + function lastModified() + { + return max(strtotime($this->notice->created), + strtotime($this->profile->modified), + ($this->avatar) ? strtotime($this->avatar->modified) : 0); + } +*/ + + /** + * An entity tag for this page + * + * Shows the ETag for the page, based on the notice ID and timestamps + * for the notice, profile, and avatar. It's weak, since we change + * the date text "one hour ago", etc. + * + * @return string etag + */ +/* + function etag() + { + $avtime = ($this->avatar) ? + strtotime($this->avatar->modified) : 0; + + return 'W/"' . implode(':', array($this->arg('action'), + common_language(), + $this->notice->id, + strtotime($this->notice->created), + strtotime($this->profile->modified), + $avtime)) . '"'; + } +*/ +} + diff --git a/actions/attachments.php b/actions/attachments.php new file mode 100644 index 000000000..6b31c839d --- /dev/null +++ b/actions/attachments.php @@ -0,0 +1,292 @@ +. + * + * @category Personal + * @package Laconica + * @author Evan Prodromou + * @copyright 2008-2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +//require_once INSTALLDIR.'/lib/personalgroupnav.php'; +//require_once INSTALLDIR.'/lib/feedlist.php'; +require_once INSTALLDIR.'/lib/attachmentlist.php'; + +/** + * Show notice attachments + * + * @category Personal + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +class AttachmentsAction extends Action +{ + /** + * Notice object to show + */ + + var $notice = null; + + /** + * Profile of the notice object + */ + + var $profile = null; + + /** + * Avatar of the profile of the notice object + */ + + var $avatar = null; + + /** + * Is this action read-only? + * + * @return boolean true + */ + + function isReadOnly($args) + { + return true; + } + + /** + * Last-modified date for page + * + * When was the content of this page last modified? Based on notice, + * profile, avatar. + * + * @return int last-modified date as unix timestamp + */ + + function lastModified() + { + return max(strtotime($this->notice->created), + strtotime($this->profile->modified), + ($this->avatar) ? strtotime($this->avatar->modified) : 0); + } + + /** + * An entity tag for this page + * + * Shows the ETag for the page, based on the notice ID and timestamps + * for the notice, profile, and avatar. It's weak, since we change + * the date text "one hour ago", etc. + * + * @return string etag + */ + + function etag() + { + $avtime = ($this->avatar) ? + strtotime($this->avatar->modified) : 0; + + return 'W/"' . implode(':', array($this->arg('action'), + common_language(), + $this->notice->id, + strtotime($this->notice->created), + strtotime($this->profile->modified), + $avtime)) . '"'; + } + + /** + * Title of the page + * + * @return string title of the page + */ + + function title() + { + return sprintf(_('%1$s\'s status on %2$s'), + $this->profile->nickname, + common_exact_date($this->notice->created)); + } + + + /** + * Load attributes based on database arguments + * + * Loads all the DB stuff + * + * @param array $args $_REQUEST array + * + * @return success flag + */ + + function prepare($args) + { + parent::prepare($args); + + $id = $this->arg('notice'); + + $this->notice = Notice::staticGet($id); + + if (!$this->notice) { + $this->clientError(_('No such notice.'), 404); + return false; + } + + +/* +// STOP if there are no attachments +// maybe even redirect if there's a single one +// RYM FIXME TODO + $this->clientError(_('No such attachment.'), 404); + return false; + +*/ + + + + + $this->profile = $this->notice->getProfile(); + + if (!$this->profile) { + $this->serverError(_('Notice has no profile'), 500); + return false; + } + + $this->avatar = $this->profile->getAvatar(AVATAR_PROFILE_SIZE); + return true; + } + + + + /** + * Handle input + * + * Only handles get, so just show the page. + * + * @param array $args $_REQUEST data (unused) + * + * @return void + */ + + function handle($args) + { + parent::handle($args); + + if ($this->notice->is_local == 0) { + if (!empty($this->notice->url)) { + common_redirect($this->notice->url, 301); + } else if (!empty($this->notice->uri) && preg_match('/^https?:/', $this->notice->uri)) { + common_redirect($this->notice->uri, 301); + } + } else { + $f2p = new File_to_post; + $f2p->post_id = $this->notice->id; + $file = new File; + $file->joinAdd($f2p); + $file->selectAdd(); + $file->selectAdd('file.id as id'); + $count = $file->find(true); + if (!$count) return; + if (1 === $count) { + common_redirect(common_local_url('attachment', array('attachment' => $file->id)), 301); + } else { + $this->showPage(); + } + } + } + + /** + * Don't show local navigation + * + * @return void + */ + + function showLocalNavBlock() + { + } + + /** + * Fill the content area of the page + * + * Shows a single notice list item. + * + * @return void + */ + + function showContent() + { + $al = new AttachmentList($this->notice, $this); + $cnt = $al->show(); + } + + /** + * Don't show page notice + * + * @return void + */ + + function showPageNoticeBlock() + { + } + + /** + * Don't show aside + * + * @return void + */ + + function showAside() { + } + + /** + * Extra content + * + * We show the microid(s) for the author, if any. + * + * @return void + */ + + function extraHead() + { + $user = User::staticGet($this->profile->id); + + if (!$user) { + return; + } + + if ($user->emailmicroid && $user->email && $this->notice->uri) { + $id = new Microid('mailto:'. $user->email, + $this->notice->uri); + $this->element('meta', array('name' => 'microid', + 'content' => $id->toString())); + } + + if ($user->jabbermicroid && $user->jabber && $this->notice->uri) { + $id = new Microid('xmpp:', $user->jabber, + $this->notice->uri); + $this->element('meta', array('name' => 'microid', + 'content' => $id->toString())); + } + } +} + diff --git a/actions/attachments_ajax.php b/actions/attachments_ajax.php new file mode 100644 index 000000000..402d8b5e7 --- /dev/null +++ b/actions/attachments_ajax.php @@ -0,0 +1,115 @@ +. + * + * @category Personal + * @package Laconica + * @author Evan Prodromou + * @copyright 2008-2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +//require_once INSTALLDIR.'/lib/personalgroupnav.php'; +//require_once INSTALLDIR.'/lib/feedlist.php'; +require_once INSTALLDIR.'/actions/attachments.php'; + +/** + * Show notice attachments + * + * @category Personal + * @package Laconica + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +class Attachments_ajaxAction extends AttachmentsAction +{ + function showContent() + { + } + + /** + * Fill the content area of the page + * + * Shows a single notice list item. + * + * @return void + */ + + function showContentBlock() + { + $al = new AttachmentList($this->notice, $this); + $cnt = $al->show(); + } + + /** + * Extra content + * + * We show the microid(s) for the author, if any. + * + * @return void + */ + + function extraHead() + { + } + + + /** + * Show page, a template method. + * + * @return nothing + */ + function showPage() + { + if (Event::handle('StartShowBody', array($this))) { + $this->showCore(); + Event::handle('EndShowBody', array($this)); + } + } + + /** + * Show core. + * + * Shows local navigation, content block and aside. + * + * @return nothing + */ + function showCore() + { + $this->elementStart('div', array('id' => 'core')); + if (Event::handle('StartShowContentBlock', array($this))) { + $this->showContentBlock(); + Event::handle('EndShowContentBlock', array($this)); + } + $this->elementEnd('div'); + } + + + + +} + diff --git a/actions/tag.php b/actions/tag.php index 02f3e3522..2202f9bb0 100644 --- a/actions/tag.php +++ b/actions/tag.php @@ -49,8 +49,18 @@ class TagAction extends Action { $pop = new PopularNoticeSection($this); $pop->show(); - } + $notice_tag = new Notice_tag; + $query = 'select file_id, count(file_id) as c from notice_tag join file_to_post on post_id = notice_id where tag="' . $notice_tag->escape($this->tag) . '" group by file_id order by c desc'; + $notice_tag->query($query); + $this->elementStart('ol'); + while ($notice_tag->fetch()) { + $this->elementStart('li'); + $this->element('a', array('class' => 'attachment', 'href' => common_local_url('attachment', array('attachment' => $notice_tag->file_id))), "Attachment tagged {$notice_tag->c} times"); + $this->elementEnd('li'); + } + $this->elementEnd('ol'); + } function title() { diff --git a/classes/File.php b/classes/File.php index 2ddc5deb8..e5913115b 100644 --- a/classes/File.php +++ b/classes/File.php @@ -54,6 +54,17 @@ class File extends Memcached_DataObject return 'http://www.facebook.com/login.php' === $url; } + function getAttachments($post_id) { + $query = "select file.* from file join file_to_post on (file_id = file.id) join notice on (post_id = notice.id) where post_id = " . $this->escape($post_id); + $this->query($query); + $att = array(); + while ($this->fetch()) { + $att[] = clone($this); + } + $this->free(); + return $att; + } + function saveNew($redir_data, $given_url) { $x = new File; $x->url = $given_url; diff --git a/classes/File_oembed.php b/classes/File_oembed.php index 2846f49db..f1b2cb13c 100644 --- a/classes/File_oembed.php +++ b/classes/File_oembed.php @@ -78,18 +78,9 @@ class File_oembed extends Memcached_DataObject if (!empty($data['author_url'])) $file_oembed->author_url = $data['author_url']; if (!empty($data['url'])) $file_oembed->url = $data['url']; $file_oembed->insert(); - if (!empty($data['thumbnail_url'])) { - $tn = new File_thumbnail; - $tn->file_id = $file_id; - $tn->url = $data['thumbnail_url']; - $tn->width = intval($data['thumbnail_width']); - $tn->height = intval($data['thumbnail_height']); - $tn->insert(); + File_thumbnail::saveNew($data, $file_id); } - - - } } diff --git a/classes/File_thumbnail.php b/classes/File_thumbnail.php index 7b906a07c..1a65b92c9 100644 --- a/classes/File_thumbnail.php +++ b/classes/File_thumbnail.php @@ -42,4 +42,14 @@ class File_thumbnail extends Memcached_DataObject /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE + + function saveNew($data, $file_id) { + $tn = new File_thumbnail; + $tn->file_id = $file_id; + $tn->url = $data['thumbnail_url']; + $tn->width = intval($data['thumbnail_width']); + $tn->height = intval($data['thumbnail_height']); + $tn->insert(); + } } + diff --git a/classes/Notice.php b/classes/Notice.php index c2fa2d19e..30508070e 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -124,8 +124,6 @@ class Notice extends Memcached_DataObject $profile = Profile::staticGet($profile_id); -// $final = common_shorten_links($content); - if (!$profile) { common_log(LOG_ERR, 'Problem saving notice. Unknown user.'); return _('Problem saving notice. Unknown user.'); @@ -279,6 +277,16 @@ class Notice extends Memcached_DataObject return true; } + function hasAttachments() { + $post = clone($this); + $query = "select count(file_id) as n_attachments from file join file_to_post on (file_id = file.id) join notice on (post_id = notice.id) where post_id = " . $post->escape($this->id); + $post->query($query); + $post->fetch(); + $n_attachments = intval($post->n_attachments); + $post->free(); + return $n_attachments; + } + function blowCaches($blowLast=false) { $this->blowSubsCache($blowLast); diff --git a/js/jquery.joverlay.min.js b/js/jquery.joverlay.min.js new file mode 100644 index 000000000..c9168506a --- /dev/null +++ b/js/jquery.joverlay.min.js @@ -0,0 +1,6 @@ +/* Copyright (c) 2009 Alvaro A. Lima Jr http://alvarojunior.com/jquery/joverlay.html + * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) + * Version: 0.6 (Abr 23, 2009) + * Requires: jQuery 1.3+ + */ +(function($){var f=$.browser.msie&&$.browser.version==6.0;var g=null;$.fn.jOverlay=function(b){var b=$.extend({},$.fn.jOverlay.options,b);if(g!=null){clearTimeout(g)}var c=this.is('*')?this:'#jOverlayContent';var d=f?'absolute':'fixed';var e=b.imgLoading?"":'';$('body').prepend(e+"
"+"