code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Form for tagging a profile with a peopletag
 *
 * 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 tagging a profile with a peopletag
 *
 * @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      HTMLOutputter
 */
class TagProfileForm extends Form
{
    protected $target = null;

    /**
     * Constructor
     *
     * @param Action $action  Action we're being embedded into
     * @param array  $options Array of optional parameters
     *                        'user' a user instead of current
     *                        'content' notice content
     *                        'inreplyto' ID of notice to reply to
     *                        'lat' Latitude
     *                        'lon' Longitude
     *                        'location_id' ID of location
     *                        'location_ns' Namespace of location
     */
    function __construct(Action $action, Profile $target)
    {
        parent::__construct($action);

        $this->target = $target;
    }

    /**
     * ID of the form
     *
     * @return string ID of the form
     */

    function id()
    {
        return 'form_tagprofile_'.$target->id;
    }

   /**
     * Class of the form
     *
     * @return string class of the form
     */

    function formClass()
    {
        return 'form_tagprofile form_settings';
    }

    /**
     * Action of the form
     *
     * @return string URL of the action
     */

    function action()
    {
        return common_local_url('tagprofile', array('id' => $this->target->id));
    }

    /**
     * Legend of the Form
     *
     * @return void
     */
    function formLegend()
    {
        // TRANS: Form legend for notice form.
        $this->out->element('legend', null, sprintf(_m('ADDTOLIST', 'List %s'), $this->target->getNickname()));

    }

    /**
     * Data elements
     *
     * @return void
     */
    function formData()
    {
        if (Event::handle('StartShowTagProfileFormData', array($this))) {
            $this->hidden('token', common_session_token());
            $this->hidden('id', $this->target->id);

            $this->elementStart('ul', 'form_data');
            $this->elementStart('li');

            $tags = Profile_tag::getTagsArray($this->out->getScoped()->id, $this->target->id, $this->out->getScoped()->id);
            // TRANS: Field label on list form.
            $this->input('tags', _m('LABEL','Lists'),
                         ($this->arg('tags')) ? $this->arg('tags') : implode(' ', $tags),
                         // TRANS: Field title on list form.
                         _('Lists for this user (letters, numbers, -, ., and _), comma- or space- separated.'));
            $this->elementEnd('li');
            $this->elementEnd('ul');
            Event::handle('EndShowTagProfileFormData', array($this));
        }
    }

    function formActions()
    {
        // TRANS: Button text to save lists.
        $this->out->submit('save', _m('BUTTON', 'Save'));
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Form for editing a peopletag
 *
 * 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    Shashi Gowda <connect2shashi@gmail.com>
 * @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 peopletag
 *
 * @category Form
 * @package  StatusNet
 * @author   Shashi Gowda <connect2shashi@gmail.com>
 * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 * @link     http://status.net/
 *
 * @see      GroupEditForm
 */
class SearchProfileForm extends Form
{
    var $peopletag;

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

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

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

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

    /**
     * Name of the form
     *
     * @return void
     */
    function formLegend()
    {
        // TRANS: Form legend.
        $this->out->element('legend', null, sprintf(_('Search and list people')));
    }

    /**
     * Data elements of the form
     *
     * @return void
     */
    function formData()
    {
        // TRANS: Dropdown option for searching in profiles.
        $fields = array('fulltext'    => _('Everything'),
                        // TRANS: Dropdown option for searching in profiles.
                        'nickname'    => _('Nickname'),
                        // TRANS: Dropdown option for searching in profiles.
                        'fullname'    => _('Fullname'),
                        // TRANS: Dropdown option for searching in profiles.
                        'description' => _('Description'),
                        // TRANS: Dropdown option for searching in profiles.
                        'location'    => _('Location'),
                        // TRANS: Dropdown option for searching in profiles.
                        'uri'         => _('URI (Remote users)'));

        $this->out->hidden('peopletag_id', $this->peopletag->id);
        $this->out->input('q', null);
        // TRANS: Dropdown field label.
        $this->out->dropdown('field', _m('LABEL','Search in'), $fields,
                        // TRANS: Dropdown field title.
                        _('Choose a field to search.'), false, 'fulltext');
    }

    /**
     * Action elements
     *
     * @return void
     */
    function formActions()
    {
        // TRANS: Button text to search profiles.
        $this->out->submit('submit', _m('BUTTON','Search'));
    }
}

class UntagButton extends Form
{
    var $profile;
    var $peopletag;

    function __construct($out, Profile $profile, Profile_list $peopletag)
    {
        parent::__construct($out);
        $this->profile = $profile;
        $this->peopletag = $peopletag;
    }

    /**
     * ID of the form
     *
     * @return string ID of the form
     */
    function id()
    {
        return 'form_peopletag-' . $this->peopletag->id . '-remove-' . $this->profile->id;
    }

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

    /**
     * Action of the form
     *
     * @return string URL of the action
     */

    function action()
    {
        return common_local_url('removepeopletag');
    }

    /**
     * Name of the form
     *
     * @return void
     */
    function formLegend()
    {
        // TRANS: Form legend.
        // TRANS: %1$s is a nickname, $2$s is a list.
        $this->out->element('legend', null, sprintf(_('Remove %1$s from list %2$s'),
            $this->profile->nickname, $this->peopletag->tag));
    }

    /**
     * Data elements of the form
     *
     * @return void
     */
    function formData()
    {
        $this->out->hidden('peopletag_id', $this->peopletag->id);
        $this->out->hidden('tagged', $this->profile->id);
    }

    /**
     * Action elements
     *
     * @return void
     */
    function formActions()
    {
        // TRANS: Button text to untag a profile.
        $this->out->submit('submit', _m('BUTTON','Remove'));
    }
}

class TagButton extends Form
{
    var $profile;
    var $peopletag;

    function __construct($out, Profile $profile, Profile_list $peopletag)
    {
        parent::__construct($out);
        $this->profile = $profile;
        $this->peopletag = $peopletag;
    }

    /**
     * ID of the form
     *
     * @return string ID of the form
     */
    function id()
    {
        return 'form_peopletag-' . $this->peopletag->id . '-add-' . $this->profile->id;
    }

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

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

    /**
     * Name of the form
     *
     * @return void
     */
    function formLegend()
    {
        // TRANS: Legend on form to add a profile to a list.
        // TRANS: %1$s is a nickname, %2$s is a list.
        $this->out->element('legend', null, sprintf(_('Add %1$s to list %2$s'),
            $this->profile->nickname, $this->peopletag->tag));
    }

    /**
     * Data elements of the form
     *
     * @return void
     */
    function formData()
    {
        UntagButton::formData();
    }

    /**
     * Action elements
     *
     * @return void
     */
    function formActions()
    {
        // TRANS: Button text to tag a profile.
        $this->out->submit('submit', _m('BUTTON','Add'));
    }
}

class TaggedProfileItem extends Widget
{
    var $profile=null;

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

    function show()
    {
        $this->out->elementStart('a', array('class' => 'url',
                                            'href' => $this->profile->profileurl,
                                            'title' => $this->profile->getBestName()));
        $avatarUrl = $this->profile->avatarUrl(AVATAR_MINI_SIZE);
        $this->out->element('img', array('src' => $avatarUrl,
                                         'width' => AVATAR_MINI_SIZE,
                                         'height' => AVATAR_MINI_SIZE,
                                         'class' => 'avatar photo',
                                         'alt' => $this->profile->getBestName()));
        $this->out->element('span', 'fn nickname', $this->profile->nickname);
        $this->out->elementEnd('a');
    }
}

repo_name: suraj/sloth

license: mit


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Form for unblocking a user
 *
 * 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')) {
    exit(1);
}

/**
 * Form for unblocking a user
 *
 * @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 UnblockForm extends ProfileActionForm
{
    /**
     * Action this form provides
     *
     * @return string Name of the action, lowercased.
     */
    function target()
    {
        return 'unblock';
    }

    /**
     * Title of the form
     *
     * @return string Title of the form, internationalized
     */
    function title()
    {
        // TRANS: Title for the form to unblock a user.
        return _m('TITLE','Unblock');
    }

    /**
     * Description of the form
     *
     * @return string description of the form, internationalized
     */
    function description()
    {
        // TRANS: Description of the form to unblock a user.
        return _('Unblock this user');
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Form for unsubscribing from a user
 *
 * 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 unsubscribing from a user
 *
 * @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      SubscribeForm
 */
class UnsubscribeForm extends Form
{
    /**
     * Profile of user to unsubscribe from
     */

    var $profile = null;

    /**
     * Constructor
     *
     * @param HTMLOutputter $out     output channel
     * @param Profile       $profile profile of user to unsub from
     */
    function __construct($out=null, $profile=null)
    {
        parent::__construct($out);

        $this->profile = $profile;
    }

    /**
     * ID of the form
     *
     * @return int ID of the form
     */
    function id()
    {
        return 'unsubscribe-' . $this->profile->id;
    }

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

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

    /**
     * Legend of the Form
     *
     * @return void
     */
    function formLegend()
    {
        // TRANS: Form legend on unsubscribe form.
        $this->out->element('legend', null, _('Unsubscribe from this user'));
    }

    /**
     * Data elements of the form
     *
     * @return void
     */
    function formData()
    {
        $this->out->hidden('unsubscribeto-' . $this->profile->id,
                           $this->profile->id,
                           'unsubscribeto');
    }

    /**
     * Action elements
     *
     * @return void
     */
    function formActions()
    {
        // TRANS: Button text on unsubscribe form.
        $this->out->submit('submit', _m('BUTTON','Unsubscribe'), 'submit', null,
                           // TRANS: Button title on unsubscribe form.
                           _('Unsubscribe from this user.'));
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Form for unsubscribing to a peopletag
 *
 * 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    Shashi Gowda <connect2shashi@gmail.com>
 * @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 unsubscribing to a peopletag
 *
 * @category Form
 * @package  StatusNet
 * @author   Shashi Gowda <connect2shashi@gmail.com>
 * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 * @link     http://status.net/
 *
 * @see      UnunsubscribeForm
 */
class UnsubscribePeopletagForm extends Form
{
    /**
     * peopletag for the user to join
     */
    var $peopletag = null;

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

        $this->peopletag = $peopletag;
    }

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

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

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

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


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();

/**
 * Queue handler for pushing new notices to ping servers.
 */
class PingQueueHandler extends QueueHandler {

    function transport()
    {
        return 'ping';
    }

    function handle($notice) : bool
    {
        if (!($notice instanceof Notice)) {
            common_log(LOG_ERR, "Got a bogus notice, not broadcasting");
            return true;
        }

        require_once INSTALLDIR . '/lib/util/ping.php';
        return ping_broadcast_notice($notice);
    }
}


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/>.

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

/**
 * Queue handler for letting plugins handle stuff.
 *
 * The module queue handler accepts notices over the "plugin" queue
 * and simply passes them through the "HandleQueuedNotice" event.
 *
 * This gives plugins a chance to do background processing without
 * actually registering their own queue and ensuring that things
 * are queued into it.
 *
 * Fancier plugins may wish to instead hook the 'GetQueueHandlerClass'
 * event with their own class, in which case they must ensure that
 * their notices get enqueued when they need them.
 */
class PluginQueueHandler extends QueueHandler
{
    function transport()
    {
        return 'plugin';
    }

    function handle($notice): bool
    {
        if (!($notice instanceof Notice)) {
            common_log(LOG_ERR, "Got a bogus notice, not broadcasting");
            return true;
        }

        try {
            Event::handle('HandleQueuedNotice', array(&$notice));
        } catch (NoProfileException $unp) {
            // We can't do anything about this, so just skip
            return true;
        }
        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); }

/**
 * Base class for queue handlers.
 *
 * As of 0.9, queue handlers are short-lived for items as they are
 * dequeued by a QueueManager running in an IoMaster in a daemon
 * such as queuedaemon.php.
 *
 * Extensions requiring long-running maintenance or polling should
 * register an IoManager.
 *
 * Subclasses must override at least the following methods:
 * - transport
 * - handle
 */
class QueueHandler
{

    /**
     * Here's the meat of your queue handler -- you're handed a Notice
     * or other object, which you may do as you will with.
     *
     * If this function indicates failure, a warning will be logged
     * and the item is placed back in the queue to be re-run.
     *
     * @param mixed $object
     * @return boolean true on success, false on failure
     */
    function handle($object) : bool
    {
        return true;
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Abstract class for i/o managers
 *
 * 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  QueueManager
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @author    Sarven Capadisli <csarven@status.net>
 * @author    Brion Vibber <brion@status.net>
 * @copyright 2009-2010 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/
 */

/**
 * Completed child classes must implement the enqueue() method.
 *
 * For background processing, classes should implement either socket-based
 * input (handleInput(), getSockets()) or idle-loop polling (idle()).
 */
abstract class QueueManager extends IoManager
{
    static $qm = null;

    protected $master = null;
    protected $handlers = array();
    protected $groups = array();
    protected $activeGroups = array();
    protected $ignoredTransports = array();

    /**
     * Factory function to pull the appropriate QueueManager object
     * for this site's configuration. It can then be used to queue
     * events for later processing or to spawn a processing loop.
     *
     * Plugins can add to the built-in types by hooking StartNewQueueManager.
     *
     * @return QueueManager
     */
    public static function get()
    {
        if (empty(self::$qm)) {

            if (Event::handle('StartNewQueueManager', array(&self::$qm))) {
                common_log(LOG_ERR, 'Some form of queue manager must be active' .
                           '(UnQueue does everything immediately and is the default)');
                throw new ServerException('Some form of queue manager must be active');
            }
        }

        return self::$qm;
    }

    /**
     * @fixme wouldn't necessarily work with other class types.
     * Better to change the interface...?
     */
    public static function multiSite()
    {
        if (common_config('queue', 'subsystem') == 'stomp') {
            return IoManager::INSTANCE_PER_PROCESS;
        } else {
            return IoManager::SINGLE_ONLY;
        }
    }

    function __construct()
    {
        $this->initialize();
    }

    /**
     * Optional; ping any running queue handler daemons with a notification
     * such as announcing a new site to handle or requesting clean shutdown.
     * This avoids having to restart all the daemons manually to update configs
     * and such.
     *
     * Called from scripts/queuectl.php controller utility.
     *
     * @param string $event event key
     * @param string $param optional parameter to append to key
     * @return boolean success
     */
    public function sendControlSignal($event, $param='')
    {
        throw new Exception(get_class($this) . " does not support control signals.");
    }

    /**
     * Store an object (usually/always a Notice) into the given queue
     * for later processing. No guarantee is made on when it will be
     * processed; it could be immediately or at some unspecified point
     * in the future.
     *
     * Must be implemented by any queue manager.
     *
     * @param Notice $object
     * @param string $queue
     */
    abstract function enqueue($object, $queue);

    /**
     * Build a representation for an object for logging
     * @param mixed
     * @return string
     */
    function logrep($object) {
        if (is_object($object)) {
            $class = get_class($object);
            if (isset($object->id)) {
                return "$class $object->id";
            }
            return $class;
        } elseif (is_string($object)) {
            $len = strlen($object);
            $fragment = mb_substr($object, 0, 32);
            if (mb_strlen($object) > 32) {
                $fragment .= '...';
            }
            return "string '$fragment' ($len bytes)";
        } elseif (is_array($object)) {
            return 'array with ' . count($object) .
                   ' elements (keys:[' .  implode(',', array_keys($object)) . '])';
        }
        return strval($object);
    }

    /**
     * Encode an object for queued storage.
     *
     * @param mixed $item
     * @return string
     */
    protected function encode($item): string
    {
        return serialize($item);
    }

    /**
     * Decode an object from queued storage.
     * Accepts notice reference entries and serialized items.
     *
     * @param string
     * @return mixed
     */
    protected function decode(string $frame)
    {
        $object = unserialize($frame);

        // If it is a string, we really store a JSON object in there
        // except if it begins with '<', because then it is XML.
        if (is_string($object) &&
            substr($object, 0, 1) != '<' &&
            !is_numeric($object))
        {
            $json = json_decode($object);
            if ($json === null) {
                throw new Exception('Bad frame in queue item');
            }

            // The JSON object has a type parameter which contains the class
            if (empty($json->type)) {
                throw new Exception('Type not specified for queue item');
            }
            if (!is_a($json->type, 'Managed_DataObject', true)) {
                throw new Exception('Managed_DataObject class does not exist for queue item');
            }

            // And each of these types should have a unique id (or uri)
            if (isset($json->id) && !empty($json->id)) {
                $object = call_user_func(array($json->type, 'getKV'), 'id', $json->id);
            } elseif (isset($json->uri) && !empty($json->uri)) {
                $object = call_user_func(array($json->type, 'getKV'), 'uri', $json->uri);
            }

            // But if no object was found, there's nothing we can handle
            if (!$object instanceof Managed_DataObject) {
                throw new Exception('Queue item frame referenced a non-existant object');
            }
        }

        // If the frame was not a string, it's either an array or an object.

        return $object;
    }

    /**
     * Instantiate the appropriate QueueHandler class for the given queue.
     *
     * @param string $queue
     * @return mixed QueueHandler or null
     */
    function getHandler($queue)
    {
        if (isset($this->handlers[$queue])) {
            $class = $this->handlers[$queue];
            if(is_object($class)) {
                return $class;
            } else if (class_exists($class)) {
                return new $class();
            } else {
                $this->_log(LOG_ERR, "Nonexistent handler class '$class' for queue '$queue'");
            }
        }
        throw new NoQueueHandlerException($queue);
    }

    /**
     * Get a list of registered queue transport names to be used
     * for listening in this daemon.
     *
     * @return array of strings
     */
    function activeQueues()
    {
        $queues = array();
        foreach ($this->activeGroups as $group) {
            if (isset($this->groups[$group])) {
                $queues = array_merge($queues, $this->groups[$group]);
            }
        }

        return array_keys($queues);
    }

    function getIgnoredTransports()
    {
        return array_keys($this->ignoredTransports);
    }

    function ignoreTransport($transport)
    {
        // key is used for uniqueness, value doesn't mean anything
        $this->ignoredTransports[$transport] = true;
    }

    /**
     * Initialize the list of queue handlers for the current site.
     *
     * @event StartInitializeQueueManager
     * @event EndInitializeQueueManager
     */
    function initialize()
    {
        $this->handlers = array();
        $this->groups = array();
        $this->groupsByTransport = array();

        if (Event::handle('StartInitializeQueueManager', array($this))) {
            $this->connect('distrib', 'DistribQueueHandler');
            $this->connect('ping', 'PingQueueHandler');
            if (common_config('sms', 'enabled')) {
                $this->connect('sms', 'SmsQueueHandler');
            }

            // Background user management tasks...
            $this->connect('deluser', 'DelUserQueueHandler');
            $this->connect('feedimp', 'FeedImporter');
            $this->connect('actimp', 'ActivityImporter');
            $this->connect('acctmove', 'AccountMover');
            $this->connect('actmove', 'ActivityMover');

            // For compat with old plugins not registering their own handlers.
            $this->connect('Module', 'ModuleQueueHandler');
        }
        Event::handle('EndInitializeQueueManager', array($this));
    }

    /**
     * Register a queue transport name and handler class for your plugin.
     * Only registered transports will be reliably picked up!
     *
     * @param string $transport
     * @param string $class class name or object instance
     * @param string $group
     */
    public function connect($transport, $class, $group='main')
    {
        $this->handlers[$transport] = $class;
        $this->groups[$group][$transport] = $class;
        $this->groupsByTransport[$transport] = $group;
    }

    /**
     * Set the active group which will be used for listening.
     * @param string $group
     */
    function setActiveGroup($group)
    {
        $this->activeGroups = array($group);
    }

    /**
     * Set the active group(s) which will be used for listening.
     * @param array $groups
     */
    function setActiveGroups($groups)
    {
        $this->activeGroups = $groups;
    }

    /**
     * @return string queue group for this queue
     */
    function queueGroup($queue)
    {
        if (isset($this->groupsByTransport[$queue])) {
            return $this->groupsByTransport[$queue];
        } else {
            throw new Exception("Requested group for unregistered transport $queue");
        }
    }

    /**
     * Send a statistic ping to the queue monitoring system,
     * optionally with a per-queue id.
     *
     * @param string $key
     * @param string $queue
     */
    function stats($key, $queue=false)
    {
        $owners = array();
        if ($queue) {
            $owners[] = "queue:$queue";
            $owners[] = "site:" . common_config('site', 'server');
        }
        if (isset($this->master)) {
            $this->master->stats($key, $owners);
        } else {
            $monitor = new QueueMonitor();
            $monitor->stats($key, $owners);
        }
    }

    protected function _log($level, $msg)
    {
        $class = get_class($this);
        if ($this->activeGroups) {
            $groups = ' (' . implode(',', $this->activeGroups) . ')';
        } else {
            $groups = '';
        }
        common_log($level, "$class$groups: $msg");
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Monitoring output helper for IoMaster and IoManager/QueueManager
 *
 * 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  QueueManager
 * @package   StatusNet
 * @author    Brion Vibber <brion@status.net>
 * @copyright 2010 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/
 */

class QueueMonitor
{
    protected $monSocket = null;

    /**
     * Increment monitoring statistics for a given counter, if configured.
     * Only explicitly listed thread/site/queue owners will be incremented.
     *
     * @param string $key counter name
     * @param array $owners list of owner keys like 'queue:xmpp' or 'site:stat01'
     */
    public function stats($key, $owners=array())
    {
        $this->ping(array('counter' => $key,
                          'owners' => $owners));
    }

    /**
     * Send thread state update to the monitoring server, if configured.
     *
     * @param string $thread ID (eg 'generic.1')
     * @param string $state ('init', 'queue', 'shutdown' etc)
     * @param string $substate (optional, eg queue name 'omb' 'sms' etc)
     */
    public function logState($threadId, $state, $substate='')
    {
        $this->ping(array('thread_id' => $threadId,
                          'state' => $state,
                          'substate' => $substate,
                          'ts' => microtime(true)));
    }

    /**
     * General call to the monitoring server
     */
    protected function ping($data)
    {
        $target = common_config('queue', 'monitor');
        if (empty($target)) {
            return;
        }

        $data = $this->prepMonitorData($data);

        if (substr($target, 0, 4) == 'udp:') {
            $this->pingUdp($target, $data);
        } else if (substr($target, 0, 5) == 'http:') {
            $this->pingHttp($target, $data);
        } else {
            common_log(LOG_ERR, __METHOD__ . ' unknown monitor target type ' . $target);
        }
    }

    protected function pingUdp($target, $data)
    {
        if (!$this->monSocket) {
            $this->monSocket = stream_socket_client($target, $errno, $errstr);
        }
        if ($this->monSocket) {
            $post = http_build_query($data, '', '&');
            stream_socket_sendto($this->monSocket, $post);
        } else {
            common_log(LOG_ERR, __METHOD__ . " UDP logging fail: $errstr");
        }
    }

    protected function pingHttp($target, $data)
    {
        $client = new HTTPClient();
        try {
            $result = $client->post($target, array(), $data);

            if (!$result->isOk()) {
                common_log(LOG_ERR, __METHOD__ . ' HTTP ' . $result->getStatus() . ': ' . $result->getBody());
            }
        } catch (NoHttpResponseException $e) {
            common_log(LOG_ERR, __METHOD__ . ':'.$e->getMessage());
        } catch (HTTP_Request2_Exception $e) {
            common_log(LOG_ERR, __CLASS__ . ": Invalid $code redirect from $url to $target");
        }
    }

    protected function prepMonitorData($data)
    {
        #asort($data);
        #$macdata = http_build_query($data, '', '&');
        #$key = 'This is a nice old key';
        #$data['hmac'] = hash_hmac('sha256', $macdata, $key);
        return $data;
    }

}


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();

/**
 * Queue handler for pushing new notices to local subscribers using SMS.
 */
class SmsQueueHandler extends QueueHandler
{
    function transport()
    {
        return 'sms';
    }

    function handle($notice) : bool
    {
        if (!($notice instanceof Notice)) {
            common_log(LOG_ERR, "Got a bogus notice, not broadcasting");
            return true;
        }

        require_once INSTALLDIR . '/lib/util/mail.php';
        return mail_broadcast_notice_sms($notice);
    }
}


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/>.

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

class SearchEngine
{
    protected $target;
    protected $table;

    public function __construct($target, $table)
    {
        $this->target = $target;
        $this->table = $table;
    }

    public function query($q)
    {
    }

    public function limit($offset, $count, $rss = false)
    {
        return $this->target->limit($offset, $count);
    }

    public function set_sort_mode($mode)
    {
        switch ($mode) {
            case 'chron':
                return $this->target->orderBy('created DESC');
                break;
            case 'reverse_chron':
                return $this->target->orderBy('created ASC');
                break;
            case 'nickname_desc':
                if ($this->table != 'profile') {
                    throw new Exception(
                        'nickname_desc sort mode can only be use when searching profile.'
                    );
                } else {
                    return $this->target->orderBy(sprintf('%1$s.nickname DESC', $this->table));
                }
                break;
            case 'nickname_asc':
                if ($this->table != 'profile') {
                    throw new Exception(
                        'nickname_desc sort mode can only be use when searching profile.'
                    );
                } else {
                    return $this->target->orderBy(sprintf('%1$s.nickname ASC', $this->table));
                }
                break;
            default:
                return $this->target->orderBy('created DESC');
                break;
        }
    }
}

class PostgreSQLSearch extends SearchEngine
{
    public function query($q)
    {
        if ($this->table === 'profile') {
            $cols = implode(" || ' ' || ", array_map(
                function ($col) {
                    return sprintf(
                        "COALESCE(%s.%s, '')",
                        common_database_tablename($this->table),
                        $col
                    );
                },
                ['nickname', 'fullname', 'location', 'bio', 'homepage']
            ));

            $this->target->whereAdd(sprintf(
                'to_tsvector(\'english\', %2$s) @@ plainto_tsquery(\'%1$s\')',
                $this->target->escape($q, true),
                $cols
            ));
            return true;
        } elseif ($this->table === 'notice') {
            // Don't show imported notices
            $this->target->whereAdd('notice.is_local <> ' . Notice::GATEWAY);

            $this->target->whereAdd(sprintf(
                'to_tsvector(\'english\', content) @@ plainto_tsquery(\'%1$s\')',
                $this->target->escape($q, true)
            ));
            return true;
        } else {
            throw new ServerException('Unknown table: ' . $this->table);
        }
    }
}

class MySQLSearch extends SearchEngine
{
    public function query($q)
    {
        if ($this->table === 'profile') {
            $this->target->whereAdd(sprintf(
                'MATCH (%2$s.nickname, %2$s.fullname, %2$s.location, %2$s.bio, %2$s.homepage) ' .
                'AGAINST (\'%1$s\' IN BOOLEAN MODE)',
                $this->target->escape($q, true),
                $this->table
            ));
            if (strtolower($q) != $q) {
                $this->target->whereAdd(
                    sprintf(
                        'MATCH (%2$s.nickname, %2$s.fullname, %2$s.location, %2$s.bio, %2$s.homepage) ' .
                        'AGAINST (\'%1$s\' IN BOOLEAN MODE)',
                        $this->target->escape(strtolower($q), true),
                        $this->table
                    ),
                    'OR'
                );
            }
            return true;
        } elseif ($this->table === 'notice') {
            // Don't show imported notices
            $this->target->whereAdd('notice.is_local <> ' . Notice::GATEWAY);

            $this->target->whereAdd(sprintf(
                'MATCH (%2$s.content) AGAINST (\'%1$s\' IN BOOLEAN MODE)',
                $this->target->escape($q, true),
                $this->table
            ));
            if (strtolower($q) != $q) {
                $this->target->whereAdd(
                    sprintf(
                        'MATCH (%2$s.content) AGAINST (\'%1$s\' IN BOOLEAN MODE)',
                        $this->target->escape(strtolower($q), true),
                        $this->table
                    ),
                    'OR'
                );
            }

            return true;
        } else {
            throw new ServerException('Unknown table: ' . $this->table);
        }
    }
}

class SQLLikeSearch extends SearchEngine
{
    public function query($q)
    {
        if ($this->table === 'profile') {
            $qry = sprintf(
                '(   %2$s.nickname LIKE \'%%%1$s%%\' ' .
                ' OR %2$s.fullname LIKE \'%%%1$s%%\' ' .
                ' OR %2$s.location LIKE \'%%%1$s%%\' ' .
                ' OR %2$s.bio      LIKE \'%%%1$s%%\' ' .
                ' OR %2$s.homepage LIKE \'%%%1$s%%\')',
                $this->target->escape($q, true),
                $this->table
            );
        } elseif ($this->table === 'notice') {
            $qry = sprintf('content LIKE \'%%%1$s%%\'', $this->target->escape($q, true));
        } else {
            throw new ServerException('Unknown table: ' . $this->table);
        }

        $this->target->whereAdd($qry);

        return true;
    }
}


code:
<?php
/**
 * Base search action class.
 *
 * PHP version 5
 *
 * @category Action
 * @package  StatusNet
 * @author   Evan Prodromou <evan@status.net>
 * @author   Robin Millette <millette@status.net>
 * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
 * @link     http://status.net/
 *
 * 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);
}

require_once INSTALLDIR . '/lib/search/searchgroupnav.php';

/**
 * Base search action class.
 *
 * @category Action
 * @package  StatusNet
 * @author   Evan Prodromou <evan@status.net>
 * @author   Robin Millette <millette@status.net>
 * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
 * @link     http://status.net/
 */
class SearchAction extends Action
{
    /**
     * Return true if read only.
     *
     * @return boolean true
     */
    function isReadOnly($args)
    {
        return true;
    }

    function handle()
    {
        parent::handle();
        $this->showPage();
    }

    function showTop($arr=null)
    {
        $error = null;
        if ($arr) {
            $error = $arr[1];
        }
        if (!empty($error)) {
            $this->element('p', 'error', $error);
        } else {
            $instr = $this->getInstructions();
            $output = common_markup_to_html($instr);
            $this->elementStart('div', 'instructions');
            $this->raw($output);
            $this->elementEnd('div');
        }
    }

    function title()
    {
        return null;
    }

    function showContent() {
        $this->showTop();
        $this->showForm();
    }

    function showForm($error=null)
    {
        $q = $this->trimmed('q');
        $page = $this->trimmed('page', 1);
        $this->elementStart('form', array('method' => 'get',
                                           'id' => 'form_search',
                                           'class' => 'form_settings',
                                           'action' => common_local_url($this->trimmed('action'))));
        $this->elementStart('fieldset');
        // TRANS: Fieldset legend for the search form.
        $this->element('legend', null, _('Search site'));
        $this->elementStart('ul', 'form_data');
        $this->elementStart('li');
        if (!common_config('site', 'fancy')) {
            $this->hidden('action', $this->trimmed('action'));
        }
        // TRANS: Used as a field label for the field where one or more keywords
        // TRANS: for searching can be entered.
        $this->input('q', _('Keyword(s)'), $q);
        // TRANS: Button text for searching site.
        $this->element('input', array('type'=>'submit', 'class'=>'submit', 'value'=>_m('BUTTON','Search')));
        $this->elementEnd('li');
        $this->elementEnd('ul');
        $this->elementEnd('fieldset');
        $this->elementEnd('form');
        if ($q) {
            $this->showResults($q, $page);
        }
    }

    function searchSuggestions($q) {
        // Don't change these long strings to HEREDOC; xgettext won't pick them up.
        // TRANS: Standard search suggestions shown when a search does not give any results.
        $message = _("* Make sure all words are spelled correctly.
* Try different keywords.
* Try more general keywords.
* Try fewer keywords.");
            $message .= "\n";

        if (!common_config('site', 'private')) {
            $qe = urlencode($q);
            $message .= "\n";
            // Don't change these long strings to HEREDOC; xgettext won't pick them up.
            // TRANS: Standard search suggestions shown when a search does not give any results.
            $message .= sprintf(_("You can also try your search on other engines:

* [DuckDuckGo](https://duckduckgo.com/?q=site%%3A%%%%site.server%%%%+%s)
* [Ixquick](https://ixquick.com/do/search?query=site%%3A%%%%site.server%%%%+%s)
* [Searx](https://searx.laquadrature.net/?q=site%%3A%%%%site.server%%%%+%s)
* [Yahoo!](https://search.yahoo.com/search?p=site%%3A%%%%site.server%%%%+%s)
"), $qe, $qe, $qe, $qe);
            $message .= "\n";
        }
        $this->elementStart('div', 'help instructions');
        $this->raw(common_markup_to_html($message));
        $this->elementEnd('div');
    }
}


code:
<?php
/**
 * StatusNet - the distributed open-source microblogging tool
 * Copyright (C) 2011, StatusNet, Inc.
 *
 * Form for searching a StatusNet site
 *
 * 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);
}

/**
 * Form for searching a StatusNet site
 *
 * @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 SearchForm extends Form
{
    /**
     * Visible or invisible data elements
     *
     * Display the form fields that make up the data of the form.
     * Sub-classes should overload this to show their data.
     *
     * @return void
     */
    function formData()
    {
        $this->out->element('input', array('name' => 'q',
                                           'size' => 20,
                                           'id' => 'search-q'));
    }

    /**
     * Buttons for form actions
     *
     * Submit and cancel buttons (or whatever)
     * Sub-classes should overload this to show their own buttons.
     *
     * @return void
     */
    function formActions()
    {
        $this->out->element('input', array('type' => 'submit',
                                           // TRANS: Button text for search button on search form.
                                           'value' => _m('BUTTON','Search')));
    }

    /**
     * ID of the form
     *
     * Should be unique on the page. Sub-classes should overload this
     * to show their own IDs.
     *
     * @return int ID of the form
     */
    function id()
    {
        return 'header-search';
    }

    /**
     * Action of the form.
     *
     * URL to post to. Should be overloaded by subclasses to give
     * somewhere to post to.
     *
     * @return string URL to post to
     */
    function action()
    {
        return common_local_url('noticesearch');
    }

    function method()
    {
        return 'get';
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Menu for search 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-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('STATUSNET') && !defined('LACONICA')) {
    exit(1);
}

/**
 * Menu for public group of actions
 *
 * @category Menu
 * @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/
 *
 * @see      Widget
 */
class SearchGroupNav extends Menu
{
    var $q = null;

    /**
     * Construction
     *
     * @param Action $action current action, used for output
     */
    function __construct(Action $action=null, $q = null)
    {
        parent::__construct($action);
        $this->q = $q;
    }

    /**
     * Show the menu
     *
     * @return void
     */
    function show()
    {
        $action_name = $this->action->trimmed('action');
        $this->action->elementStart('ul', array('class' => 'nav'));
        $args = array();
        if ($this->q) {
            $args['q'] = $this->q;
        }
        // TRANS: Menu item in search group navigation panel.
        $this->out->menuItem(common_local_url('peoplesearch', $args), _m('MENU','People'),
            // TRANS: Menu item title in search group navigation panel.
            _('Find people on this site'), $action_name == 'peoplesearch', 'nav_search_people');
        // TRANS: Menu item in search group navigation panel.
        $this->out->menuItem(common_local_url('noticesearch', $args), _m('MENU','Notices'),
            // TRANS: Menu item title in search group navigation panel.
            _('Find content of notices'), $action_name == 'noticesearch', 'nav_search_notice');
        // TRANS: Menu item in search group navigation panel.
        $this->out->menuItem(common_local_url('groupsearch', $args), _m('MENU','Groups'),
            // TRANS: Menu item title in search group navigation panel.
            _('Find groups on this site'), $action_name == 'groupsearch', 'nav_search_group');
        $this->action->elementEnd('ul');
    }
}


code:
<?php
/**
 * StatusNet - the distributed open-source microblogging tool
 * Copyright (C) 2011, StatusNet, Inc.
 *
 * Stream of notice results
 *
 * 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 notice search results
 *
 * @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 SearchNoticeStream extends ScopingNoticeStream
{
    function __construct($q, Profile $scoped=null)
    {
        parent::__construct(new RawSearchNoticeStream($q), $scoped);
    }
}

class RawSearchNoticeStream extends NoticeStream
{
    protected $q;

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

    function getNoticeIds($offset, $limit, $since_id, $max_id)
    {
        $notice = new Notice();

        $search_engine = $notice->getSearchEngine('notice');
        $search_engine->set_sort_mode('chron');

        $search_engine->limit($offset, $limit);

        $ids = array();

        // wtf?

        $search_engine->query($this->q);

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

        return $ids;
    }
}


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); }

/**
 * @todo Needs documentation.
 */
class Channel
{
    function on($user)
    {
        return false;
    }

    function off($user)
    {
        return false;
    }

    function output($user, $text)
    {
        return false;
    }

    function error($user, $text)
    {
        return false;
    }

    function source()
    {
        return null;
    }
}

class CLIChannel extends Channel
{
    function source()
    {
        return 'cli';
    }

    function output($user, $text)
    {
        $site = common_config('site', 'name');
        print "[{$user->nickname}@{$site}] $text\n";
    }

    function error($user, $text)
    {
        $this->output($user, $text);
    }
}

class WebChannel extends Channel
{
    var $out = null;

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

    function source()
    {
        return 'web';
    }

    function on($user)
    {
        return false;
    }

    function off($user)
    {
        return false;
    }

    function output($user, $text)
    {
        // XXX: buffer all output and send it at the end
        // XXX: even better, redirect to appropriate page
        //      depending on what command was run
        $this->out->startHTML();
        $this->out->elementStart('head');
        // TRANS: Title for command results.
        $this->out->element('title', null, _('Command results'));
        $this->out->elementEnd('head');
        $this->out->elementStart('body');
        $this->out->element('p', array('id' => 'command_result'), $text);
        $this->out->elementEnd('body');
        $this->out->endHTML();
    }

    function error($user, $text)
    {
        common_user_error($text);
    }
}

class AjaxWebChannel extends WebChannel
{
    function output($user, $text)
    {
        $this->out->startHTML('text/xml;charset=utf-8');
        $this->out->elementStart('head');
        // TRANS: Title for command results.
        $this->out->element('title', null, _('Command results'));
        $this->out->elementEnd('head');
        $this->out->elementStart('body');
        $this->out->element('p', array('id' => 'command_result'), $text);
        $this->out->elementEnd('body');
        $this->out->endHTML();
    }

    function error($user, $text)
    {
        $this->out->startHTML('text/xml;charset=utf-8');
        $this->out->elementStart('head');
        // TRANS: Title for command results.
        $this->out->element('title', null, _('AJAX error'));
        $this->out->elementEnd('head');
        $this->out->elementStart('body');
        $this->out->element('p', array('id' => 'error'), $text);
        $this->out->elementEnd('body');
        $this->out->endHTML();
    }
}

class MailChannel extends Channel
{
    var $addr = null;

    function source()
    {
        return 'mail';
    }

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

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

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

    function output($user, $text)
    {
        $headers['From'] = $user->incomingemail;
        $headers['To'] = $this->addr;

        // TRANS: E-mail subject when a command has completed.
        $headers['Subject'] = _('Command complete');

        return mail_send(array($this->addr), $headers, $text);
    }

    function error($user, $text)
    {
        $headers['From'] = $user->incomingemail;
        $headers['To'] = $this->addr;

        // TRANS: E-mail subject when a command has failed.
        $headers['Subject'] = _('Command failed');

        return mail_send(array($this->addr), $headers, $text);
    }

    function setNotify($user, $value)
    {
        $orig = clone($user);
        $user->smsnotify = $value;
        $result = $user->update($orig);
        if (!$result) {
            common_log_db_error($user, 'UPDATE', __FILE__);
            return false;
        }
        return true;
    }
}


code:
<?php
/**
 * Client error action.
 *
 * PHP version 5
 *
 * @category Action
 * @package  StatusNet
 * @author   Evan Prodromou <evan@status.net>
 * @author   Zach Copley <zach@status.net>
 * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
 * @link     http://status.net/
 *
 * StatusNet - the distributed open-source microblogging tool
 * Copyright (C) 2008-2010 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('GNUSOCIAL')) { exit(1); }

/**
 * Class for displaying HTTP client errors
 *
 * @category Action
 * @package  StatusNet
 * @author   Zach Copley <zach@status.net>
 * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
 * @link     http://status.net/
 */
class ClientErrorAction extends ErrorAction
{
    static $status = array(400 => 'Bad Request',
                           401 => 'Unauthorized',
                           402 => 'Payment Required',
                           403 => 'Forbidden',
                           404 => 'Not Found',
                           405 => 'Method Not Allowed',
                           406 => 'Not Acceptable',
                           407 => 'Proxy Authentication Required',
                           408 => 'Request Timeout',
                           409 => 'Conflict',
                           410 => 'Gone',
                           411 => 'Length Required',
                           412 => 'Precondition Failed',
                           413 => 'Request Entity Too Large',
                           414 => 'Request-URI Too Long',
                           415 => 'Unsupported Media Type',
                           416 => 'Requested Range Not Satisfiable',
                           417 => 'Expectation Failed');

    function __construct($message='Error', $code=400)
    {
        parent::__construct($message, $code);
        $this->default = 400;

        if (!$this->code || $this->code < 400 || $this->code > 499) {
            $this->code = $this->default;
        }
        if (!$this->message) {
            $this->message = "Client Error $this->code";
        }
    }

    /**
     *  To specify additional HTTP headers for the action
     *
     *  @return void
     */
    function extraHeaders()
    {
        $status_string = @self::$status[$this->code];
        header('HTTP/1.1 '.$this->code.' '.$status_string);
    }

    /**
     * Page title.
     *
     * @return page title
     */

    function title()
    {
        return @self::$status[$this->code];
    }
}


code:
<?php
/**
 * StatusNet - the distributed open-source microblogging tool
 * Copyright (C) 2011, StatusNet, Inc.
 *
 * Default local nav
 *
 * 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  Menu
 * @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);
}

/**
 * Default menu
 *
 * @category  Menu
 * @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 DefaultLocalNav extends Menu
{
    function show()
    {
        $user = common_current_user();

        $this->action->elementStart('ul', array('id' => 'nav_local_default'));

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

            if (!empty($user)) {
                $pn = new PersonalGroupNav($this->action);
                // TRANS: Menu item in default local navigation panel.
                $this->submenu(_m('MENU','Home'), $pn);
            }

            $bn = new PublicGroupNav($this->action);
            // TRANS: Menu item in default local navigation panel.
            $this->submenu(_m('MENU','Public'), $bn);

            if (!empty($user)) {
                $sn = new GroupsNav($this->action, $user);
                if ($sn->haveGroups()) {
                    // TRANS: Menu item in default local navigation panel.
                    $this->submenu(_m('MENU', 'Groups'), $sn);
                }
            }

            if (!empty($user)) {
                $sn = new ListsNav($this->action, $user->getProfile());
                if ($sn->hasLists()) {
                    // TRANS: Menu item in default local navigation panel.
                    $this->submenu(_m('MENU', 'Lists'), $sn);
                }
            }

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

        $this->action->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/>.

/**
 * Section for featured users
 *
 * @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();

/**
 * Section for featured users
 *
 * @copyright 2009 StatusNet, Inc.
 * @license   https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
 */
class FeaturedUsersSection extends ProfileSection
{
    public function show()
    {
        $featured_nicks = common_config('nickname', 'featured');
        if (empty($featured_nicks)) {
            return;
        }
        parent::show();
    }

    public function getProfiles()
    {
        $featured_nicks = common_config('nickname', 'featured');

        if (!$featured_nicks) {
            return null;
        }

        $quoted = array();

        foreach ($featured_nicks as $nick) {
            $quoted[] = "'$nick'";
        }

        $table = common_database_tablename('user');
        $limit = PROFILES_PER_SECTION + 1;

        $qry = 'SELECT profile.* ' .
            'FROM profile INNER JOIN ' . $table . ' ON profile.id = ' . $table . '.id ' .
            'WHERE ' . $table . '.nickname IN (' . implode(',', $quoted) . ') ' .
            'ORDER BY profile.created DESC LIMIT ' . $limit;

        $profile = Memcached_DataObject::cachedQuery('Profile', $qry, 6 * 3600);
        return $profile;
    }

    public function title()
    {
        // TRANS: Title for featured users section.
        return _('Featured users');
    }

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

    public function moreUrl()
    {
        return common_local_url('featured');
    }
}


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/>.

/**
 * @copyright 2008, 2009 StatusNet, Inc.
 * @license   https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
 */

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

// 10x8

define('AVATARS_PER_PAGE', 80);

// @todo FIXME: Class documentation missing.
class GalleryAction extends ProfileAction
{
    protected function handle()
    {
        // Post from the tag dropdown; redirect to a GET
        if ($this->isPost()) {
            common_redirect($this->selfUrl(), 303);
        }

        parent::handle();
    }

    public function showContent()
    {
        $this->showTagsDropdown();
    }

    public function showTagsDropdown()
    {
        $tag = $this->trimmed('tag');

        $tags = $this->getAllTags();

        $content = array();

        foreach ($tags as $t) {
            $content[$t] = $t;
        }
        if ($tags) {
            $this->elementStart('dl', array('id' => 'filter_tags'));
            $this->element('dt', null, _('Tags'));
            $this->elementStart('dd');
            $this->elementStart('ul');
            $this->elementStart('li', array('id' => 'filter_tags_all',
                                             'class' => 'child_1'));
            $this->element(
                'a',
                [
                    'href' => common_local_url(
                        $this->trimmed('action'),
                        ['nickname' => $this->target->getNickname()]
                    ),
                ],
                // TRANS: List element on gallery action page to show all tags.
                _m('TAGS', 'All')
            );
            $this->elementEnd('li');
            $this->elementStart('li', array('id'=>'filter_tags_item'));
            $this->elementStart('form', array('name' => 'bytag',
                                               'id' => 'form_filter_bytag',
                                              'action' => common_path('?action=' . $this->getActionName()),
                                               'method' => 'post'));
            $this->elementStart('fieldset');
            // TRANS: Fieldset legend on gallery action page.
            $this->element('legend', null, _('Select tag to filter'));
            // TRANS: Dropdown field label on gallery action page for a list containing tags.
            $this->dropdown(
                'tag',
                _('Tag'),
                $content,
                // TRANS: Dropdown field title on gallery action page for a list containing tags.
                _('Choose a tag to narrow list.'),
                false,
                $tag
            );
            $this->hidden('nickname', $this->target->getNickname());
            // TRANS: Submit button text on gallery action page.
            $this->submit('submit', _m('BUTTON', 'Go'));
            $this->elementEnd('fieldset');
            $this->elementEnd('form');
            $this->elementEnd('li');
            $this->elementEnd('ul');
            $this->elementEnd('dd');
            $this->elementEnd('dl');
        }
    }

    // Get list of tags we tagged other users with
    public function getTags($lst, $usr)
    {
        $profile_tag = new Notice_tag();
        $profile_tag->query('SELECT DISTINCT(tag) ' .
                            'FROM profile_tag, subscription ' .
                            'WHERE tagger = ' . $this->target->id . ' ' .
                            'AND ' . $usr . ' = ' . $this->target->id . ' ' .
                            'AND ' . $lst . ' = tagged ' .
                            'AND tagger <> tagged');
        $tags = array();
        while ($profile_tag->fetch()) {
            $tags[] = $profile_tag->tag;
        }
        $profile_tag->free();
        return $tags;
    }

    public function getAllTags()
    {
        return array();
    }

    public function showProfileBlock()
    {
        $block = new AccountProfileBlock($this, $this->target);
        $block->show();
    }
}


code:
<?php
/**
 * StatusNet - the distributed open-source microblogging tool
 * Copyright (C) 2011, StatusNet, Inc.
 *
 * Stub sub-menu for sections that need to go home
 *
 * 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  Menu
 * @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);
}

/**
 * stub sub-menu for settings and stuff
 *
 * @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 HomeStubNav extends Menu
{
    function getItems()
    {
        $items = array();
        if (Event::handle('StartHomeStubNavItems', array($this->action, &$items))) {
            $items[] = array('top',
                            array(),
                            // TRANS: Menu item in personal group navigation menu.
                            _m('MENU','Home'),
                            // TRANS: Menu item title in personal group navigation menu.
                            // TRANS: %s is a username.
                            _('Back to top'),
                            'nav_return_top');
            Event::handle('EndHomeStubNavItems', array($this->action, &$items));
        }
        return $items;
    }
}


code:
<?php
/**
 * StatusNet - the distributed open-source microblogging tool
 * Copyright (C) 2011, StatusNet, Inc.
 *
 * Section for an invite button
 *
 * 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  Section
 * @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);
}

/**
 * Invite button
 *
 * @category  Section
 * @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 InviteButtonSection extends Section
{
    protected $buttonText;

    function __construct($out = null, $buttonText = null)
    {
        $this->out = $out;
        if (empty($buttonText)) {
            // TRANS: Default button text for inviting more users to the StatusNet instance.
            $this->buttonText = _m('BUTTON', 'Invite more people');
        } else {
            $this->buttonText = $buttonText;
        }
    }

    function showTitle()
    {
        return false;
    }

    function divId()
    {
        return 'invite_button';
    }

    function showContent()
    {
        $this->out->element(
            'a',
            array(
                'href' => common_local_url('invite'),
                'class' => 'invite_button'
            ),
            $this->buttonText
        );
        return false;
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Form for inviting collegues and friends
 *
 * 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    Zach Copley <zach@status.net>
 * @copyright 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('STATUSNET')) {
    exit(1);
}

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

/**
 * Form for inviting collegues and friends
 *
 * @category Form
 * @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 InviteForm extends Form
{
    /**
     * Constructor
     *
     * @param Action $out output channel
     */
    function __construct($out=null)
    {
        parent::__construct($out);
    }

    /**
     * ID of the form
     *
     * @return string ID of the form
     */
    function id()
    {
       return 'form_invite';
    }

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

    /**
     * Name of the form
     *
     * @return void
     */
    function formLegend()
    {
        // TRANS: Form legend.
        $this->out->element('legend', null, _('Invite collegues'));
    }

    /**
     * Data elements of the form
     *
     * @return void
     */
    function formData()
    {
        $this->out->elementStart('ul', 'form_data');
        $this->out->elementStart('li');
        $this->out->textarea(
            'addresses',
            // TRANS: Field label for a list of e-mail addresses.
            _('Email addresses'),
            $this->out->trimmed('addresses'),
            // TRANS: Field title for a list of e-mail addresses.
            _('Addresses of friends to invite (one per line).')
        );
        $this->out->elementEnd('li');
        $this->out->elementStart('li');
        $this->out->textarea(
            // TRANS: Field label for a personal message to send to invitees.
            'personal', _('Personal message'),
            $this->out->trimmed('personal'),
            // TRANS: Field title for a personal message to send to invitees.
            _('Optionally add a personal message to the invitation.')
        );
        $this->out->elementEnd('li');
        $this->out->elementEnd('ul');
    }

    /**
     * Action elements
     *
     * @return void
     */
    function formActions()
    {
        $this->out->submit(
            'send',
            // TRANS: Send button for inviting friends
            _m('BUTTON','Send'), 'submit form_action-primary',
            'send',
            // TRANS: Submit button title.
            _('Send invitations.')
        );
    }
}


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

/**
 * Superclass for menus
 *
 * @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 Menu extends Widget
{
    var $action     = null;
    var $actionName = null;
    var $actionArgs = null;

    /**
     * Construction
     *
     * @param Action $action current action, used for output
     */
    function __construct(Action $action=null)
    {
        parent::__construct($action);

        $this->action     = $action;
        $this->actionName = $action->trimmed('action');

        $rtargs = $action->returnToArgs();

        $this->actionArgs = $rtargs[1];
    }

    function getItems()
    {
        return array();
    }

    function tag()
    {
        return null;
    }

    function show()
    {
        $items = $this->getItems();
        $tag = $this->tag();

        $attrs = array('class' => 'nav');

        if (!is_null($tag)) {
            $attrs['id']  = 'nav_' . $tag;
        }

        if (Event::handle('StartNav', array($this, &$tag, &$items))) {

            $this->out->elementStart('ul', $attrs);

            foreach ($items as $item) {
                list($actionName, $args, $label, $description, $id) = $item;
                $this->item($actionName, $args, $label, $description, $id);
            }

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

            Event::handle('EndNav', array($this, $tag, $items));
        }
    }

    function item($actionName, array $args, $label, $description, $id=null, $cls=null)
    {
        if (empty($id)) {
            $id = $this->menuItemID($actionName, $args);
        }

        $url = common_local_url($actionName, $args);

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

    function isCurrent($actionName, array $args)
    {
        if ($actionName != $this->actionName) {
            return false;
        }

        foreach ($this->actionArgs as $k => $v) {
            if (!array_key_exists($k, $args) || $args[$k] != $v) {
                return false;
            }
        }

        return true;
    }

    function menuItemID($actionName, $args = null)
    {
        $id = sprintf('nav_%s', $actionName);

        if (!is_null($args)) {
            foreach ($args as $key => $value) {
                $id .= '_' . $key . '_' . $value;
            }
        }

        return $id;
    }

    function submenu($label, $menu)
    {
        if (Event::handle('StartSubMenu', [$this->action, $menu, $label])) {
            $this->action->elementStart('li');
            $this->action->element('h3', null, $label);
            $menu->show();
            $this->action->elementEnd('li');
            Event::handle('EndSubMenu', [$this->action, $menu, $label]);
        }
    }
}


code:
<?php
/**
 * StatusNet - the distributed open-source microblogging tool
 * Copyright (C) 2011, StatusNet, Inc.
 *
 * A menu with a More... button to show more elements
 *
 * 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);
}

/**
 * A menu with a More... element to show more items
 *
 * @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 MoreMenu extends Menu
{
    const SOFT_MAX = 5;
    const HARD_MAX = 15;

    /**
     * Show a menu with a limited number of elements
     *
     * @param
     *
     * @return
     */
    function show()
    {
        $items = $this->getItems();
        $tag = $this->tag();
        $menuID  = null;

        $attrs = array('class' => 'nav');

        if (!is_null($tag)) {
            $menuID = 'nav_' . $tag;
            $attrs['id'] = $menuID;
        }

        if (Event::handle('StartNav', array($this, &$tag, &$items))) {
            $this->out->elementStart('ul', $attrs);

            $total = count($items);

            if ($total <= self::SOFT_MAX + 1) {
                $toShow = $items;
            } else {
                $toShow = array_slice($items, 0, self::SOFT_MAX);
            }

            foreach ($toShow as $item) {
            	if (count($item) == 5) {
                	list($actionName, $args, $label, $description, $id) = $item;
            	} else {
                	list($actionName, $args, $label, $description) = $item;
                	$id = null;
            	}
                $this->item($actionName, $args, $label, $description, $id);
            }

            if ($total > self::SOFT_MAX + 1) {
                $this->out->elementStart('li', array('class' => 'more_link'));
                $this->out->element('a', array('href' => '#',
                                               'onclick' => 'SN.U.showMoreMenuItems("'.$menuID.'"); return false;'),
                                    // TRANS: Link description to show more items in a list.
                                    _('More ▼'));
                $this->out->elementEnd('li');

                $extended = array_slice($items, self::SOFT_MAX, self::HARD_MAX - self::SOFT_MAX);

                foreach ($extended as $item) {
            		if (count($item) == 5) {
                		list($actionName, $args, $label, $description, $id) = $item;
            		} else {
                		list($actionName, $args, $label, $description) = $item;
                		$id = null;
            		}
                    $this->item($actionName, $args, $label, $description, $id, 'extended_menu');
                }

                if ($total > self::HARD_MAX) {
                    $seeAll = $this->seeAllItem();

                    if (!empty($seeAll)) {
            			if (count($seeAll) == 5) {
                			list($actionName, $args, $label, $description, $id) = $seeAll;
            			} else {
                			list($actionName, $args, $label, $description) = $seeAll;
                			$id = null;
            			}
                        $this->item($actionName, $args, $label, $description, $id, 'extended_menu see_all');
                    }
                }
            }

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

            Event::handle('EndNav', array($this, $tag, $items));
        }
    }

    function seeAllItem()
    {
        return null;
    }
}