code:
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social 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.
//
// GNU social 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 GNU social.  If not, see <http://www.gnu.org/licenses/>.

/**
 * Base class for RSS 1.0 feed actions
 *
 * @category  Mail
 * @package   GNUsocial
 * @author    Evan Prodromou <evan@status.net>
 * @author    Earle Martin <earle@downlode.org>
 * @copyright 2008, 2009 StatusNet, Inc.
 * @license   https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
 */

defined('GNUSOCIAL') || die();

define('DEFAULT_RSS_LIMIT', 48);

class Rss10Action extends ManagedAction
{
    // This will contain the details of each feed item's author and be used to generate SIOC data.

    public $creators = [];
    public $limit = DEFAULT_RSS_LIMIT;
    public $notices = null;
    public $tags_already_output = [];

    public function isReadOnly($args)
    {
        return true;
    }

    protected function doPreparation()
    {
        $this->limit = $this->int('limit');

        if (empty($this->limit)) {
            $this->limit = DEFAULT_RSS_LIMIT;
        }

        if (common_config('site', 'private')) {
            if (!isset($_SERVER['PHP_AUTH_USER'])) {

                // This header makes basic auth go
                header('WWW-Authenticate: Basic realm="GNU social RSS"');

                // If the user hits cancel -- bam!
                $this->show_basic_auth_error();
                // the above calls 'exit'
            } else {
                $nickname = $_SERVER['PHP_AUTH_USER'];
                $password = $_SERVER['PHP_AUTH_PW'];

                if (!common_check_user($nickname, $password)) {
                    // basic authentication failed
                    list($proxy, $ip) = common_client_ip();

                    common_log(LOG_WARNING, "Failed RSS auth attempt, nickname = $nickname, proxy = $proxy, ip = $ip.");
                    $this->show_basic_auth_error();
                    // the above calls 'exit'
                }
            }
        }

        $this->doStreamPreparation();

        $this->notices = $this->getNotices($this->limit);
    }

    protected function doStreamPreparation()
    {
        // for example if we need to set $this->target or something
    }

    public function show_basic_auth_error()
    {
        http_response_code(401);
        header('Content-Type: application/xml; charset=utf-8');
        $this->startXML();
        $this->elementStart('hash');
        $this->element('error', null, 'Could not authenticate you.');
        $this->element('request', null, $_SERVER['REQUEST_URI']);
        $this->elementEnd('hash');
        $this->endXML();
        exit;
    }

    /**
     * Get the notices to output in this stream.
     *
     * @return array an array of Notice objects sorted in reverse chron
     */

    protected function getNotices()
    {
        return array();
    }

    /**
     * Get a description of the channel
     *
     * Returns an array with the following
     * @return array
     */

    public function getChannel()
    {
        return [
            'url'         => '',
            'title'       => '',
            'link'        => '',
            'description' => '',
        ];
    }

    public function getImage()
    {
        return null;
    }

    public function showPage()
    {
        $this->initRss();
        $this->showChannel();
        $this->showImage();

        if (count($this->notices)) {
            foreach ($this->notices as $n) {
                try {
                    $this->showItem($n);
                } catch (Exception $e) {
                    // log exceptions and continue
                    common_log(LOG_ERR, $e->getMessage());
                    continue;
                }
            }
        }

        $this->showCreators();
        $this->endRss();
    }

    public function showChannel()
    {
        $channel = $this->getChannel();
        $image = $this->getImage();

        $this->elementStart('channel', array('rdf:about' => $channel['url']));
        $this->element('title', null, $channel['title']);
        $this->element('link', null, $channel['link']);
        $this->element('description', null, $channel['description']);
        $this->element('cc:licence', [
            'rdf:resource' => common_config('license', 'url'),
        ]);

        if ($image) {
            $this->element('image', array('rdf:resource' => $image));
        }

        $this->elementStart('items');
        $this->elementStart('rdf:Seq');

        if (count($this->notices)) {
            foreach ($this->notices as $notice) {
                $this->element('rdf:li', array('rdf:resource' => $notice->uri));
            }
        }

        $this->elementEnd('rdf:Seq');
        $this->elementEnd('items');

        $this->elementEnd('channel');
    }

    public function showImage()
    {
        $image = $this->getImage();
        if ($image) {
            $channel = $this->getChannel();
            $this->elementStart('image', array('rdf:about' => $image));
            $this->element('title', null, $channel['title']);
            $this->element('link', null, $channel['link']);
            $this->element('url', null, $image);
            $this->elementEnd('image');
        }
    }

    public function showItem($notice)
    {
        $profile = $notice->getProfile();
        $nurl = common_local_url('shownotice', array('notice' => $notice->id));
        $creator_uri = common_profile_uri($profile);
        $this->elementStart('item', array('rdf:about' => $notice->uri,
                            'rdf:type' => 'http://rdfs.org/sioc/types#MicroblogPost'));
        $title = $profile->nickname . ': ' . common_xml_safe_str(trim($notice->content));
        $this->element('title', null, $title);
        $this->element('link', null, $nurl);
        $this->element('description', null, $profile->nickname."'s status on ".common_exact_date($notice->created));
        if ($notice->getRendered()) {
            $this->element('content:encoded', null, common_xml_safe_str($notice->getRendered()));
        }
        $this->element('dc:date', null, common_date_w3dtf($notice->created));
        $this->element('dc:creator', null, ($profile->fullname) ? $profile->fullname : $profile->nickname);
        $this->element('foaf:maker', array('rdf:resource' => $creator_uri));
        $this->element('sioc:has_creator', array('rdf:resource' => $creator_uri.'#acct'));
        try {
            $location = Notice_location::locFromStored($notice);
            if (isset($location->lat) && isset($location->lon)) {
                $location_uri = $location->getRdfURL();
                $attrs = array('geo:lat' => $location->lat,
                               'geo:long' => $location->lon);
                if (strlen($location_uri)) {
                    $attrs['rdf:resource'] = $location_uri;
                }
                $this->element('statusnet:origin', $attrs);
            }
        } catch (ServerException $e) {
            // No result, so no location data
        }
        $this->element('statusnet:postIcon', array('rdf:resource' => $profile->avatarUrl()));
        $this->element('cc:licence', array('rdf:resource' => common_config('license', 'url')));
        if ($notice->reply_to) {
            $replyurl = common_local_url('shownotice', array('notice' => $notice->reply_to));
            $this->element('sioc:reply_of', array('rdf:resource' => $replyurl));
        }
        if (!empty($notice->conversation)) {
            $conversationurl = common_local_url(
                'conversation',
                ['id' => $notice->conversation]
            );
            $this->element('sioc:has_discussion', [
                'rdf:resource' => $conversationurl,
            ]);
        }
        $attachments = $notice->attachments();
        if ($attachments) {
            foreach ($attachments as $attachment) {
                try {
                    $enclosure = $attachment->getEnclosure();
                    $attribs = array('rdf:resource' => $enclosure->url);
                    if ($enclosure->title) {
                        $attribs['dc:title'] = $enclosure->title;
                    }
                    if ($enclosure->modified) {
                        $attribs['dc:date'] = common_date_w3dtf($enclosure->modified);
                    }
                    if ($enclosure->size) {
                        $attribs['enc:length'] = $enclosure->size;
                    }
                    if ($enclosure->mimetype) {
                        $attribs['enc:type'] = $enclosure->mimetype;
                    }
                    $this->element('enc:enclosure', $attribs);
                } catch (ServerException $e) {
                    // There was not enough metadata available
                }
                $this->element('sioc:links_to', array('rdf:resource'=>$attachment->url));
            }
        }

        $tag = new Notice_tag();
        $tag->notice_id = $notice->id;
        if ($tag->find()) {
            $entry['tags']=array();
            while ($tag->fetch()) {
                $tagpage = common_local_url('tag', array('tag' => $tag->tag));

                if (in_array($tag, $this->tags_already_output)) {
                    $this->element('ctag:tagged', array('rdf:resource'=>$tagpage.'#concept'));
                    continue;
                }

                $tagrss  = common_local_url('tagrss', array('tag' => $tag->tag));
                $this->elementStart('ctag:tagged');
                $this->elementStart('ctag:Tag', array('rdf:about'=>$tagpage.'#concept', 'ctag:label'=>$tag->tag));
                $this->element('foaf:page', array('rdf:resource'=>$tagpage));
                $this->element('rdfs:seeAlso', array('rdf:resource'=>$tagrss));
                $this->elementEnd('ctag:Tag');
                $this->elementEnd('ctag:tagged');

                $this->tags_already_output[] = $tag->tag;
            }
        }
        $this->elementEnd('item');
        $this->creators[$creator_uri] = $profile;
    }

    public function showCreators()
    {
        foreach ($this->creators as $uri => $profile) {
            $id = $profile->id;
            $nickname = $profile->nickname;
            $this->elementStart('foaf:Agent', array('rdf:about' => $uri));
            $this->element('foaf:nick', null, $nickname);
            if ($profile->fullname) {
                $this->element('foaf:name', null, $profile->fullname);
            }
            $this->element('foaf:holdsAccount', array('rdf:resource' => $uri.'#acct'));
            $avatar = $profile->avatarUrl();
            $this->element('foaf:depiction', array('rdf:resource' => $avatar));
            $this->elementEnd('foaf:Agent');
        }
    }

    public function initRss()
    {
        $channel = $this->getChannel();
        header('Content-Type: application/rdf+xml');

        $this->startXml();
        $this->elementStart('rdf:RDF', array('xmlns:rdf' =>
                                              'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
                                              'xmlns:dc' =>
                                              'http://purl.org/dc/elements/1.1/',
                                              'xmlns:cc' =>
                                              'http://creativecommons.org/ns#',
                                              'xmlns:content' =>
                                              'http://purl.org/rss/1.0/modules/content/',
                                              'xmlns:ctag' =>
                                              'http://commontag.org/ns#',
                                              'xmlns:foaf' =>
                                              'http://xmlns.com/foaf/0.1/',
                                              'xmlns:enc' =>
                                              'http://purl.oclc.org/net/rss_2.0/enc#',
                                              'xmlns:sioc' =>
                                              'http://rdfs.org/sioc/ns#',
                                              'xmlns:sioct' =>
                                              'http://rdfs.org/sioc/types#',
                                              'xmlns:rdfs' =>
                                              'http://www.w3.org/2000/01/rdf-schema#',
                                              'xmlns:geo' =>
                                              'http://www.w3.org/2003/01/geo/wgs84_pos#',
                                              'xmlns:statusnet' =>
                                              'http://status.net/ont/',
                                              'xmlns' => 'http://purl.org/rss/1.0/'));
        $this->elementStart('sioc:Site', array('rdf:about' => common_root_url()));
        $this->element('sioc:name', null, common_config('site', 'name'));
        $this->elementStart('sioc:space_of');
        $this->element('sioc:Container', array('rdf:about' =>
                                               $channel['url']));
        $this->elementEnd('sioc:space_of');
        $this->elementEnd('sioc:Site');
    }

    public function endRss()
    {
        $this->elementEnd('rdf:RDF');
    }

    /**
     * When was this page last modified?
     *
     */

    public function lastModified()
    {
        if (empty($this->notices)) {
            return null;
        }

        if (count($this->notices) == 0) {
            return null;
        }

        // FIXME: doesn't handle modified profiles, avatars, deleted notices

        return strtotime($this->notices[0]->created);
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Base class for RSS 1.0 feed actions
 *
 * 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  Mail
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @author    Earle Martin <earle@downlode.org>
 * @copyright 2008-9 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); }

class TargetedRss10Action extends Rss10Action
{
    protected $target = null;

    protected function doStreamPreparation()
    {
        $this->target = User::getByNickname($this->trimmed('nickname'))->getProfile();
    }

    public function getTarget()
    {
        return $this->target;
    }

    function getImage()
    {
        return $this->target->avatarUrl(AVATAR_PROFILE_SIZE);
    }
}

repo_name: ksuudilla/gnu

license: mit


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Form for leaving a group
 *
 * 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  Form
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @author    Sarven Capadisli <csarven@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);
}

require_once INSTALLDIR . '/lib/util/form.php';

/**
 * Form for leaving a group
 *
 * @category Form
 * @package  StatusNet
 * @author   Evan Prodromou <evan@status.net>
 * @author   Sarven Capadisli <csarven@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/
 *
 * @see      UnsubscribeForm
 */
class ApproveGroupForm extends Form
{
    /**
     * group for user to leave
     */

    var $group = null;
    var $profile = null;

    /**
     * Constructor
     *
     * @param HTMLOutputter $out   output channel
     * @param group         $group group to leave
     */
    function __construct($out=null, $group=null, $profile=null)
    {
        parent::__construct($out);

        $this->group = $group;
        $this->profile = $profile;
    }

    /**
     * ID of the form
     *
     * @return string ID of the form
     */
    function id()
    {
        return 'group-queue-' . $this->group->id;
    }

    /**
     * class of the form
     *
     * @return string of the form class
     */
    function formClass()
    {
        return 'form_group_queue ajax';
    }

    /**
     * Action of the form
     *
     * @return string URL of the action
     */
    function action()
    {
        $params = array();
        if ($this->profile) {
            $params['profile_id'] = $this->profile->id;
        }
        return common_local_url('approvegroup',
                                array('id' => $this->group->id), $params);
    }

    /**
     * Action elements
     *
     * @return void
     */

    function formActions()
    {
        // TRANS: Submit button text to accept a group membership request on approve group form.
        $this->out->submit('approve', _m('BUTTON','Accept'));
        // TRANS: Submit button text to reject a group membership request on approve group form.
        $this->out->submit('cancel', _m('BUTTON','Reject'));
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Form for leaving a group
 *
 * 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  Form
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @author    Sarven Capadisli <csarven@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); }

/**
 * Form for leaving a group
 *
 * @category Form
 * @package  StatusNet
 * @author   Evan Prodromou <evan@status.net>
 * @author   Sarven Capadisli <csarven@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/
 *
 * @see      UnsubscribeForm
 */
class CancelGroupForm extends Form
{
    /**
     * group for user to leave
     */

    var $group = null;
    var $profile = null;

    /**
     * Constructor
     *
     * @param HTMLOutputter $out        output channel
     * @param User_group    $group      group to leave
     * @param Profile       $profile    User profile this is meant for
     */
    function __construct(HTMLOutputter $out=null, User_group $group=null, Profile $profile=null)
    {
        parent::__construct($out);

        $this->group = $group;
        $this->profile = $profile;
    }

    /**
     * ID of the form
     *
     * @return string ID of the form
     */
    function id()
    {
        return 'group-cancel-' . $this->group->getID();
    }

    /**
     * class of the form
     *
     * @return string of the form class
     */
    function formClass()
    {
        return 'form_group_leave ajax';
    }

    /**
     * Action of the form
     *
     * @return string URL of the action
     */
    function action()
    {
        $params = array();
        if ($this->profile instanceof Profile) {
            $params['profile_id'] = $this->profile->getID();
        }
        return common_local_url('cancelgroup', array('id' => $this->group->getID()), $params);
    }

    /**
     * Action elements
     *
     * @return void
     */
    function formActions()
    {
        // TRANS: Submit button text on form to cancel group join request.
        $this->out->submit('submit', _m('BUTTON','Cancel join request'));
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Base class for group actions
 *
 * 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  Action
 * @package   StatusNet
 * @author    Zach Copley <zach@status.net>
 * @copyright 2009-2011 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); }

define('MEMBERS_PER_SECTION', 27);

/**
 * Base class for group actions, similar to ProfileAction
 *
 * @category Action
 * @package  StatusNet
 * @author   Zach Copley <zach@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 GroupAction extends ShowstreamAction
{
    protected $group;

    protected function doPreparation()
    {
        $nickname_arg = $this->arg('nickname');
        $nickname = common_canonical_nickname($nickname_arg);

        // Permanent redirect on non-canonical nickname

        if ($nickname_arg !== $nickname) {
            $args = array('nickname' => $nickname);
            if ($this->page != 1) {
                $args['page'] = $this->page;
            }
            common_redirect(common_local_url($this->getActionName(), $args), 301);
        }

        if (!$nickname) {
            // TRANS: Client error displayed if no nickname argument was given requesting a group page.
            $this->clientError(_('No nickname.'), 404);
        }

        $local = Local_group::getKV('nickname', $nickname);

        if (!$local) {
            $alias = Group_alias::getKV('alias', $nickname);
            if ($alias) {
                $args = array('id' => $alias->group_id);
                if ($this->page != 1) {
                    $args['page'] = $this->page;
                }
                common_redirect(common_local_url('groupbyid', $args), 301);
            } else {
                common_log(LOG_NOTICE, "Couldn't find local group for nickname '$nickname'");
                // TRANS: Client error displayed if no remote group with a given name was found requesting group page.
                throw new ClientException(_('No such group.'), 404);
            }
        }

        $this->group = User_group::getKV('id', $local->group_id);
        $this->target = $this->group->getProfile();

        if (!$this->group instanceof User_group) {
            // TRANS: Client error displayed if no local group with a given name was found requesting group page.
            throw new ClientException(_('No such group.'), 404);
        }
    }

    function showProfileBlock()
    {
        $block = new GroupProfileBlock($this, $this->group);
        $block->show();
    }

    /**
     * Fill in the sidebar.
     *
     * @return void
     */
    function showSections()
    {
        $this->showMembers();
        if ($this->scoped instanceof Profile && $this->scoped->isAdmin($this->group)) {
            $this->showPending();
            $this->showBlocked();
        }

        $this->showAdmins();
    }

    /**
     * Show mini-list of members
     *
     * @return void
     */
    function showMembers()
    {
        $member = $this->group->getMembers(0, MEMBERS_PER_SECTION);

        if (!$member) {
            return;
        }

        $this->elementStart('div', array('id' => 'entity_members',
                                         'class' => 'section'));

        if (Event::handle('StartShowGroupMembersMiniList', array($this))) {
            $this->elementStart('h2');

            $this->element('a', array('href' => common_local_url('groupmembers', array('nickname' =>
                                                                                $this->group->nickname))),
                           // TRANS: Header for mini list of group members on a group page (h2).
                           _('Members'));

            $this->text(' ');

            $this->text($this->group->getMemberCount());

            $this->elementEnd('h2');

            $gmml = new GroupMembersMiniList($member, $this);
            $cnt = $gmml->show();
            if ($cnt == 0) {
                // TRANS: Description for mini list of group members on a group page when the group has no members.
                $this->element('p', null, _('(None)'));
            }

            // @todo FIXME: Should be shown if a group has more than 27 members, but I do not see it displayed at
            //              for example http://identi.ca/group/statusnet. Broken?
            if ($cnt > MEMBERS_PER_SECTION) {
                $this->element('a', array('href' => common_local_url('groupmembers',
                                                                     array('nickname' => $this->group->nickname))),
                               // TRANS: Link to all group members from mini list of group members if group has more than n members.
                               _('All members'));
            }

            Event::handle('EndShowGroupMembersMiniList', array($this));
        }

        $this->elementEnd('div');
    }

    function showPending()
    {
        if ($this->group->join_policy != User_group::JOIN_POLICY_MODERATE) {
            return;
        }

        $pending = $this->group->getQueueCount();

        if (!$pending) {
            return;
        }

        $request = $this->group->getRequests(0, MEMBERS_PER_SECTION);

        if (!$request) {
            return;
        }

        $this->elementStart('div', array('id' => 'entity_pending',
                                         'class' => 'section'));

        if (Event::handle('StartShowGroupPendingMiniList', array($this))) {

            $this->elementStart('h2');

            $this->element('a', array('href' => common_local_url('groupqueue', array('nickname' =>
                                                                                $this->group->nickname))),
                           // TRANS: Header for mini list of users with a pending membership request on a group page (h2).
                           _('Pending'));

            $this->text(' ');

            $this->text($pending);

            $this->elementEnd('h2');

            $gmml = new ProfileMiniList($request, $this);
            $gmml->show();

            Event::handle('EndShowGroupPendingMiniList', array($this));
        }

        $this->elementEnd('div');
    }

    function showBlocked()
    {
        $blocked = $this->group->getBlocked(0, MEMBERS_PER_SECTION);

        $this->elementStart('div', array('id' => 'entity_blocked',
                                         'class' => 'section'));

        if (Event::handle('StartShowGroupBlockedMiniList', array($this))) {

            $this->elementStart('h2');

            $this->element('a', array('href' => common_local_url('blockedfromgroup', array('nickname' =>
                                                                                $this->group->nickname))),
                           // TRANS: Header for mini list of users that are blocked in a group page (h2).
                           _('Blocked'));

            $this->text(' ');

            $this->text($this->group->getBlockedCount());

            $this->elementEnd('h2');

            $gmml = new GroupBlockedMiniList($blocked, $this);
            $cnt = $gmml->show();
            if ($cnt == 0) {
                // TRANS: Description for mini list of group members on a group page when the group has no members.
                $this->element('p', null, _('(None)'));
            }

            // @todo FIXME: Should be shown if a group has more than 27 members, but I do not see it displayed at
            //              for example http://identi.ca/group/statusnet. Broken?
            if ($cnt > MEMBERS_PER_SECTION) {
                $this->element('a', array('href' => common_local_url('blockedfromgroup',
                                                                     array('nickname' => $this->group->nickname))),
                               // TRANS: Link to all group members from mini list of group members if group has more than n members.
                               _('All members'));
            }

            Event::handle('EndShowGroupBlockedMiniList', array($this));
        }

        $this->elementEnd('div');
    }

    /**
     * Show list of admins
     *
     * @return void
     */
    function showAdmins()
    {
        $adminSection = new GroupAdminSection($this, $this->group);
        $adminSection->show();
    }

    function noticeFormOptions()
    {
        $options = parent::noticeFormOptions();
        $cur = common_current_user();

        if (!empty($cur) && $cur->isMember($this->group)) {
            $options['to_group'] =  $this->group;
        }

        return $options;
    }

    function getGroup()
    {
        return $this->group;
    }
}


code:
<?php

if (!defined('GNUSOCIAL')) { exit(1); }

class GroupAdminSection extends ProfileSection
{
    var $group;

    function __construct($out, $group)
    {
        parent::__construct($out);
        $this->group = $group;
    }

    function getProfiles()
    {
        return $this->group->getAdmins();
    }

    function title()
    {
        // TRANS: Title for list of group administrators on a group page.
        return _m('TITLE','Admins');
    }

    function divId()
    {
        return 'group_admins';
    }

    function moreUrl()
    {
        return null;
    }
}


code:
<?php

if (!defined('GNUSOCIAL')) { exit(1); }

class GroupBlockedMiniList extends ProfileMiniList
{
    function newListItem(Profile $profile)
    {
        return new GroupBlockedMiniListItem($profile, $this->action);
    }
}


code:
<?php

if (!defined('GNUSOCIAL')) { exit(1); }

class GroupBlockedMiniListItem extends ProfileMiniListItem
{
    function linkAttributes()
    {
        $aAttrs = parent::linkAttributes();

        if (common_config('nofollow', 'members')) {
            $aAttrs['rel'] .= ' nofollow';
        }

        return $aAttrs;
    }
}


code:
<?php
// @todo FIXME: standard file header missing.
/**
 * Form for blocking a user from a group
 *
 * @category Form
 * @package  StatusNet
 * @author   Evan Prodromou <evan@status.net>
 * @author   Sarven Capadisli <csarven@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/
 *
 * @see      BlockForm
 */
class GroupBlockForm extends Form
{
    /**
     * Profile of user to block
     */

    var $profile = null;

    /**
     * Group to block the user from
     */

    var $group = null;

    /**
     * Return-to args
     */

    var $args = null;

    /**
     * Constructor
     *
     * @param HTMLOutputter $out     output channel
     * @param Profile       $profile profile of user to block
     * @param User_group    $group   group to block user from
     * @param array         $args    return-to args
     */
    function __construct($out=null, $profile=null, $group=null, $args=null)
    {
        parent::__construct($out);

        $this->profile = $profile;
        $this->group   = $group;
        $this->args    = $args;
    }

    /**
     * ID of the form
     *
     * @return int ID of the form
     */
    function id()
    {
        // This should be unique for the page.
        return 'block-' . $this->profile->id;
    }

    /**
     * class of the form
     *
     * @return string class of the form
     */
    function formClass()
    {
        return 'form_group_block';
    }

    /**
     * Action of the form
     *
     * @return string URL of the action
     */
    function action()
    {
        return common_local_url('groupblock');
    }

    /**
     * Legend of the Form
     *
     * @return void
     */
    function formLegend()
    {
        // TRANS: Form legend for form to block user from a group.
        $this->out->element('legend', null, _('Block user from group'));
    }

    /**
     * Data elements of the form
     *
     * @return void
     */
    function formData()
    {
        $this->out->hidden('blockto-' . $this->profile->id,
                           $this->profile->id,
                           'blockto');
        $this->out->hidden('blockgroup-' . $this->group->id,
                           $this->group->id,
                           'blockgroup');
        if ($this->args) {
            foreach ($this->args as $k => $v) {
                $this->out->hidden('returnto-' . $k, $v);
            }
        }
    }

    /**
     * Action elements
     *
     * @return void
     */
    function formActions()
    {
        $this->out->submit(
            'submit',
            // TRANS: Button text for the form that will block a user from a group.
            _m('BUTTON','Block'),
            'submit',
            null,
            // TRANS: Submit button title.
            _m('TOOLTIP', 'Block this user so that they can no longer post messages to it.'));
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Form for editing a group
 *
 * 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  Form
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @author    Sarven Capadisli <csarven@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);
}

require_once INSTALLDIR . '/lib/util/form.php';

/**
 * Form for editing a group
 *
 * @category Form
 * @package  StatusNet
 * @author   Evan Prodromou <evan@status.net>
 * @author   Sarven Capadisli <csarven@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/
 *
 * @see      UnsubscribeForm
 */
class GroupEditForm extends Form
{
    /**
     * group for user to join
     */
    var $group = null;

    /**
     * Constructor
     *
     * @param Action     $out   output channel
     * @param User_group $group group to join
     */
    function __construct($out=null, $group=null)
    {
        parent::__construct($out);

        $this->group = $group;
    }

    /**
     * ID of the form
     *
     * @return string ID of the form
     */
    function id()
    {
        if ($this->group) {
            return 'form_group_edit-' . $this->group->id;
        } else {
            return 'form_group_add';
        }
    }

    /**
     * class of the form
     *
     * @return string of the form class
     */
    function formClass()
    {
        return 'form_settings';
    }

    /**
     * Action of the form
     *
     * @return string URL of the action
     */
    function action()
    {
        if ($this->group) {
            return common_local_url('editgroup',
                                    array('nickname' => $this->group->nickname));
        } else {
            return common_local_url('newgroup');
        }
    }

    /**
     * Name of the form
     *
     * @return void
     */
    function formLegend()
    {
        // TRANS: Form legend for group edit form.
        $this->out->element('legend', null, _('Create a new group'));
    }

    /**
     * Data elements of the form
     *
     * @return void
     */
    function formData()
    {
        if ($this->group) {
            $id = $this->group->id;
            $nickname = $this->group->nickname;
            $fullname = $this->group->fullname;
            $homepage = $this->group->homepage;
            $description = $this->group->description;
            $location = $this->group->location;
        } else {
            $id = '';
            $nickname = '';
            $fullname = '';
            $homepage = '';
            $description = '';
            $location = '';
        }

        $this->out->elementStart('ul', 'form_data');
        if (Event::handle('StartGroupEditFormData', array($this))) {
            $this->out->elementStart('li');
            $this->out->hidden('groupid', $id);
            // TRANS: Field label on group edit form.
            $this->out->input('newnickname', _('Nickname'),
                              ($this->out->arg('newnickname')) ? $this->out->arg('newnickname') : $nickname,
                              // TRANS: Field title on group edit form.
                              _('1-64 lowercase letters or numbers, no punctuation or spaces.'),
                              null, false,
                              $this->group instanceof User_group && !common_config('profile', 'changenick')
                                    ? array('disabled'=>'disabled') // can't change nickname
                                    : array()); // either we can change nickname, or we're creating a new group.
            $this->out->elementEnd('li');
            $this->out->elementStart('li');
            // TRANS: Field label on group edit form.
            $this->out->input('fullname', _('Full name'),
                              ($this->out->arg('fullname')) ? $this->out->arg('fullname') : $fullname);
            $this->out->elementEnd('li');
            $this->out->elementStart('li');
            // TRANS: Field label on group edit form; points to "more info" for a group.
            $this->out->input('homepage', _('Homepage'),
                              ($this->out->arg('homepage')) ? $this->out->arg('homepage') : $homepage,
                              // TRANS: Field title on group edit form.
                              _('URL of the homepage or blog of the group or topic.'));
            $this->out->elementEnd('li');
            $this->out->elementStart('li');
            $desclimit = User_group::maxDescription();
            if ($desclimit == 0) {
                // TRANS: Text area title for group description when there is no text limit.
                $descinstr = _('Describe the group or topic.');
            } else {
                // TRANS: Text area title for group description.
                // TRANS: %d is the number of characters available for the description.
                $descinstr = sprintf(_m('Describe the group or topic in %d character or less.',
                                        'Describe the group or topic in %d characters or less.',
                                        $desclimit),
                                     $desclimit);
            }
            // TRANS: Text area label on group edit form; contains description of group.
            $this->out->textarea('description', _('Description'),
                                 ($this->out->arg('description')) ? $this->out->arg('description') : $description,
                                 $descinstr);
            $this->out->elementEnd('li');
            $this->out->elementStart('li');
            // TRANS: Field label on group edit form.
            $this->out->input('location', _('Location'),
                              ($this->out->arg('location')) ? $this->out->arg('location') : $location,
                              // TRANS: Field title on group edit form.
                              _('Location for the group, if any, like "City, State (or Region), Country".'));
            $this->out->elementEnd('li');
            if (common_config('group', 'maxaliases') > 0) {
                $aliases = (empty($this->group)) ? array() : $this->group->getAliases();
                $this->out->elementStart('li');
                // TRANS: Field label on group edit form.
                $this->out->input('aliases', _('Aliases'),
                                  ($this->out->arg('aliases')) ? $this->out->arg('aliases') :
                                  (!empty($aliases)) ? implode(' ', $aliases) : '',
                                  // TRANS: Input field title for group aliases.
                                  // TRANS: %d is the maximum number of group aliases available.
                                  sprintf(_m('Extra nicknames for the group, separated with commas or spaces. Maximum %d alias allowed.',
                                             'Extra nicknames for the group, separated with commas or spaces. Maximum %d aliases allowed.',
                                             common_config('group', 'maxaliases')),
                                          common_config('group', 'maxaliases')));;
                $this->out->elementEnd('li');
            }
            $this->out->elementStart('li');
            // TRANS: Checkbox field label on group edit form to mark a group private.
            $this->out->checkbox('private', _m('LABEL','Private'),
                                  ($this->out->arg('private')) ? $this->out->arg('private') :
                                 ((!empty($this->group)) ? $this->group->isPrivate() : false),
                                 // TRANS: Checkbox field title on group edit form to mark a group private.
                                 _('New members must be approved by admin and all posts are forced to be private.'));
            $this->out->elementEnd('li');
            Event::handle('EndGroupEditFormData', array($this));
        }
        $this->out->elementEnd('ul');
    }

    /**
     * Action elements
     *
     * @return void
     */
    function formActions()
    {
        // TRANS: Text for save button on group edit form.
        $this->out->submit('submit', _m('BUTTON','Save'));
    }
}


code:
<?php

/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Widget to show a list of groups
 *
 * 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    Evan Prodromou <evan@status.net>
 * @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);
}

require_once INSTALLDIR . '/lib/ui/widget.php';

/**
 * Widget to show a list of groups
 *
 * @category Public
 * @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 GroupList extends Widget
{
    /** Current group, group query. */
    var $group = null;
    /** Owner of this list */
    var $owner = null;
    /** Action object using us. */
    var $action = null;

    function __construct($group, $owner=null, $action=null)
    {
        parent::__construct($action);

        $this->group = $group;
        $this->owner = $owner;
        $this->action = $action;
    }

    function show()
    {
        $this->out->elementStart('ul', 'profiles groups xoxo');

        $cnt = 0;

        while ($this->group->fetch()) {
            $cnt++;
            if($cnt > GROUPS_PER_PAGE) {
                break;
            }
            $this->showgroup();
        }

        $this->out->elementEnd('ul');

        return $cnt;
    }

    function showGroup()
    {
        $this->out->elementStart('li', array('class' => 'profile h-card',
                                             'id' => 'group-' . $this->group->id));

        $user = common_current_user();

        $this->out->elementStart('div', 'entity_profile');

        $logo = $this->group->stream_logo ?: User_group::defaultLogo(AVATAR_STREAM_SIZE);

        $this->out->elementStart('a', array('href' => $this->group->homeUrl(),
                                            'class' => 'u-url p-nickname',
                                            'rel' => 'contact group'));
        $this->out->element('img', array('src' => $logo,
                                         'class' => 'avatar u-photo',
                                         'width' => AVATAR_STREAM_SIZE,
                                         'height' => AVATAR_STREAM_SIZE,
                                         'alt' => $this->group->getBestName()));
        $this->out->text($this->group->getNickname());
        $this->out->elementEnd('a');

        if ($this->group->fullname) {
            $this->out->text(' ');
            $this->out->elementStart('span', 'p-name');
            $this->out->raw($this->highlight($this->group->fullname));
            $this->out->elementEnd('span');
        }
        if ($this->group->location) {
            $this->out->text(' ');
            $this->out->elementStart('span', 'label');
            $this->out->raw($this->highlight($this->group->location));
            $this->out->elementEnd('span');
        }
        if ($this->group->homepage) {
            $this->out->text(' ');
            $this->out->elementStart('a', array('href' => $this->group->homepage,
                                                'class' => 'u-url'));
            $this->out->raw($this->highlight($this->group->homepage));
            $this->out->elementEnd('a');
        }
        if ($this->group->description) {
            $this->out->elementStart('p', 'note');
            $this->out->raw($this->highlight($this->group->description));
            $this->out->elementEnd('p');
        }

        // If we're on a list with an owner (subscriptions or subscribers)...

        if (!empty($user) && !empty($this->owner) && $user->id == $this->owner->id) {
            $this->showOwnerControls();
        }

        $this->out->elementEnd('div');

        if ($user) {
            $this->out->elementStart('div', 'entity_actions');
            $this->out->elementStart('ul');
            $this->out->elementStart('li', 'entity_subscribe');
            // XXX: special-case for user looking at own
            // subscriptions page
            if ($user->isMember($this->group)) {
                $lf = new LeaveForm($this->out, $this->group);
                $lf->show();
            } else if (!Group_block::isBlocked($this->group, $user->getProfile())) {
                $jf = new JoinForm($this->out, $this->group);
                $jf->show();
            }
            $this->out->elementEnd('li');
            $this->out->elementEnd('ul');
            $this->out->elementEnd('div');
        }

        $this->out->elementEnd('li');
    }

    /* Override this in subclasses. */

    function showOwnerControls()
    {
        return;
    }

    function highlight($text)
    {
        return htmlspecialchars($text);
    }
}


code:
<?php
// @todo FIXME: add documentation.

class GroupMemberList extends ProfileList
{
    var $group = null;

    function __construct($profile, $group, $action)
    {
        parent::__construct($profile, $action);

        $this->group = $group;
    }

    function newListItem(Profile $profile)
    {
        return new GroupMemberListItem($profile, $this->group, $this->action);
    }
}


code:
<?php
// @todo FIXME: add documentation.

class GroupMemberListItem extends ProfileListItem
{
    var $group = null;

    function __construct($profile, $group, $action)
    {
        parent::__construct($profile, $action);

        $this->group = $group;
    }

    function showFullName()
    {
        parent::showFullName();
        if ($this->profile->isAdmin($this->group)) {
            $this->out->text(' '); // for separating the classes.
            // TRANS: Indicator in group members list that this user is a group administrator.
            $this->out->element('span', 'role', _m('GROUPADMIN','Admin'));
        }
    }

    function showActions()
    {
        $this->startActions();
        if (Event::handle('StartProfileListItemActionElements', array($this))) {
            $this->showSubscribeButton();
            $this->showMakeAdminForm();
            $this->showGroupBlockForm();
            Event::handle('EndProfileListItemActionElements', array($this));
        }
        $this->endActions();
    }

    function showMakeAdminForm()
    {
        $user = common_current_user();

        if (!empty($user) &&
            $user->id != $this->profile->id &&
            ($user->isAdmin($this->group) || $user->hasRight(Right::MAKEGROUPADMIN)) &&
            !$this->profile->isAdmin($this->group)) {
            $this->out->elementStart('li', 'entity_make_admin');
            $maf = new MakeAdminForm($this->out, $this->profile, $this->group,
                                     $this->returnToArgs());
            $maf->show();
            $this->out->elementEnd('li');
        }

    }

    function showGroupBlockForm()
    {
        $user = common_current_user();

        if (!empty($user) && $user->id != $this->profile->id && $user->isAdmin($this->group)) {
            $this->out->elementStart('li', 'entity_block');
            $bf = new GroupBlockForm($this->out, $this->profile, $this->group,
                                     $this->returnToArgs());
            $bf->show();
            $this->out->elementEnd('li');
        }
    }

    function linkAttributes()
    {
        $aAttrs = parent::linkAttributes();

        if (common_config('nofollow', 'members')) {
            $aAttrs['rel'] .= ' nofollow';
        }

        return $aAttrs;
    }

    function homepageAttributes()
    {
        $aAttrs = parent::linkAttributes();

        if (common_config('nofollow', 'members')) {
            $aAttrs['rel'] = 'nofollow';
        }

        return $aAttrs;
    }

    /**
     * Fetch necessary return-to arguments for the profile forms
     * to return to this list when they're done.
     *
     * @return array
     */
    protected function returnToArgs()
    {
        $args = array('action' => 'groupmembers',
                      'nickname' => $this->group->nickname);
        $page = $this->out->arg('page');
        if ($page) {
            $args['param-page'] = $page;
        }
        return $args;
    }
}


code:
<?php

if (!defined('GNUSOCIAL')) { exit(1); }

class GroupMembersMiniList extends ProfileMiniList
{
    function newListItem(Profile $profile)
    {
        return new GroupMembersMiniListItem($profile, $this->action);
    }
}


code:
<?php

if (!defined('GNUSOCIAL')) { exit(1); }

class GroupMembersMiniListItem extends ProfileMiniListItem
{
    function linkAttributes()
    {
        $aAttrs = parent::linkAttributes();

        if (common_config('nofollow', 'members')) {
            $aAttrs['rel'] .= ' nofollow';
        }

        return $aAttrs;
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Widget to show a mini-list of groups
 *
 * 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    Evan Prodromou <evan@status.net>
 * @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);
}

require_once INSTALLDIR . '/lib/groups/grouplist.php';

/**
 * Widget to show a list of groups, good for sidebar
 *
 * @category Public
 * @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 GroupMiniList extends GroupList
{
    function show()
    {
        $this->out->elementStart('ul', 'entities groups xoxo');

        $cnt = 0;

        while ($this->group->fetch()) {
            $cnt++;
            if($cnt > GROUPS_PER_MINILIST) {
                break;
            }
            $this->showGroup();
        }

        $this->out->elementEnd('ul');

        return $cnt;
    }

    function showGroup()
    {
        $this->out->elementStart('li', 'h-card');
        $this->out->elementStart('a', array('title' => $this->group->getBestName(),
                                       'href' => $this->group->homeUrl(),
                                       'rel' => 'contact group',
                                       'class' => 'p-name u-url org'));

        $logo = ($this->group->mini_logo) ?
          $this->group->mini_logo : User_group::defaultLogo(AVATAR_MINI_SIZE);

        $this->out->element('img', array('src' => $logo,
                                    'width' => AVATAR_MINI_SIZE,
                                    'height' => AVATAR_MINI_SIZE,
                                    'class' => 'avatar photo',
                                    'alt' => $this->group->getBestName()));
        $this->out->elementEnd('a');
        $this->out->elementEnd('li');
    }
}


code:
<?php
/**
 * StatusNet - the distributed open-source microblogging tool
 * Copyright (C) 2011, StatusNet, Inc.
 *
 * Stream of notices for a group
 *
 * PHP version 5
 *
 * 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  Stream
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @copyright 2011 StatusNet, Inc.
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
 * @link      http://status.net/
 */

if (!defined('GNUSOCIAL')) { exit(1); }

/**
 * Stream of notices for a group
 *
 * @category  Stream
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @copyright 2011 StatusNet, Inc.
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
 * @link      http://status.net/
 */
class GroupNoticeStream extends ScopingNoticeStream
{
    var $group;

    function __construct($group, Profile $scoped=null)
    {
        $this->group = $group;

        parent::__construct(new CachingNoticeStream(new RawGroupNoticeStream($group),
                                                    'user_group:notice_ids:' . $group->id),
                            $scoped);
    }

    function getNoticeIds($offset, $limit, $since_id, $max_id)
    {
        if ($this->impossibleStream()) {
            return array();
        } else {
            return parent::getNoticeIds($offset, $limit, $since_id, $max_id);
        }
    }

    function getNotices($offset, $limit, $sinceId = null, $maxId = null)
    {
        if ($this->impossibleStream()) {
            return new ArrayWrapper(array());
        } else {
            return parent::getNotices($offset, $limit, $sinceId, $maxId);
        }
    }

    function impossibleStream()
    {
        if ($this->group->force_scope &&
            (!$this->scoped instanceof Profile || $this->scoped->isMember($this->group))) {
            return true;
        }

        return false;
    }
}

/**
 * Stream of notices for a group
 *
 * @category  Stream
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @copyright 2011 StatusNet, Inc.
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
 * @link      http://status.net/
 */
class RawGroupNoticeStream extends NoticeStream
{
    protected $group;

    function __construct($group)
    {
        $this->group = $group;
    }

    function getNoticeIds($offset, $limit, $since_id, $max_id)
    {
        $inbox = new Group_inbox();

        $inbox->group_id = $this->group->id;

        $inbox->selectAdd();
        $inbox->selectAdd('notice_id');

        Notice::addWhereSinceId($inbox, $since_id, 'notice_id');
        Notice::addWhereMaxId($inbox, $max_id, 'notice_id');

        $inbox->orderBy('created DESC, notice_id DESC');

        if (!is_null($offset)) {
            $inbox->limit($offset, $limit);
        }

        $ids = array();

        if ($inbox->find()) {
            while ($inbox->fetch()) {
                $ids[] = $inbox->notice_id;
            }
        }

        return $ids;
    }
}


code:
<?php
/**
 * StatusNet - the distributed open-source microblogging tool
 * Copyright (C) 2011, StatusNet, Inc.
 *
 * Profile block to show for a group
 *
 * PHP version 5
 *
 * 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 2011 StatusNet, Inc.
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
 * @link      http://status.net/
 */

if (!defined('STATUSNET')) {
    // This check helps protect against security problems;
    // your code file can't be executed directly from the web.
    exit(1);
}

/**
 * Profile block to show for a group
 *
 * @category  Widget
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @copyright 2011 StatusNet, Inc.
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
 * @link      http://status.net/
 */
class GroupProfileBlock extends ProfileBlock
{
    protected $group = null;

    function __construct($out, $group)
    {
        parent::__construct($out);
        $this->group = $group;
        $this->profile = $this->group->getProfile();
    }

    protected function showAvatar(Profile $profile, $size=null)
    {
        $avatar_url = $profile->getGroup()->homepage_logo ?: User_group::defaultLogo($size ?: $this->avatarSize());
        $this->out->element('img', array('src' => $avatar_url,
                                         'class' => 'avatar u-photo',
                                         'width' => $this->avatarSize(),
                                         'height' => $this->avatarSize(),
                                         'alt' => $profile->getBestName()));
    }

    function name()
    {
        return $this->group->getBestName();
    }

    function url()
    {
        return $this->group->homeUrl();
    }

    function location()
    {
        return $this->group->location;
    }

    function homepage()
    {
        return $this->group->homepage;
    }

    function description()
    {
        return $this->group->description;
    }

    function otherProfiles()
    {
        return array();
    }

    function showActions()
    {
        $cur = common_current_user();
        $this->out->elementStart('div', 'entity_actions');
        // TRANS: Group actions header (h2). Text hidden by default.
        $this->out->element('h2', null, _('Group actions'));
        $this->out->elementStart('ul');
        if (Event::handle('StartGroupActionsList', array($this, $this->group))) {
            $this->out->elementStart('li', 'entity_subscribe');
            if (Event::handle('StartGroupSubscribe', array($this, $this->group))) {
                if ($cur) {
                    $profile = $cur->getProfile();
                    if ($profile->isMember($this->group)) {
                        $lf = new LeaveForm($this->out, $this->group);
                        $lf->show();
                    } else if ($profile->isPendingMember($this->group)) {
                        $cf = new CancelGroupForm($this->out, $this->group);
                        $cf->show();
                    } else if (!Group_block::isBlocked($this->group, $profile)) {
                        $jf = new JoinForm($this->out, $this->group);
                        $jf->show();
                    }
                }
                Event::handle('EndGroupSubscribe', array($this, $this->group));
            }
            $this->out->elementEnd('li');
            if ($cur && $cur->isAdmin($this->group)) {
                $this->out->elementStart('li', 'entity_edit');
                $this->out->element('a', array('href' => common_local_url('editgroup',
                                                                          array('nickname' => $this->group->nickname)),
                                               // TRANS: Tooltip for menu item in the group navigation page. Only shown for group administrators.
                                               // TRANS: %s is the nickname of the group.
                                               'title' => sprintf(_m('TOOLTIP','Edit %s group properties'), $this->group->nickname)),
                                    // TRANS: Link text for link on user profile.
                                    _m('BUTTON','Edit'));
                $this->out->elementEnd('li');
                $this->out->elementStart('li', 'entity_edit');
                $this->out->element('a', array('href' => common_local_url('grouplogo',
                                                                          array('nickname' => $this->group->nickname)),
                                               // TRANS: Tooltip for menu item in the group navigation page. Only shown for group administrators.
                                               // TRANS: %s is the nickname of the group.
                                               'title' => sprintf(_m('TOOLTIP','Add or edit %s logo'), $this->group->nickname)),
                                    // TRANS: Link text for link on user profile.
                                    _m('MENU','Logo'));
                $this->out->elementEnd('li');
            }
            if ($cur && $cur->hasRight(Right::DELETEGROUP)) {
                $this->out->elementStart('li', 'entity_delete');
                $df = new DeleteGroupForm($this->out, $this->group);
                $df->show();
                $this->out->elementEnd('li');
            }

            Event::handle('EndGroupActionsList', array($this, $this->group));
        }
        $this->out->elementEnd('ul');
        $this->out->elementEnd('div');
    }

    function show()
    {
        $this->out->elementStart('div', 'profile_block group_profile_block section');
        if (Event::handle('StartShowGroupProfileBlock', array($this->out, $this->group))) {
            parent::show();
            Event::handle('EndShowGroupProfileBlock', array($this->out, $this->group));
        }
        $this->out->elementEnd('div');
    }

    function showName()
    {
        parent::showName();
        $this->showAliases();
    }

    function showAliases()
    {
        $aliases = $this->group->getAliases();

        if (!empty($aliases)) {
            $this->out->elementStart('ul', 'group_aliases');
            foreach ($aliases as $alias) {
                $this->out->element('li', 'group_alias', $alias);
            }
            $this->out->elementEnd('ul');
        }
    }
}


code:
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social 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.
//
// GNU social 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 GNU social.  If not, see <http://www.gnu.org/licenses/>.

/**
 * Groups with the most members section
 *
 * @category  Widget
 * @package   GNUsocial
 * @author    Evan Prodromou <evan@status.net>
 * @copyright 2009 StatusNet, Inc.
 * @license   https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
 */

defined('GNUSOCIAL') || die();

/**
 * Groups with the most members section
 *
 * @copyright 2019 Free Software Foundation, Inc http://www.fsf.org
 * @license   https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
 */
class GroupsByMembersSection extends GroupSection
{
    public function getGroups()
    {
        $limit = GROUPS_PER_SECTION;

        $qry = <<<END
            SELECT *
              FROM user_group INNER JOIN (
                SELECT group_id AS id, COUNT(group_id) AS value
                  FROM group_member
                  GROUP BY group_id
              ) AS t1 USING (id)
              ORDER BY value DESC LIMIT {$limit};
            END;

        $group = Memcached_DataObject::cachedQuery('User_group', $qry, 3600);
        return $group;
    }

    public function title()
    {
        // TRANS: Title for groups with the most members section.
        return _('Popular groups');
    }

    public function divId()
    {
        return 'top_groups_by_member';
    }
}


code:
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social 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.
//
// GNU social 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 GNU social.  If not, see <http://www.gnu.org/licenses/>.

/**
 * Groups with the most posts section
 *
 * @category  Widget
 * @package   GNUsocial
 * @author    Evan Prodromou <evan@status.net>
 * @copyright 2009 StatusNet, Inc.
 * @license   https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
 */

defined('GNUSOCIAL') || die();

/**
 * Groups with the most posts section
 *
 * @category  Widget
 * @package   GNUsocial
 * @author    Evan Prodromou <evan@status.net>
 * @license   https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
 */
class GroupsByPostsSection extends GroupSection
{
    public function getGroups()
    {
        $limit = GROUPS_PER_SECTION;

        $qry = <<<END
            SELECT *
              FROM user_group INNER JOIN (
                SELECT group_id AS id, COUNT(group_id) AS value
                  FROM group_inbox
                  GROUP BY group_id
              ) AS t1 USING (id)
              ORDER BY value DESC LIMIT {$limit};
            END;

        $group = Memcached_DataObject::cachedQuery('User_group', $qry, 3600);
        return $group;
    }

    public function title()
    {
        // TRANS: Title for groups with the most posts section.
        return _('Active groups');
    }

    public function divId()
    {
        return 'top_groups_by_post';
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Base class for sections showing lists of groups
 *
 * 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('GROUPS_PER_SECTION', 6);

/**
 * 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/
 */
abstract class GroupSection extends Section
{
    function showContent()
    {
        $profiles = $this->getGroups();

        if (!$profiles) {
            return false;
        }

        $cnt = 0;

        $this->out->elementStart('table');

        while ($profiles->fetch() && ++$cnt <= GROUPS_PER_SECTION) {
            $this->showGroup($profiles);
        }

        $this->out->elementEnd('table');

        return ($cnt > GROUPS_PER_SECTION);
    }

    function getGroups()
    {
        return null;
    }

    function showGroup($group)
    {
        $this->out->elementStart('tr');
        $this->out->elementStart('td');
        $this->out->elementStart('a', array('title' => $group->getBestName(),
                                            'href' => $group->homeUrl(),
                                            'rel' => 'contact group',
                                            'class' => 'h-card org nickname'));
        $logo = $group->stream_logo ?: User_group::defaultLogo(AVATAR_STREAM_SIZE);
        $this->out->element('img', array('src' => $logo,
                                         'width' => AVATAR_MINI_SIZE,
                                         'height' => AVATAR_MINI_SIZE,
                                         'class' => 'avatar u-photo',
                                         'alt' =>  $group->getBestName()));
        $this->out->text($group->nickname);
        $this->out->elementEnd('a');
        $this->out->elementEnd('td');
        if ($group->value) {
            $this->out->element('td', 'value', $group->value);
        }
        $this->out->elementEnd('tr');
    }
}


code:
<?php
/**
 * StatusNet - the distributed open-source microblogging tool
 * Copyright (C) 2011, StatusNet, Inc.
 *
 * Menu for streams
 *
 * PHP version 5
 *
 * 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  Cache
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @copyright 2011 StatusNet, Inc.
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
 * @link      http://status.net/
 */

if (!defined('STATUSNET')) {
    // This check helps protect against security problems;
    // your code file can't be executed directly from the web.
    exit(1);
}

/**
 * Menu for streams you follow
 *
 * @category  General
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @copyright 2011 StatusNet, Inc.
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
 * @link      http://status.net/
 */
class GroupsNav extends MoreMenu
{
    protected $user;
    protected $groups;

    function __construct($action, $user)
    {
        parent::__construct($action);
        $this->user = $user;
        $this->groups = $user->getGroups();
    }

    function haveGroups()
    {
        return ($this->groups instanceof User_group && $this->groups->N > 0);
    }

    function tag()
    {
        return 'groups';
    }

    function getItems()
    {
        $items = array();

        while ($this->groups instanceof User_group && $this->groups->fetch()) {
            $items[] = array('placeholder',
                             array('nickname' => $this->groups->getNickname(),
                                   'mainpage' => $this->groups->homeUrl()),
                             $this->groups->getNickname(),
                             $this->groups->getBestName()
                            );
        }

        return $items;
    }

    function seeAllItem() {
        return array('usergroups',
                     array('nickname' => $this->user->nickname),
                     // TRANS: Link description for seeing all groups.
                     _('See all'),
                     // TRANS: Link title for seeing all groups.
                     _('See all groups you belong to.'));
    }

    function item($actionName, array $args, $label, $description, $id=null, $cls=null)
    {
        if ($actionName != 'placeholder') {
            return parent::item($actionName, $args, $label, $description, $id, $cls);
        }

        if (empty($id)) {
            $id = $this->menuItemID('showgroup', array('nickname' => $args['nickname']));
        }

        $url = $args['mainpage'];

        $this->out->menuItem($url,
                             $label,
                             $description,
                             $this->isCurrent($actionName, $args),
                             $id,
                             $cls);
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Form for joining a group
 *
 * 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  Form
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @author    Sarven Capadisli <csarven@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); }

/**
 * Form for joining a group
 *
 * @category Form
 * @package  StatusNet
 * @author   Evan Prodromou <evan@status.net>
 * @author   Sarven Capadisli <csarven@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/
 *
 * @see      UnsubscribeForm
 */
class JoinForm extends Form
{
    /**
     * group for user to join
     */
    var $group = null;

    /**
     * Constructor
     *
     * @param HTMLOutputter $out   output channel
     * @param User_group    $group group to join
     */
    function __construct(HTMLOutputter $out=null, User_group $group=null)
    {
        parent::__construct($out);

        $this->group = $group;
    }

    /**
     * ID of the form
     *
     * @return string ID of the form
     */
    function id()
    {
        return 'group-join-' . $this->group->getID();
    }

    /**
     * class of the form
     *
     * @return string of the form class
     */
    function formClass()
    {
        return 'form_group_join ajax';
    }

    /**
     * Action of the form
     *
     * @return string URL of the action
     */
    function action()
    {
        return common_local_url('joingroup', array('id' => $this->group->getID()));
    }

    /**
     * Action elements
     *
     * @return void
     */
    function formActions()
    {
        // TRANS: Button text for joining a group.
        $this->out->submit('submit', _m('BUTTON','Join'));
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Form for leaving a group
 *
 * 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  Form
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @author    Sarven Capadisli <csarven@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); }

/**
 * Form for leaving a group
 *
 * @category Form
 * @package  StatusNet
 * @author   Evan Prodromou <evan@status.net>
 * @author   Sarven Capadisli <csarven@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/
 *
 * @see      UnsubscribeForm
 */
class LeaveForm extends Form
{
    /**
     * group for user to leave
     */

    var $group = null;

    /**
     * Constructor
     *
     * @param HTMLOutputter $out   output channel
     * @param User_group    $group group to leave
     */
    function __construct(HTMLOutputter $out=null, User_group $group=null)
    {
        parent::__construct($out);

        $this->group = $group;
    }

    /**
     * ID of the form
     *
     * @return string ID of the form
     */
    function id()
    {
        return 'group-leave-' . $this->group->getID();
    }

    /**
     * class of the form
     *
     * @return string of the form class
     */
    function formClass()
    {
        return 'form_group_leave ajax';
    }

    /**
     * Action of the form
     *
     * @return string URL of the action
     */
    function action()
    {
        return common_local_url('leavegroup', array('id' => $this->group->getID()));
    }

    /**
     * Action elements
     *
     * @return void
     */
    function formActions()
    {
        // TRANS: Button text on form to leave a group.
        $this->out->submit('submit', _m('BUTTON','Leave'));
    }
}


code:
<?php
// @todo FIXME: add standard file header.

/**
 * Form for making a user an admin for a group
 *
 * @category Form
 * @package  StatusNet
 * @author   Evan Prodromou <evan@status.net>
 * @author   Sarven Capadisli <csarven@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 MakeAdminForm extends Form
{
    /**
     * Profile of user to block
     */
    var $profile = null;

    /**
     * Group to block the user from
     */
    var $group = null;

    /**
     * Return-to args
     */
    var $args = null;

    /**
     * Constructor
     *
     * @param HTMLOutputter $out     output channel
     * @param Profile       $profile profile of user to block
     * @param User_group    $group   group to block user from
     * @param array         $args    return-to args
     */
    function __construct($out=null, $profile=null, $group=null, $args=null)
    {
        parent::__construct($out);

        $this->profile = $profile;
        $this->group   = $group;
        $this->args    = $args;
    }

    /**
     * ID of the form
     *
     * @return int ID of the form
     */
    function id()
    {
        // This should be unique for the page.
        return 'makeadmin-' . $this->profile->id;
    }

    /**
     * class of the form
     *
     * @return string class of the form
     */
    function formClass()
    {
        return 'form_make_admin';
    }

    /**
     * Action of the form
     *
     * @return string URL of the action
     */
    function action()
    {
        return common_local_url('makeadmin', array('nickname' => $this->group->nickname));
    }

    /**
     * Legend of the Form
     *
     * @return void
     */
    function formLegend()
    {
        // TRANS: Form legend for form to make a user a group admin.
        $this->out->element('legend', null, _('Make user an admin of the group'));
    }

    /**
     * Data elements of the form
     *
     * @return void
     */
    function formData()
    {
        $this->out->hidden('profileid-' . $this->profile->id,
                           $this->profile->id,
                           'profileid');
        $this->out->hidden('groupid-' . $this->group->id,
                           $this->group->id,
                           'groupid');
        if ($this->args) {
            foreach ($this->args as $k => $v) {
                $this->out->hidden('returnto-' . $k, $v);
            }
        }
    }

    /**
     * Action elements
     *
     * @return void
     */
    function formActions()
    {
        $this->out->submit(
          'submit',
          // TRANS: Button text for the form that will make a user administrator.
          _m('BUTTON','Make Admin'),
          'submit',
          null,
          // TRANS: Submit button title.
          _m('TOOLTIP','Make this user an admin.'));
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Menu for public group of actions
 *
 * 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  Menu
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @copyright 2008 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); }

/**
 * Menu for public group of actions
 *
 * @category Output
 * @package  StatusNet
 * @author   Evan Prodromou <evan@status.net>
 * @author   Sarven Capadisli <csarven@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/
 *
 * @see      Widget
 */
class PublicGroupNav extends Menu
{

    var $actionName = null;

    /**
     * Show the menu
     *
     * @return void
     */
    function show()
    {
        $this->actionName = $this->action->trimmed('action');

        $this->action->elementStart('ul', array('class' => 'nav'));

        if (Event::handle('StartPublicGroupNav', array($this))) {
            if (!common_config('singleuser', 'enabled')) {
                // TRANS: Menu item in search group navigation panel.
                $this->out->menuItem(common_local_url('public'), _m('MENU','Public'),
                                     // TRANS: Menu item title in search group navigation panel.
                                     _('Public timeline'), $this->actionName == 'public', 'nav_timeline_public');
            }
            if (!common_config('public', 'localonly') || $this->action->getScoped() instanceof Profile) {
                // Allow network wide view if you're logged in
                // TRANS: Menu item in search group navigation panel.
                $this->out->menuItem(common_local_url('networkpublic'), _m('MENU','Network'),
                                     // TRANS: Menu item title in search group navigation panel.
                                     _('Network public timeline'), $this->actionName == 'networkpublic', 'nav_timeline_networkpublic');
            }

            // TRANS: Menu item in search group navigation panel.
            $this->out->menuItem(common_local_url('groups'), _m('MENU','Groups'),
                // TRANS: Menu item title in search group navigation panel.
                _('User groups'), $this->actionName == 'groups', 'nav_groups');

            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'),
                    // TRANS: Menu item title in search group navigation panel.
                    _('Featured users'), $this->actionName == 'featured', 'nav_featured');
            }

            Event::handle('EndPublicGroupNav', array($this));
        }
        $this->action->elementEnd('ul');
    }
}


code:
<?php

if (!defined('GNUSOCIAL')) { exit(1); }

class ThreadingGroupNoticeStream extends ThreadingNoticeStream
{
    function __construct($group, Profile $scoped=null)
    {
        parent::__construct(new GroupNoticeStream($group, $scoped));
    }
}


code:
<?php
/*
 * StatusNet - the distributed open-source microblogging tool
 * Copyright (C) 2008, 2009, StatusNet, Inc.
 *
 * 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/>.
 */

if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }

class IMChannel extends Channel
{

    var $imPlugin;

    function source()
    {
        return $imPlugin->transport;
    }

    function __construct($imPlugin)
    {
        $this->imPlugin = $imPlugin;
    }

    function on($user)
    {
        return $this->setNotify($user, 1);
    }

    function off($user)
    {
        return $this->setNotify($user, 0);
    }

    function output($user, $text)
    {
        $text = '['.common_config('site', 'name') . '] ' . $text;
        $this->imPlugin->sendMessage($this->imPlugin->getScreenname($user), $text);
    }

    function error($user, $text)
    {
        $text = '['.common_config('site', 'name') . '] ' . $text;

        $screenname = $this->imPlugin->getScreenname($user);
        if($screenname){
            $this->imPlugin->sendMessage($screenname, $text);
            return true;
        }else{
            common_log(LOG_ERR,
                'Could not send error message to user ' . common_log_objstring($user) .
                ' on transport ' . $this->imPlugin->transport .' : user preference does not exist');
            return false;
        }
    }

    function setNotify($user, $notify)
    {
        global $_PEAR;

        $user_im_prefs = new User_im_prefs();
        $user_im_prefs->transport = $this->imPlugin->transport;
        $user_im_prefs->user_id = $user->id;
        if($user_im_prefs->find() && $user_im_prefs->fetch()){
            if($user_im_prefs->notify == $notify){
                //notify is already set the way they want
                return true;
            }else{
                $original = clone($user_im_prefs);
                $user_im_prefs->notify = $notify;
                $result = $user_im_prefs->update($original);

                if (!$result) {
                    $last_error = &$_PEAR->getStaticProperty('DB_DataObject','lastError');
                    common_log(LOG_ERR,
                               'Could not set notify flag to ' . $notify .
                               ' for user ' . common_log_objstring($user) .
                               ' on transport ' . $this->imPlugin->transport .' : ' . $last_error->message);
                    return false;
                } else {
                    common_log(LOG_INFO,
                               'User ' . $user->nickname . ' set notify flag to ' . $notify);
                    return true;
                }
            }
        }else{
                common_log(LOG_ERR,
                           'Could not set notify flag to ' . $notify .
                           ' for user ' . common_log_objstring($user) .
                           ' on transport ' . $this->imPlugin->transport .' : user preference does not exist');
                return false;
        }
    }
}


code:
<?php
/*
 * StatusNet - the distributed open-source microblogging tool
 * Copyright (C) 2008, 2009, StatusNet, Inc.
 *
 * 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/>.
 */

if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }

/**
 * IKM background connection manager for IM-using queue handlers,
 * allowing them to send outgoing messages on the right connection.
 *
 * In a multi-site queuedaemon.php run, one connection will be instantiated
 * for each site being handled by the current process that has IM enabled.
 *
 * Implementations that extend this class will likely want to:
 * 1) override start() with their connection process.
 * 2) override handleInput() with what to do when data is waiting on
 *    one of the sockets
 * 3) override idle($timeout) to do keepalives (if necessary)
 * 4) implement send_raw_message() to send raw data that ImPlugin::enqueueOutgoingRaw
 *      enqueued
 */

abstract class ImManager extends IoManager
{
    abstract function send_raw_message($data);

    function __construct($imPlugin)
    {
        $this->plugin = $imPlugin;
        $this->plugin->imManager = $this;
    }

    /**
     * Fetch the singleton manager for the current site.
     * @return mixed ImManager, or false if unneeded
     */
    public static function get()
    {
        throw new Exception('ImManager should be created using it\'s constructor, not the static get method');
    }
}


code:
<?php
/*
 * StatusNet - the distributed open-source microblogging tool
 * Copyright (C) 2008, 2009, StatusNet, Inc.
 *
 * 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/>.
 */

defined('GNUSOCIAL') || die();

/**
 * Common superclass for all IM sending queue handlers.
 */

class ImQueueHandler extends QueueHandler
{
    function __construct($plugin)
    {
        $this->plugin = $plugin;
    }

    /**
     * Handle a notice
     * @param Notice $notice
     * @return boolean success
     */
    function handle($notice) : bool
    {
        if (!($notice instanceof Notice)) {
            common_log(LOG_ERR, "Got a bogus notice, not broadcasting");
            return true;
        }

        $this->plugin->broadcastNotice($notice);
        if ($notice->isLocal()) {
            $this->plugin->publicNotice($notice);
        }
        return true;
    }

}


code:
<?php
/*
 * StatusNet - the distributed open-source microblogging tool
 * Copyright (C) 2008, 2009, StatusNet, Inc.
 *
 * 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/>.
 */

if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }

/**
 * Common superclass for all IM receiving queue handlers.
 */

class ImReceiverQueueHandler extends QueueHandler
{
    function __construct($plugin)
    {
        $this->plugin = $plugin;
    }

    /**
     * Handle incoming IM data sent by a user to the IM bot
     * @param object $data
     * @return boolean success
     */
    function handle($data) : bool
    {
        return $this->plugin->receiveRawMessage($data);
    }
}