]> git.mxchange.org Git - quix0rs-gnu-social.git/commitdiff
TagCloud turned into plugin (performance issues on large installs)
authorMikael Nordfeldth <mmn@hethane.se>
Sat, 27 Aug 2016 13:24:25 +0000 (15:24 +0200)
committerMikael Nordfeldth <mmn@hethane.se>
Sat, 27 Aug 2016 13:24:25 +0000 (15:24 +0200)
32 files changed:
actions/all.php
actions/attachment.php
actions/public.php
actions/publictagcloud.php [deleted file]
actions/showstream.php
lib/attachmenttagcloudsection.php [deleted file]
lib/groupaction.php
lib/grouptagcloudsection.php [deleted file]
lib/inboxtagcloudsection.php [deleted file]
lib/personaltagcloudsection.php [deleted file]
lib/publicgroupnav.php
lib/publictagcloudsection.php [deleted file]
lib/router.php
lib/subpeopletagcloudsection.php [deleted file]
lib/subscriberspeopleselftagcloudsection.php [deleted file]
lib/subscriberspeopletagcloudsection.php [deleted file]
lib/subscriptionspeopleselftagcloudsection.php [deleted file]
lib/subscriptionspeopletagcloudsection.php [deleted file]
lib/tagcloudsection.php [deleted file]
plugins/TagCloud/TagCloudPlugin.php [new file with mode: 0644]
plugins/TagCloud/actions/publictagcloud.php [new file with mode: 0644]
plugins/TagCloud/lib/attachmenttagcloudsection.php [new file with mode: 0644]
plugins/TagCloud/lib/grouptagcloudsection.php [new file with mode: 0644]
plugins/TagCloud/lib/inboxtagcloudsection.php [new file with mode: 0644]
plugins/TagCloud/lib/personaltagcloudsection.php [new file with mode: 0644]
plugins/TagCloud/lib/publictagcloudsection.php [new file with mode: 0644]
plugins/TagCloud/lib/subpeopletagcloudsection.php [new file with mode: 0644]
plugins/TagCloud/lib/subscriberspeopleselftagcloudsection.php [new file with mode: 0644]
plugins/TagCloud/lib/subscriberspeopletagcloudsection.php [new file with mode: 0644]
plugins/TagCloud/lib/subscriptionspeopleselftagcloudsection.php [new file with mode: 0644]
plugins/TagCloud/lib/subscriptionspeopletagcloudsection.php [new file with mode: 0644]
plugins/TagCloud/lib/tagcloudsection.php [new file with mode: 0644]

index 19413076b57f89231ba72f8ca333da6d06e5b065..84e4dd53051aa97dc0e8c82b5ca833428a180554 100644 (file)
@@ -170,12 +170,6 @@ class AllAction extends ShowstreamAction
             }
             $ibs->show();
         }
-        // XXX: make this a little more convenient
-
-        if (!common_config('performance', 'high')) {
-            $pop = new InboxTagCloudSection($this, $this->target);
-            $pop->show();
-        }
     }
 }
 
index 3ec837a511f804bcd1d82b764a0103ebc3912261..3f2ae5c1ce0f89aa7081653b850d8090480aafb6 100644 (file)
@@ -132,9 +132,5 @@ class AttachmentAction extends ManagedAction
     function showSections() {
         $ns = new AttachmentNoticeSection($this);
         $ns->show();
-        if (!common_config('performance', 'high')) {
-            $atcs = new AttachmentTagCloudSection($this);
-            $atcs->show();
-        }
     }
 }
index 000f82cb93d5e96b49609cf01676326e9aec6ae3..a2958e8806aa9a74c3991d919eb6179d034ce290 100644 (file)
@@ -86,12 +86,6 @@ class PublicAction extends SitestreamAction
             $ibs->show();
         }
 
-        $p = Profile::current();
-
-        if (!common_config('performance', 'high')) {
-            $cloud = new PublicTagCloudSection($this);
-            $cloud->show();
-        }
         $feat = new FeaturedUsersSection($this);
         $feat->show();
     }
diff --git a/actions/publictagcloud.php b/actions/publictagcloud.php
deleted file mode 100644 (file)
index e557b75..0000000
+++ /dev/null
@@ -1,179 +0,0 @@
-<?php
-/**
- * StatusNet, the distributed open-source microblogging tool
- *
- * Public tag cloud for notices
- *
- * PHP version 5
- *
- * LICENCE: This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- * @category  Public
- * @package   StatusNet
- * @author    Mike Cochrane <mikec@mikenz.geek.nz>
- * @author    Evan Prodromou <evan@status.net>
- * @copyright 2008 Mike Cochrane
- * @copyright 2008-2009 StatusNet, Inc.
- * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link      http://status.net/
- */
-
-if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
-
-define('TAGS_PER_PAGE', 100);
-
-/**
- * Public tag cloud for notices
- *
- * @category Personal
- * @package  StatusNet
- * @author    Mike Cochrane <mikec@mikenz.geek.nz>
- * @author    Evan Prodromou <evan@status.net>
- * @copyright 2008 Mike Cochrane
- * @copyright 2008-2009 StatusNet, Inc.
- * @link     http://status.net/
- */
-class PublictagcloudAction extends Action
-{
-    function isReadOnly($args)
-    {
-        return true;
-    }
-
-    function title()
-    {
-        // TRANS: Title for public tag cloud.
-        return _('Public tag cloud');
-    }
-
-    function showPageNotice()
-    {
-        $this->element('p', 'instructions',
-                       // TRANS: Instructions (more used like an explanation/header).
-                       // TRANS: %s is the StatusNet sitename.
-                       sprintf(_('These are most popular recent tags on %s'),
-                               common_config('site', 'name')));
-    }
-
-    function showEmptyList()
-    {
-        // TRANS: This message contains a Markdown URL. The link description is between
-        // TRANS: square brackets, and the link between parentheses. Do not separate "]("
-        // TRANS: and do not change the URL part.
-        $message = _('No one has posted a notice with a [hashtag](%%doc.tags%%) yet.') . ' ';
-
-        if (common_logged_in()) {
-            // TRANS: Message shown to a logged in user for the public tag cloud
-            // TRANS: while no tags exist yet. "One" refers to the non-existing hashtag.
-            $message .= _('Be the first to post one!');
-        }
-        else {
-            // TRANS: Message shown to a anonymous user for the public tag cloud
-            // TRANS: while no tags exist yet. "One" refers to the non-existing hashtag.
-            // TRANS: This message contains a Markdown URL. The link description is between
-            // TRANS: square brackets, and the link between parentheses. Do not separate "]("
-            // TRANS: and do not change the URL part.
-            $message .= _('Why not [register an account](%%action.register%%) and be the first to post one!');
-        }
-
-        $this->elementStart('div', 'guide');
-        $this->raw(common_markup_to_html($message));
-        $this->elementEnd('div');
-    }
-
-    function handle()
-    {
-        parent::handle();
-        $this->showPage();
-    }
-
-    function showContent()
-    {
-        // This should probably be cached rather than recalculated
-        $tags = new Notice_tag();
-
-        #Need to clear the selection and then only re-add the field
-        #we are grouping by, otherwise it's not a valid 'group by'
-        #even though MySQL seems to let it slide...
-        $tags->selectAdd();
-        $tags->selectAdd('tag');
-
-        #Add the aggregated columns...
-        $tags->selectAdd('max(notice_id) as last_notice_id');
-        $calc = common_sql_weight('created', common_config('tag', 'dropoff'));
-        $cutoff = sprintf("notice_tag.created > '%s'",
-                          common_sql_date(time() - common_config('tag', 'cutoff')));
-        $tags->selectAdd($calc . ' as weight');
-        $tags->whereAdd($cutoff);
-        $tags->groupBy('tag');
-        $tags->orderBy('weight DESC');
-
-        $tags->limit(TAGS_PER_PAGE);
-
-        $cnt = $tags->find();
-
-        if ($cnt > 0) {
-            $this->elementStart('div', array('id' => 'tagcloud',
-                                             'class' => 'section'));
-
-            $tw = array();
-            $sum = 0;
-            while ($tags->fetch()) {
-                $tw[$tags->tag] = $tags->weight;
-                $sum += $tags->weight;
-            }
-
-            ksort($tw);
-
-            $this->elementStart('ul', 'tags xoxo tag-cloud');
-            foreach ($tw as $tag => $weight) {
-                if ($sum) {
-                    $weightedSum = $weight/$sum;
-                } else {
-                    $weightedSum = 0.5;
-                }
-                $this->showTag($tag, $weight, $weightedSum);
-            }
-            $this->elementEnd('ul');
-
-            $this->elementEnd('div');
-        } else {
-            $this->showEmptyList();
-        }
-    }
-
-    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->elementStart('li', $rel);
-        $this->element('a', array('href' => common_local_url('tag', array('tag' => $tag))),
-                       $tag);
-        $this->elementEnd('li');
-    }
-}
index 97b21b12864c73f8a61d8a6279a85030d8ba8163..1e70ecd3ac3fe19ea8084d5efa8c39c3ab701dd5 100644 (file)
@@ -251,15 +251,6 @@ class ShowstreamAction extends NoticestreamAction
         $this->elementEnd('div');
     }
 
-    function showSections()
-    {
-        parent::showSections();
-        if (!common_config('performance', 'high')) {
-            $cloud = new PersonalTagCloudSection($this->target, $this);
-            $cloud->show();
-        }
-    }
-
     function noticeFormOptions()
     {
         $options = parent::noticeFormOptions();
diff --git a/lib/attachmenttagcloudsection.php b/lib/attachmenttagcloudsection.php
deleted file mode 100644 (file)
index 2c8fc5e..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-<?php
-/**
- * StatusNet, the distributed open-source microblogging tool
- *
- * Attachment tag cloud section
- *
- * PHP version 5
- *
- * LICENCE: This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- * @category  Widget
- * @package   StatusNet
- * @author    Evan Prodromou <evan@status.net>
- * @copyright 2009 StatusNet, Inc.
- * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link      http://status.net/
- */
-
-if (!defined('STATUSNET') && !defined('LACONICA')) {
-    exit(1);
-}
-
-/**
- * Attachment tag cloud section
- *
- * @category Widget
- * @package  StatusNet
- * @author   Evan Prodromou <evan@status.net>
- * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link     http://status.net/
- */
-class AttachmentTagCloudSection extends TagCloudSection
-{
-    function title()
-    {
-        // TRANS: Title.
-        return _('Tags for this attachment');
-    }
-
-    function showTag($tag, $weight, $relative)
-    {
-        if ($relative > 0.5) {
-            $rel =  'tag-cloud-7';
-        } else if ($relative > 0.4) {
-            $rel = 'tag-cloud-6';
-        } else if ($relative > 0.3) {
-            $rel = 'tag-cloud-5';
-        } else if ($relative > 0.2) {
-            $rel = 'tag-cloud-4';
-        } else if ($relative > 0.1) {
-            $rel = 'tag-cloud-3';
-        } else if ($relative > 0.05) {
-            $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 getTags()
-    {
-        $notice_tag = new Notice_tag;
-        $query = 'select tag,count(tag) as weight 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->out->attachment->id) . ' group by tag order by weight desc';
-        $notice_tag->query($query);
-        return $notice_tag;
-    }
-}
index 08864607377dbc2e3a357a5499e52bcde7304e40..31a0b8bc345fcfe0c9c3be3a905be6f1b862dcd2 100644 (file)
@@ -112,11 +112,6 @@ class GroupAction extends Action
         }
 
         $this->showAdmins();
-
-        if (!common_config('performance', 'high')) {
-            $cloud = new GroupTagCloudSection($this, $this->group);
-            $cloud->show();
-        }
     }
 
     /**
diff --git a/lib/grouptagcloudsection.php b/lib/grouptagcloudsection.php
deleted file mode 100644 (file)
index 5ed1456..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-<?php
-/**
- * StatusNet, the distributed open-source microblogging tool
- *
- * Personal tag cloud section
- *
- * PHP version 5
- *
- * LICENCE: This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- * @category  Widget
- * @package   StatusNet
- * @author    Evan Prodromou <evan@status.net>
- * @copyright 2009 StatusNet, Inc.
- * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link      http://status.net/
- */
-
-if (!defined('STATUSNET') && !defined('LACONICA')) {
-    exit(1);
-}
-
-/**
- * Group tag cloud section
- *
- * @category Widget
- * @package  StatusNet
- * @author   Evan Prodromou <evan@status.net>
- * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link     http://status.net/
- */
-class GroupTagCloudSection extends TagCloudSection
-{
-    var $group = null;
-
-    function __construct($out=null, $group=null)
-    {
-        parent::__construct($out);
-        $this->group = $group;
-    }
-
-    function title()
-    {
-        // TRANS: Title for group tag cloud section.
-        // TRANS: %s is a group name.
-        return _('Tags');
-    }
-
-    function getTags()
-    {
-        $weightexpr = common_sql_weight('notice_tag.created', common_config('tag', 'dropoff'));
-        // @fixme should we use the cutoff too? Doesn't help with indexing per-group.
-
-        $names = $this->group->getAliases();
-
-        $names = array_merge(array($this->group->nickname), $names);
-
-        // XXX This is dumb.
-
-        $quoted = array();
-
-        foreach ($names as $name) {
-            $quoted[] = "'$name'";
-        }
-
-        $namestring = implode(',', $quoted);
-
-        $qry = 'SELECT notice_tag.tag, '.
-          $weightexpr . ' as weight ' .
-          'FROM notice_tag JOIN notice ' .
-          'ON notice_tag.notice_id = notice.id ' .
-          'JOIN group_inbox on group_inbox.notice_id = notice.id ' .
-          'WHERE group_inbox.group_id = %d ' .
-          'AND notice_tag.tag not in (%s) '.
-          'GROUP BY notice_tag.tag ' .
-          'ORDER BY weight DESC ';
-
-        $limit = TAGS_PER_SECTION;
-        $offset = 0;
-
-        if (common_config('db','type') == 'pgsql') {
-            $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
-        } else {
-            $qry .= ' LIMIT ' . $offset . ', ' . $limit;
-        }
-
-        $tag = Memcached_DataObject::cachedQuery('Notice_tag',
-                                                 sprintf($qry,
-                                                         $this->group->id,
-                                                         $namestring),
-                                                 3600);
-        return $tag;
-    }
-}
diff --git a/lib/inboxtagcloudsection.php b/lib/inboxtagcloudsection.php
deleted file mode 100644 (file)
index 4268ee4..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-<?php
-/**
- * StatusNet, the distributed open-source microblogging tool
- *
- * Personal tag cloud section
- *
- * PHP version 5
- *
- * LICENCE: This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- * @category  Widget
- * @package   StatusNet
- * @author    Evan Prodromou <evan@status.net>
- * @copyright 2009 StatusNet, Inc.
- * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link      http://status.net/
- */
-
-if (!defined('GNUSOCIAL')) { exit(1); }
-
-/**
- * Personal tag cloud section
- *
- * @category Widget
- * @package  StatusNet
- * @author   Evan Prodromou <evan@status.net>
- * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link     http://status.net/
- */
-class InboxTagCloudSection extends TagCloudSection
-{
-    const MAX_NOTICES = 1024;   // legacy value for "Inbox" table size when that existed
-
-    protected $target = null;
-
-    function __construct($out=null, Profile $target)
-    {
-        parent::__construct($out);
-        $this->target = $target;
-    }
-
-    function title()
-    {
-        // TRANS: Title for inbox tag cloud section.
-        return _m('TITLE', 'Trends');
-    }
-
-    function getTags()
-    {
-        // FIXME: Get the Profile::current() value some other way
-        // to avoid confusion between background stuff and session.
-        $stream = new InboxNoticeStream($this->target, Profile::current());
-
-        $ids = $stream->getNoticeIds(0, self::MAX_NOTICES, null, null);
-
-        if (empty($ids)) {
-            $tag = array();
-        } else {
-            $weightexpr = common_sql_weight('notice_tag.created', common_config('tag', 'dropoff'));
-            // @fixme should we use the cutoff too? Doesn't help with indexing per-user.
-
-            $qry = 'SELECT notice_tag.tag, '.
-                $weightexpr . ' as weight ' .
-                'FROM notice_tag JOIN notice ' .
-                'ON notice_tag.notice_id = notice.id ' .
-                'WHERE notice.id in (' . implode(',', $ids) . ')'.
-                'GROUP BY notice_tag.tag ' .
-                'ORDER BY weight DESC ';
-
-            $limit = TAGS_PER_SECTION;
-            $offset = 0;
-
-            if (common_config('db','type') == 'pgsql') {
-                $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
-            } else {
-                $qry .= ' LIMIT ' . $offset . ', ' . $limit;
-            }
-
-            $t = new Notice_tag();
-
-            $t->query($qry);
-
-            $tag = array();
-
-            while ($t->fetch()) {
-                $tag[] = clone($t);
-            }
-        }
-
-        return new ArrayWrapper($tag);
-    }
-
-    function showMore()
-    {
-    }
-}
diff --git a/lib/personaltagcloudsection.php b/lib/personaltagcloudsection.php
deleted file mode 100644 (file)
index 46b4661..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-<?php
-/**
- * StatusNet, the distributed open-source microblogging tool
- *
- * Personal tag cloud section
- *
- * PHP version 5
- *
- * LICENCE: This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- * @category  Widget
- * @package   StatusNet
- * @author    Evan Prodromou <evan@status.net>
- * @copyright 2009 StatusNet, Inc.
- * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link      http://status.net/
- */
-
-if (!defined('GNUSOCIAL')) { exit(1); }
-
-/**
- * Personal tag cloud section
- *
- * @category Widget
- * @package  StatusNet
- * @author   Evan Prodromou <evan@status.net>
- * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link     http://status.net/
- */
-class PersonalTagCloudSection extends TagCloudSection
-{
-    protected $profile = null;
-
-    function __construct(Profile $profile, HTMLOutputter $out=null)
-    {
-        parent::__construct($out);
-        $this->profile = $profile;
-    }
-
-    function title()
-    {
-        // TRANS: Title for personal tag cloud section.
-        return _m('TITLE','Tags');
-    }
-
-    function getTags()
-    {
-        $weightexpr = common_sql_weight('notice_tag.created', common_config('tag', 'dropoff'));
-        // @fixme should we use the cutoff too? Doesn't help with indexing per-user.
-
-        $qry = 'SELECT notice_tag.tag, '.
-          $weightexpr . ' as weight ' .
-          'FROM notice_tag JOIN notice ' .
-          'ON notice_tag.notice_id = notice.id ' .
-          'WHERE notice.profile_id = %d ' .
-          'GROUP BY notice_tag.tag ' .
-          'ORDER BY weight DESC ';
-
-        $limit = TAGS_PER_SECTION;
-        $offset = 0;
-
-        if (common_config('db','type') == 'pgsql') {
-            $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
-        } else {
-            $qry .= ' LIMIT ' . $offset . ', ' . $limit;
-        }
-
-        $tag = Memcached_DataObject::cachedQuery('Notice_tag',
-                                                 sprintf($qry,
-                                                         $this->profile->getID()),
-                                                 3600);
-        return $tag;
-    }
-}
index 620a61ddd95bdd886d67b87bdd907e398b383a42..ef342839d8f6fedf5514db7d19d4959f5fdebbde 100644 (file)
@@ -77,13 +77,6 @@ class PublicGroupNav extends Menu
                 // TRANS: Menu item title in search group navigation panel.
                 _('User groups'), $this->actionName == 'groups', 'nav_groups');
 
-            if (!common_config('performance', 'high')) {
-                // TRANS: Menu item in search group navigation panel.
-                $this->out->menuItem(common_local_url('publictagcloud'), _m('MENU','Recent tags'),
-                                     // TRANS: Menu item title in search group navigation panel.
-                                     _('Recent tags'), $this->actionName == 'publictagcloud', 'nav_recent-tags');
-            }
-
             if (count(common_config('nickname', 'featured')) > 0) {
                 // TRANS: Menu item in search group navigation panel.
                 $this->out->menuItem(common_local_url('featured'), _m('MENU','Featured'),
diff --git a/lib/publictagcloudsection.php b/lib/publictagcloudsection.php
deleted file mode 100644 (file)
index bf88091..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-<?php
-/**
- * StatusNet, the distributed open-source microblogging tool
- *
- * Public tag cloud section
- *
- * PHP version 5
- *
- * LICENCE: This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- * @category  Widget
- * @package   StatusNet
- * @author    Evan Prodromou <evan@status.net>
- * @copyright 2009 StatusNet, Inc.
- * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link      http://status.net/
- */
-
-if (!defined('STATUSNET') && !defined('LACONICA')) {
-    exit(1);
-}
-
-/**
- * Public tag cloud section
- *
- * @category Widget
- * @package  StatusNet
- * @author   Evan Prodromou <evan@status.net>
- * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link     http://status.net/
- */
-class PublicTagCloudSection extends TagCloudSection
-{
-    function __construct($out=null)
-    {
-        parent::__construct($out);
-    }
-
-    function title()
-    {
-        // TRANS: Title for inbox tag cloud section.
-        return _m('TITLE', 'Trends');
-    }
-
-    function getTags()
-    {
-        $profile = Profile::current();
-
-        if (empty($profile)) {
-            $keypart = sprintf('Notice:public_tag_cloud:null');
-        } else {
-            $keypart = sprintf('Notice:public_tag_cloud:%d', $profile->id);
-        }
-
-        $tag = Memcached_DataObject::cacheGet($keypart);
-
-        if ($tag === false) {
-
-            $stream = new PublicNoticeStream($profile);
-
-            $ids = $stream->getNoticeIds(0, 500, null, null);
-
-            if (empty($ids)) {
-                $tag = array();
-            } else {
-                $weightexpr = common_sql_weight('notice_tag.created', common_config('tag', 'dropoff'));
-                // @fixme should we use the cutoff too? Doesn't help with indexing per-user.
-
-                $qry = 'SELECT notice_tag.tag, '.
-                    $weightexpr . ' as weight ' .
-                    'FROM notice_tag JOIN notice ' .
-                    'ON notice_tag.notice_id = notice.id ' .
-                    'WHERE notice.id in (' . implode(',', $ids) . ') '.
-                    'GROUP BY notice_tag.tag ' .
-                    'ORDER BY weight DESC ';
-
-                $limit = TAGS_PER_SECTION;
-                $offset = 0;
-
-                if (common_config('db','type') == 'pgsql') {
-                    $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
-                } else {
-                    $qry .= ' LIMIT ' . $offset . ', ' . $limit;
-                }
-
-                $t = new Notice_tag();
-
-                $t->query($qry);
-
-                $tag = array();
-
-                while ($t->fetch()) {
-                    $tag[] = clone($t);
-                }
-            }
-
-            Memcached_DataObject::cacheSet($keypart, $tag, 60 * 60 * 24);
-        }
-
-        return new ArrayWrapper($tag);
-    }
-
-    function showMore()
-    {
-    }
-}
index b01c9a767797db17bce0d7ef2d411fb4a64e7fd9..cd464d841cdfdf37a1416f8288cf85bd5896a86c 100644 (file)
@@ -260,12 +260,6 @@ class Router
                         array('action' => 'userbyid'),
                         array('id' => '[0-9]+'));
 
-            if (!common_config('performance', 'high')) {
-                $m->connect('tags/', array('action' => 'publictagcloud'));
-                $m->connect('tag/', array('action' => 'publictagcloud'));
-                $m->connect('tags', array('action' => 'publictagcloud'));
-                $m->connect('tag', array('action' => 'publictagcloud'));
-            }
             $m->connect('tag/:tag/rss',
                         array('action' => 'tagrss'),
                         array('tag' => self::REGEX_TAG));
diff --git a/lib/subpeopletagcloudsection.php b/lib/subpeopletagcloudsection.php
deleted file mode 100644 (file)
index b23a822..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-<?php
-/**
- * StatusNet, the distributed open-source microblogging tool
- *
- * Personal tag cloud section
- *
- * PHP version 5
- *
- * LICENCE: This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- * @category  Widget
- * @package   StatusNet
- * @author    Evan Prodromou <evan@status.net>
- * @copyright 2009 StatusNet, Inc.
- * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link      http://status.net/
- */
-
-if (!defined('STATUSNET') && !defined('LACONICA')) {
-    exit(1);
-}
-
-/**
- * Personal tag cloud section
- *
- * @category Widget
- * @package  StatusNet
- * @author   Evan Prodromou <evan@status.net>
- * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link     http://status.net/
- */
-
-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
deleted file mode 100644 (file)
index ddbf389..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-<?php
-/**
- * StatusNet, the distributed open-source microblogging tool
- *
- * Personal tag cloud section
- *
- * PHP version 5
- *
- * LICENCE: This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- * @category  Widget
- * @package   StatusNet
- * @author    Evan Prodromou <evan@status.net>
- * @copyright 2009 StatusNet, Inc.
- * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link      http://status.net/
- */
-
-if (!defined('STATUSNET') && !defined('LACONICA')) {
-    exit(1);
-}
-
-/**
- * Personal tag cloud section
- *
- * @category Widget
- * @package  StatusNet
- * @author   Evan Prodromou <evan@status.net>
- * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link     http://status.net/
- */
-class SubscribersPeopleSelfTagCloudSection extends SubPeopleTagCloudSection
-{
-    function title()
-    {
-        // TRANS: Title of personal tag cloud section.
-        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';
-
-        return 'select profile_tag.tag, count(profile_tag.tag) as weight from subscription left join (profile_tag, profile_list) on  profile_list.tag =  profile_tag.tag and profile_list.tagger =  profile_tag.tagger and profile_tag.tagger = subscriber where subscribed=%d and subscribed != subscriber and profile_tag.tagger = tagged and profile_list.private = false and profile_tag.tag is not null group by profile_tag.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
deleted file mode 100644 (file)
index c3602a6..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-<?php
-/**
- * StatusNet, the distributed open-source microblogging tool
- *
- * Personal tag cloud section
- *
- * PHP version 5
- *
- * LICENCE: This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- * @category  Widget
- * @package   StatusNet
- * @author    Evan Prodromou <evan@status.net>
- * @copyright 2009 StatusNet, Inc.
- * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link      http://status.net/
- */
-
-if (!defined('STATUSNET') && !defined('LACONICA')) {
-    exit(1);
-}
-
-/**
- * Personal tag cloud section
- *
- * @category Widget
- * @package  StatusNet
- * @author   Evan Prodromou <evan@status.net>
- * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link     http://status.net/
- */
-class SubscribersPeopleTagCloudSection extends SubPeopleTagCloudSection
-{
-    function title()
-    {
-        // TRANS: Title of personal tag cloud section.
-        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';
-        return 'select profile_tag.tag, count(profile_tag.tag) as weight from subscription left join (profile_tag, profile_list) on subscriber=profile_tag.tagged and subscribed=profile_tag.tagger and profile_tag.tagger = profile_list.tagger and profile_tag.tag = profile_list.tag where subscribed=%d and subscriber != subscribed and profile_list.private = false and profile_tag.tag is not null group by profile_tag.tag order by weight desc';
-    }
-}
diff --git a/lib/subscriptionspeopleselftagcloudsection.php b/lib/subscriptionspeopleselftagcloudsection.php
deleted file mode 100644 (file)
index 7334234..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-<?php
-/**
- * StatusNet, the distributed open-source microblogging tool
- *
- * Personal tag cloud section
- *
- * PHP version 5
- *
- * LICENCE: This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- * @category  Widget
- * @package   StatusNet
- * @author    Evan Prodromou <evan@status.net>
- * @copyright 2009 StatusNet, Inc.
- * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link      http://status.net/
- */
-
-if (!defined('STATUSNET') && !defined('LACONICA')) {
-    exit(1);
-}
-
-/**
- * Personal tag cloud section
- *
- * @category Widget
- * @package  StatusNet
- * @author   Evan Prodromou <evan@status.net>
- * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link     http://status.net/
- */
-class SubscriptionsPeopleSelfTagCloudSection extends SubPeopleTagCloudSection
-{
-    function title()
-    {
-        // TRANS: Title of personal tag cloud section.
-        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';
-
-        return 'select profile_tag.tag, count(profile_tag.tag) as weight from subscription left join (profile_tag, profile_list) on profile_tag.tagger = subscribed and profile_tag.tag = profile_list.tag and profile_tag.tagger = profile_tag.tagger where subscriber=%d and subscribed != subscriber and profile_tag.tagger = profile_tag.tagged and profile_list.private = false and profile_tag.tag is not null group by profile_tag.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
deleted file mode 100644 (file)
index e101640..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-<?php
-/**
- * StatusNet, the distributed open-source microblogging tool
- *
- * Personal tag cloud section
- *
- * PHP version 5
- *
- * LICENCE: This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- * @category  Widget
- * @package   StatusNet
- * @author    Evan Prodromou <evan@status.net>
- * @copyright 2009 StatusNet, Inc.
- * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link      http://status.net/
- */
-
-if (!defined('STATUSNET') && !defined('LACONICA')) {
-    exit(1);
-}
-
-/**
- * Personal tag cloud section
- *
- * @category Widget
- * @package  StatusNet
- * @author   Evan Prodromou <evan@status.net>
- * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link     http://status.net/
- */
-class SubscriptionsPeopleTagCloudSection extends SubPeopleTagCloudSection
-{
-    function title()
-    {
-        // TRANS: Title of personal tag cloud section.
-        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';
-        return 'select profile_tag.tag, count(profile_tag.tag) as weight from subscription left join (profile_tag, profile_list) on subscriber=profile_tag.tagger and subscribed=tagged and profile_tag.tag = profile_list.tag and profile_tag.tagger = profile_list.tagger where subscriber=%d and subscriber != subscribed and profile_list.private = false and profile_tag.tag is not null group by profile_tag.tag order by weight desc';
-    }
-}
diff --git a/lib/tagcloudsection.php b/lib/tagcloudsection.php
deleted file mode 100644 (file)
index 80a9042..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-<?php
-/**
- * StatusNet, the distributed open-source microblogging tool
- *
- * Base class for sections showing tag clouds
- *
- * PHP version 5
- *
- * LICENCE: This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- * @category  Widget
- * @package   StatusNet
- * @author    Evan Prodromou <evan@status.net>
- * @copyright 2009 StatusNet, Inc.
- * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link      http://status.net/
- */
-
-if (!defined('STATUSNET') && !defined('LACONICA')) {
-    exit(1);
-}
-
-define('TAGS_PER_SECTION', 10);
-
-/**
- * Base class for sections
- *
- * These are the widgets that show interesting data about a person
- * group, or site.
- *
- * @category Widget
- * @package  StatusNet
- * @author   Evan Prodromou <evan@status.net>
- * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link     http://status.net/
- */
-class TagCloudSection extends Section
-{
-    function showContent()
-    {
-        $tags = $this->getTags();
-
-        if (!$tags) {
-            // TRANS: Content displayed in a tag cloud section if there are no tags.
-            $this->out->element('p', null, _m('NOTAGS','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) {
-            // TRANS: Content displayed in a tag cloud section if there are no tags.
-            $this->out->element('p', null, _m('NOTAGS','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)
-    {
-        if ($this->out instanceof ShowstreamAction) {
-            return common_local_url('showstream', array('nickname' => $this->out->getTarget()->getNickname(), 'tag' => $tag));
-        }
-        return common_local_url('tag', array('tag' => $tag));
-    }
-
-    function divId()
-    {
-        return 'tagcloud';
-    }
-}
diff --git a/plugins/TagCloud/TagCloudPlugin.php b/plugins/TagCloud/TagCloudPlugin.php
new file mode 100644 (file)
index 0000000..c616be7
--- /dev/null
@@ -0,0 +1,70 @@
+<?php
+/**
+ * GNU social plugin for "tag clouds" in the UI
+ *
+ * @category  UI
+ * @package   GNUsocial
+ * @author    Mikael Nordfeldth <mmn@hethane.se>
+ * @copyright 2016 Free Software Foundation, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://gnu.io/social/
+ */
+
+if (!defined('GNUSOCIAL')) { exit(1); }
+
+class TagCloudPlugin extends Plugin {
+
+    public function onRouterInitialized(URLMapper $m)
+    {
+        $m->connect('tags/', array('action' => 'publictagcloud'));
+        $m->connect('tag/', array('action' => 'publictagcloud'));
+        $m->connect('tags', array('action' => 'publictagcloud'));
+        $m->connect('tag', array('action' => 'publictagcloud'));
+    }
+
+    public function onEndPublicGroupNav(Menu $menu)
+    {
+        // TRANS: Menu item in search group navigation panel.
+        $menu->out->menuItem(common_local_url('publictagcloud'), _m('MENU','Recent tags'),
+                             // TRANS: Menu item title in search group navigation panel.
+                             _('Recent tags'), $menu->actionName === 'publictagcloud', 'nav_recent-tags');
+    }
+
+    public function onEndShowSections(Action $action)
+    {
+        $cloud = null;
+
+        switch (true) {
+        case $action instanceof AllAction:
+            $cloud = new InboxTagCloudSection($action, $action->getTarget());
+            break;
+        case $action instanceof AttachmentAction:
+            $cloud = new AttachmentTagCloudSection($action);
+            break;
+        case $action instanceof PublicAction:
+            $cloud = new PublicTagCloudSection($action);
+            break;
+        case $action instanceof ShowstreamAction:
+            $cloud = new PersonalTagCloudSection($action, $action->getTarget());
+            break;
+        case $action instanceof GroupAction:
+            $cloud = new GroupTagCloudSection($action, $action->getGroup());
+        }
+
+        if (!is_null($cloud)) {
+            $cloud->show();
+        }
+    }
+
+    public function onPluginVersion(array &$versions)
+    {
+        $versions[] = array('name' => 'TagCloud',
+                            'version' => GNUSOCIAL_VERSION,
+                            'author' => 'Mikael Nordfeldth',
+                            'homepage' => 'https://gnu.io/social',
+                            'description' =>
+                            // TRANS: Plugin description.
+                            _m('Adds tag clouds to stream pages'));
+        return true;
+    }
+}
diff --git a/plugins/TagCloud/actions/publictagcloud.php b/plugins/TagCloud/actions/publictagcloud.php
new file mode 100644 (file)
index 0000000..e557b75
--- /dev/null
@@ -0,0 +1,179 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Public tag cloud for notices
+ *
+ * PHP version 5
+ *
+ * LICENCE: This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category  Public
+ * @package   StatusNet
+ * @author    Mike Cochrane <mikec@mikenz.geek.nz>
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2008 Mike Cochrane
+ * @copyright 2008-2009 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link      http://status.net/
+ */
+
+if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
+
+define('TAGS_PER_PAGE', 100);
+
+/**
+ * Public tag cloud for notices
+ *
+ * @category Personal
+ * @package  StatusNet
+ * @author    Mike Cochrane <mikec@mikenz.geek.nz>
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2008 Mike Cochrane
+ * @copyright 2008-2009 StatusNet, Inc.
+ * @link     http://status.net/
+ */
+class PublictagcloudAction extends Action
+{
+    function isReadOnly($args)
+    {
+        return true;
+    }
+
+    function title()
+    {
+        // TRANS: Title for public tag cloud.
+        return _('Public tag cloud');
+    }
+
+    function showPageNotice()
+    {
+        $this->element('p', 'instructions',
+                       // TRANS: Instructions (more used like an explanation/header).
+                       // TRANS: %s is the StatusNet sitename.
+                       sprintf(_('These are most popular recent tags on %s'),
+                               common_config('site', 'name')));
+    }
+
+    function showEmptyList()
+    {
+        // TRANS: This message contains a Markdown URL. The link description is between
+        // TRANS: square brackets, and the link between parentheses. Do not separate "]("
+        // TRANS: and do not change the URL part.
+        $message = _('No one has posted a notice with a [hashtag](%%doc.tags%%) yet.') . ' ';
+
+        if (common_logged_in()) {
+            // TRANS: Message shown to a logged in user for the public tag cloud
+            // TRANS: while no tags exist yet. "One" refers to the non-existing hashtag.
+            $message .= _('Be the first to post one!');
+        }
+        else {
+            // TRANS: Message shown to a anonymous user for the public tag cloud
+            // TRANS: while no tags exist yet. "One" refers to the non-existing hashtag.
+            // TRANS: This message contains a Markdown URL. The link description is between
+            // TRANS: square brackets, and the link between parentheses. Do not separate "]("
+            // TRANS: and do not change the URL part.
+            $message .= _('Why not [register an account](%%action.register%%) and be the first to post one!');
+        }
+
+        $this->elementStart('div', 'guide');
+        $this->raw(common_markup_to_html($message));
+        $this->elementEnd('div');
+    }
+
+    function handle()
+    {
+        parent::handle();
+        $this->showPage();
+    }
+
+    function showContent()
+    {
+        // This should probably be cached rather than recalculated
+        $tags = new Notice_tag();
+
+        #Need to clear the selection and then only re-add the field
+        #we are grouping by, otherwise it's not a valid 'group by'
+        #even though MySQL seems to let it slide...
+        $tags->selectAdd();
+        $tags->selectAdd('tag');
+
+        #Add the aggregated columns...
+        $tags->selectAdd('max(notice_id) as last_notice_id');
+        $calc = common_sql_weight('created', common_config('tag', 'dropoff'));
+        $cutoff = sprintf("notice_tag.created > '%s'",
+                          common_sql_date(time() - common_config('tag', 'cutoff')));
+        $tags->selectAdd($calc . ' as weight');
+        $tags->whereAdd($cutoff);
+        $tags->groupBy('tag');
+        $tags->orderBy('weight DESC');
+
+        $tags->limit(TAGS_PER_PAGE);
+
+        $cnt = $tags->find();
+
+        if ($cnt > 0) {
+            $this->elementStart('div', array('id' => 'tagcloud',
+                                             'class' => 'section'));
+
+            $tw = array();
+            $sum = 0;
+            while ($tags->fetch()) {
+                $tw[$tags->tag] = $tags->weight;
+                $sum += $tags->weight;
+            }
+
+            ksort($tw);
+
+            $this->elementStart('ul', 'tags xoxo tag-cloud');
+            foreach ($tw as $tag => $weight) {
+                if ($sum) {
+                    $weightedSum = $weight/$sum;
+                } else {
+                    $weightedSum = 0.5;
+                }
+                $this->showTag($tag, $weight, $weightedSum);
+            }
+            $this->elementEnd('ul');
+
+            $this->elementEnd('div');
+        } else {
+            $this->showEmptyList();
+        }
+    }
+
+    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->elementStart('li', $rel);
+        $this->element('a', array('href' => common_local_url('tag', array('tag' => $tag))),
+                       $tag);
+        $this->elementEnd('li');
+    }
+}
diff --git a/plugins/TagCloud/lib/attachmenttagcloudsection.php b/plugins/TagCloud/lib/attachmenttagcloudsection.php
new file mode 100644 (file)
index 0000000..2c8fc5e
--- /dev/null
@@ -0,0 +1,82 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Attachment tag cloud section
+ *
+ * PHP version 5
+ *
+ * LICENCE: This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category  Widget
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link      http://status.net/
+ */
+
+if (!defined('STATUSNET') && !defined('LACONICA')) {
+    exit(1);
+}
+
+/**
+ * Attachment tag cloud section
+ *
+ * @category Widget
+ * @package  StatusNet
+ * @author   Evan Prodromou <evan@status.net>
+ * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link     http://status.net/
+ */
+class AttachmentTagCloudSection extends TagCloudSection
+{
+    function title()
+    {
+        // TRANS: Title.
+        return _('Tags for this attachment');
+    }
+
+    function showTag($tag, $weight, $relative)
+    {
+        if ($relative > 0.5) {
+            $rel =  'tag-cloud-7';
+        } else if ($relative > 0.4) {
+            $rel = 'tag-cloud-6';
+        } else if ($relative > 0.3) {
+            $rel = 'tag-cloud-5';
+        } else if ($relative > 0.2) {
+            $rel = 'tag-cloud-4';
+        } else if ($relative > 0.1) {
+            $rel = 'tag-cloud-3';
+        } else if ($relative > 0.05) {
+            $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 getTags()
+    {
+        $notice_tag = new Notice_tag;
+        $query = 'select tag,count(tag) as weight 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->out->attachment->id) . ' group by tag order by weight desc';
+        $notice_tag->query($query);
+        return $notice_tag;
+    }
+}
diff --git a/plugins/TagCloud/lib/grouptagcloudsection.php b/plugins/TagCloud/lib/grouptagcloudsection.php
new file mode 100644 (file)
index 0000000..5ed1456
--- /dev/null
@@ -0,0 +1,105 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Personal tag cloud section
+ *
+ * PHP version 5
+ *
+ * LICENCE: This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category  Widget
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link      http://status.net/
+ */
+
+if (!defined('STATUSNET') && !defined('LACONICA')) {
+    exit(1);
+}
+
+/**
+ * Group tag cloud section
+ *
+ * @category Widget
+ * @package  StatusNet
+ * @author   Evan Prodromou <evan@status.net>
+ * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link     http://status.net/
+ */
+class GroupTagCloudSection extends TagCloudSection
+{
+    var $group = null;
+
+    function __construct($out=null, $group=null)
+    {
+        parent::__construct($out);
+        $this->group = $group;
+    }
+
+    function title()
+    {
+        // TRANS: Title for group tag cloud section.
+        // TRANS: %s is a group name.
+        return _('Tags');
+    }
+
+    function getTags()
+    {
+        $weightexpr = common_sql_weight('notice_tag.created', common_config('tag', 'dropoff'));
+        // @fixme should we use the cutoff too? Doesn't help with indexing per-group.
+
+        $names = $this->group->getAliases();
+
+        $names = array_merge(array($this->group->nickname), $names);
+
+        // XXX This is dumb.
+
+        $quoted = array();
+
+        foreach ($names as $name) {
+            $quoted[] = "'$name'";
+        }
+
+        $namestring = implode(',', $quoted);
+
+        $qry = 'SELECT notice_tag.tag, '.
+          $weightexpr . ' as weight ' .
+          'FROM notice_tag JOIN notice ' .
+          'ON notice_tag.notice_id = notice.id ' .
+          'JOIN group_inbox on group_inbox.notice_id = notice.id ' .
+          'WHERE group_inbox.group_id = %d ' .
+          'AND notice_tag.tag not in (%s) '.
+          'GROUP BY notice_tag.tag ' .
+          'ORDER BY weight DESC ';
+
+        $limit = TAGS_PER_SECTION;
+        $offset = 0;
+
+        if (common_config('db','type') == 'pgsql') {
+            $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
+        } else {
+            $qry .= ' LIMIT ' . $offset . ', ' . $limit;
+        }
+
+        $tag = Memcached_DataObject::cachedQuery('Notice_tag',
+                                                 sprintf($qry,
+                                                         $this->group->id,
+                                                         $namestring),
+                                                 3600);
+        return $tag;
+    }
+}
diff --git a/plugins/TagCloud/lib/inboxtagcloudsection.php b/plugins/TagCloud/lib/inboxtagcloudsection.php
new file mode 100644 (file)
index 0000000..4268ee4
--- /dev/null
@@ -0,0 +1,107 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Personal tag cloud section
+ *
+ * PHP version 5
+ *
+ * LICENCE: This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category  Widget
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link      http://status.net/
+ */
+
+if (!defined('GNUSOCIAL')) { exit(1); }
+
+/**
+ * Personal tag cloud section
+ *
+ * @category Widget
+ * @package  StatusNet
+ * @author   Evan Prodromou <evan@status.net>
+ * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link     http://status.net/
+ */
+class InboxTagCloudSection extends TagCloudSection
+{
+    const MAX_NOTICES = 1024;   // legacy value for "Inbox" table size when that existed
+
+    protected $target = null;
+
+    function __construct($out=null, Profile $target)
+    {
+        parent::__construct($out);
+        $this->target = $target;
+    }
+
+    function title()
+    {
+        // TRANS: Title for inbox tag cloud section.
+        return _m('TITLE', 'Trends');
+    }
+
+    function getTags()
+    {
+        // FIXME: Get the Profile::current() value some other way
+        // to avoid confusion between background stuff and session.
+        $stream = new InboxNoticeStream($this->target, Profile::current());
+
+        $ids = $stream->getNoticeIds(0, self::MAX_NOTICES, null, null);
+
+        if (empty($ids)) {
+            $tag = array();
+        } else {
+            $weightexpr = common_sql_weight('notice_tag.created', common_config('tag', 'dropoff'));
+            // @fixme should we use the cutoff too? Doesn't help with indexing per-user.
+
+            $qry = 'SELECT notice_tag.tag, '.
+                $weightexpr . ' as weight ' .
+                'FROM notice_tag JOIN notice ' .
+                'ON notice_tag.notice_id = notice.id ' .
+                'WHERE notice.id in (' . implode(',', $ids) . ')'.
+                'GROUP BY notice_tag.tag ' .
+                'ORDER BY weight DESC ';
+
+            $limit = TAGS_PER_SECTION;
+            $offset = 0;
+
+            if (common_config('db','type') == 'pgsql') {
+                $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
+            } else {
+                $qry .= ' LIMIT ' . $offset . ', ' . $limit;
+            }
+
+            $t = new Notice_tag();
+
+            $t->query($qry);
+
+            $tag = array();
+
+            while ($t->fetch()) {
+                $tag[] = clone($t);
+            }
+        }
+
+        return new ArrayWrapper($tag);
+    }
+
+    function showMore()
+    {
+    }
+}
diff --git a/plugins/TagCloud/lib/personaltagcloudsection.php b/plugins/TagCloud/lib/personaltagcloudsection.php
new file mode 100644 (file)
index 0000000..e46aa2d
--- /dev/null
@@ -0,0 +1,85 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Personal tag cloud section
+ *
+ * PHP version 5
+ *
+ * LICENCE: This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category  Widget
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link      http://status.net/
+ */
+
+if (!defined('GNUSOCIAL')) { exit(1); }
+
+/**
+ * Personal tag cloud section
+ *
+ * @category Widget
+ * @package  StatusNet
+ * @author   Evan Prodromou <evan@status.net>
+ * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link     http://status.net/
+ */
+class PersonalTagCloudSection extends TagCloudSection
+{
+    protected $profile = null;
+
+    function __construct(HTMLOutputter $out, Profile $profile)
+    {
+        parent::__construct($out);
+        $this->profile = $profile;
+    }
+
+    function title()
+    {
+        // TRANS: Title for personal tag cloud section.
+        return _m('TITLE','Tags');
+    }
+
+    function getTags()
+    {
+        $weightexpr = common_sql_weight('notice_tag.created', common_config('tag', 'dropoff'));
+        // @fixme should we use the cutoff too? Doesn't help with indexing per-user.
+
+        $qry = 'SELECT notice_tag.tag, '.
+          $weightexpr . ' as weight ' .
+          'FROM notice_tag JOIN notice ' .
+          'ON notice_tag.notice_id = notice.id ' .
+          'WHERE notice.profile_id = %d ' .
+          'GROUP BY notice_tag.tag ' .
+          'ORDER BY weight DESC ';
+
+        $limit = TAGS_PER_SECTION;
+        $offset = 0;
+
+        if (common_config('db','type') == 'pgsql') {
+            $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
+        } else {
+            $qry .= ' LIMIT ' . $offset . ', ' . $limit;
+        }
+
+        $tag = Memcached_DataObject::cachedQuery('Notice_tag',
+                                                 sprintf($qry,
+                                                         $this->profile->getID()),
+                                                 3600);
+        return $tag;
+    }
+}
diff --git a/plugins/TagCloud/lib/publictagcloudsection.php b/plugins/TagCloud/lib/publictagcloudsection.php
new file mode 100644 (file)
index 0000000..bf88091
--- /dev/null
@@ -0,0 +1,117 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Public tag cloud section
+ *
+ * PHP version 5
+ *
+ * LICENCE: This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category  Widget
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link      http://status.net/
+ */
+
+if (!defined('STATUSNET') && !defined('LACONICA')) {
+    exit(1);
+}
+
+/**
+ * Public tag cloud section
+ *
+ * @category Widget
+ * @package  StatusNet
+ * @author   Evan Prodromou <evan@status.net>
+ * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link     http://status.net/
+ */
+class PublicTagCloudSection extends TagCloudSection
+{
+    function __construct($out=null)
+    {
+        parent::__construct($out);
+    }
+
+    function title()
+    {
+        // TRANS: Title for inbox tag cloud section.
+        return _m('TITLE', 'Trends');
+    }
+
+    function getTags()
+    {
+        $profile = Profile::current();
+
+        if (empty($profile)) {
+            $keypart = sprintf('Notice:public_tag_cloud:null');
+        } else {
+            $keypart = sprintf('Notice:public_tag_cloud:%d', $profile->id);
+        }
+
+        $tag = Memcached_DataObject::cacheGet($keypart);
+
+        if ($tag === false) {
+
+            $stream = new PublicNoticeStream($profile);
+
+            $ids = $stream->getNoticeIds(0, 500, null, null);
+
+            if (empty($ids)) {
+                $tag = array();
+            } else {
+                $weightexpr = common_sql_weight('notice_tag.created', common_config('tag', 'dropoff'));
+                // @fixme should we use the cutoff too? Doesn't help with indexing per-user.
+
+                $qry = 'SELECT notice_tag.tag, '.
+                    $weightexpr . ' as weight ' .
+                    'FROM notice_tag JOIN notice ' .
+                    'ON notice_tag.notice_id = notice.id ' .
+                    'WHERE notice.id in (' . implode(',', $ids) . ') '.
+                    'GROUP BY notice_tag.tag ' .
+                    'ORDER BY weight DESC ';
+
+                $limit = TAGS_PER_SECTION;
+                $offset = 0;
+
+                if (common_config('db','type') == 'pgsql') {
+                    $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
+                } else {
+                    $qry .= ' LIMIT ' . $offset . ', ' . $limit;
+                }
+
+                $t = new Notice_tag();
+
+                $t->query($qry);
+
+                $tag = array();
+
+                while ($t->fetch()) {
+                    $tag[] = clone($t);
+                }
+            }
+
+            Memcached_DataObject::cacheSet($keypart, $tag, 60 * 60 * 24);
+        }
+
+        return new ArrayWrapper($tag);
+    }
+
+    function showMore()
+    {
+    }
+}
diff --git a/plugins/TagCloud/lib/subpeopletagcloudsection.php b/plugins/TagCloud/lib/subpeopletagcloudsection.php
new file mode 100644 (file)
index 0000000..b23a822
--- /dev/null
@@ -0,0 +1,77 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Personal tag cloud section
+ *
+ * PHP version 5
+ *
+ * LICENCE: This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category  Widget
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link      http://status.net/
+ */
+
+if (!defined('STATUSNET') && !defined('LACONICA')) {
+    exit(1);
+}
+
+/**
+ * Personal tag cloud section
+ *
+ * @category Widget
+ * @package  StatusNet
+ * @author   Evan Prodromou <evan@status.net>
+ * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link     http://status.net/
+ */
+
+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/plugins/TagCloud/lib/subscriberspeopleselftagcloudsection.php b/plugins/TagCloud/lib/subscriberspeopleselftagcloudsection.php
new file mode 100644 (file)
index 0000000..ddbf389
--- /dev/null
@@ -0,0 +1,58 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Personal tag cloud section
+ *
+ * PHP version 5
+ *
+ * LICENCE: This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category  Widget
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link      http://status.net/
+ */
+
+if (!defined('STATUSNET') && !defined('LACONICA')) {
+    exit(1);
+}
+
+/**
+ * Personal tag cloud section
+ *
+ * @category Widget
+ * @package  StatusNet
+ * @author   Evan Prodromou <evan@status.net>
+ * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link     http://status.net/
+ */
+class SubscribersPeopleSelfTagCloudSection extends SubPeopleTagCloudSection
+{
+    function title()
+    {
+        // TRANS: Title of personal tag cloud section.
+        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';
+
+        return 'select profile_tag.tag, count(profile_tag.tag) as weight from subscription left join (profile_tag, profile_list) on  profile_list.tag =  profile_tag.tag and profile_list.tagger =  profile_tag.tagger and profile_tag.tagger = subscriber where subscribed=%d and subscribed != subscriber and profile_tag.tagger = tagged and profile_list.private = false and profile_tag.tag is not null group by profile_tag.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/plugins/TagCloud/lib/subscriberspeopletagcloudsection.php b/plugins/TagCloud/lib/subscriberspeopletagcloudsection.php
new file mode 100644 (file)
index 0000000..c3602a6
--- /dev/null
@@ -0,0 +1,60 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Personal tag cloud section
+ *
+ * PHP version 5
+ *
+ * LICENCE: This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category  Widget
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link      http://status.net/
+ */
+
+if (!defined('STATUSNET') && !defined('LACONICA')) {
+    exit(1);
+}
+
+/**
+ * Personal tag cloud section
+ *
+ * @category Widget
+ * @package  StatusNet
+ * @author   Evan Prodromou <evan@status.net>
+ * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link     http://status.net/
+ */
+class SubscribersPeopleTagCloudSection extends SubPeopleTagCloudSection
+{
+    function title()
+    {
+        // TRANS: Title of personal tag cloud section.
+        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';
+        return 'select profile_tag.tag, count(profile_tag.tag) as weight from subscription left join (profile_tag, profile_list) on subscriber=profile_tag.tagged and subscribed=profile_tag.tagger and profile_tag.tagger = profile_list.tagger and profile_tag.tag = profile_list.tag where subscribed=%d and subscriber != subscribed and profile_list.private = false and profile_tag.tag is not null group by profile_tag.tag order by weight desc';
+    }
+}
diff --git a/plugins/TagCloud/lib/subscriptionspeopleselftagcloudsection.php b/plugins/TagCloud/lib/subscriptionspeopleselftagcloudsection.php
new file mode 100644 (file)
index 0000000..7334234
--- /dev/null
@@ -0,0 +1,58 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Personal tag cloud section
+ *
+ * PHP version 5
+ *
+ * LICENCE: This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category  Widget
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link      http://status.net/
+ */
+
+if (!defined('STATUSNET') && !defined('LACONICA')) {
+    exit(1);
+}
+
+/**
+ * Personal tag cloud section
+ *
+ * @category Widget
+ * @package  StatusNet
+ * @author   Evan Prodromou <evan@status.net>
+ * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link     http://status.net/
+ */
+class SubscriptionsPeopleSelfTagCloudSection extends SubPeopleTagCloudSection
+{
+    function title()
+    {
+        // TRANS: Title of personal tag cloud section.
+        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';
+
+        return 'select profile_tag.tag, count(profile_tag.tag) as weight from subscription left join (profile_tag, profile_list) on profile_tag.tagger = subscribed and profile_tag.tag = profile_list.tag and profile_tag.tagger = profile_tag.tagger where subscriber=%d and subscribed != subscriber and profile_tag.tagger = profile_tag.tagged and profile_list.private = false and profile_tag.tag is not null group by profile_tag.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/plugins/TagCloud/lib/subscriptionspeopletagcloudsection.php b/plugins/TagCloud/lib/subscriptionspeopletagcloudsection.php
new file mode 100644 (file)
index 0000000..e101640
--- /dev/null
@@ -0,0 +1,60 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Personal tag cloud section
+ *
+ * PHP version 5
+ *
+ * LICENCE: This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category  Widget
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link      http://status.net/
+ */
+
+if (!defined('STATUSNET') && !defined('LACONICA')) {
+    exit(1);
+}
+
+/**
+ * Personal tag cloud section
+ *
+ * @category Widget
+ * @package  StatusNet
+ * @author   Evan Prodromou <evan@status.net>
+ * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link     http://status.net/
+ */
+class SubscriptionsPeopleTagCloudSection extends SubPeopleTagCloudSection
+{
+    function title()
+    {
+        // TRANS: Title of personal tag cloud section.
+        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';
+        return 'select profile_tag.tag, count(profile_tag.tag) as weight from subscription left join (profile_tag, profile_list) on subscriber=profile_tag.tagger and subscribed=tagged and profile_tag.tag = profile_list.tag and profile_tag.tagger = profile_list.tagger where subscriber=%d and subscriber != subscribed and profile_list.private = false and profile_tag.tag is not null group by profile_tag.tag order by weight desc';
+    }
+}
diff --git a/plugins/TagCloud/lib/tagcloudsection.php b/plugins/TagCloud/lib/tagcloudsection.php
new file mode 100644 (file)
index 0000000..80a9042
--- /dev/null
@@ -0,0 +1,128 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Base class for sections showing tag clouds
+ *
+ * PHP version 5
+ *
+ * LICENCE: This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category  Widget
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link      http://status.net/
+ */
+
+if (!defined('STATUSNET') && !defined('LACONICA')) {
+    exit(1);
+}
+
+define('TAGS_PER_SECTION', 10);
+
+/**
+ * Base class for sections
+ *
+ * These are the widgets that show interesting data about a person
+ * group, or site.
+ *
+ * @category Widget
+ * @package  StatusNet
+ * @author   Evan Prodromou <evan@status.net>
+ * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link     http://status.net/
+ */
+class TagCloudSection extends Section
+{
+    function showContent()
+    {
+        $tags = $this->getTags();
+
+        if (!$tags) {
+            // TRANS: Content displayed in a tag cloud section if there are no tags.
+            $this->out->element('p', null, _m('NOTAGS','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) {
+            // TRANS: Content displayed in a tag cloud section if there are no tags.
+            $this->out->element('p', null, _m('NOTAGS','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)
+    {
+        if ($this->out instanceof ShowstreamAction) {
+            return common_local_url('showstream', array('nickname' => $this->out->getTarget()->getNickname(), 'tag' => $tag));
+        }
+        return common_local_url('tag', array('tag' => $tag));
+    }
+
+    function divId()
+    {
+        return 'tagcloud';
+    }
+}