code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Form for nudging 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/form.php';

/**
 * Form for nudging 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      DisfavorForm
 */
class NudgeForm extends Form
{
    /**
     * Profile of user to nudge
     */
    var $profile = null;

    /**
     * Constructor
     *
     * @param HTMLOutputter $out     output channel
     * @param Profile       $profile profile of user to nudge
     */
    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 'form_user_nudge';
    }

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

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

    /**
     * Legend of the Form
     *
     * @return void
     */
    function formLegend()
    {
        // TRANS: Form legend of form to nudge/ping another user.
        $this->out->element('legend', null, _('Nudge this user'));
    }

    /**
     * Action elements
     *
     * @return void
     */
    function formActions()
    {
        $this->out->submit('submit',
                           // TRANS: Button text to nudge/ping another user.
                           _m('BUTTON','Nudge'),
                           'submit',
                           null,
                           // TRANS: Button title to nudge/ping another user.
                           _('Send a nudge to this user.'));
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Base class for doing OAuth calls as a consumer
 *
 * PHP version 5
 *
 * LICENCE: This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @category  Action
 * @package   StatusNet
 * @author    Zach Copley <zach@status.net>
 * @copyright 2009 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 'OAuth.php';

/**
 * Exception wrapper for cURL errors
 *
 * @category Integration
 * @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 OAuthClientException extends Exception
{
}

/**
 * Base class for doing OAuth calls as a consumer
 *
 * @category Integration
 * @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 OAuthClient
{
    var $consumer;
    var $token;

    /**
     * Constructor
     *
     * Can be initialized with just consumer key and secret for requesting new
     * tokens or with additional request token or access token
     *
     * @param string $consumer_key       consumer key
     * @param string $consumer_secret    consumer secret
     * @param string $oauth_token        user's token
     * @param string $oauth_token_secret user's secret
     *
     * @return nothing
     */
    function __construct($consumer_key, $consumer_secret,
                         $oauth_token = null, $oauth_token_secret = null)
    {
        $this->sha1_method = new OAuthSignatureMethod_HMAC_SHA1();
        $this->consumer    = new OAuthConsumer($consumer_key, $consumer_secret);
        $this->token       = null;

        if (isset($oauth_token) && isset($oauth_token_secret)) {
            $this->token = new OAuthToken($oauth_token, $oauth_token_secret);
        }
    }

    /**
     * Gets a request token from the given url
     *
     * @param string $url      OAuth endpoint for grabbing request tokens
     * @param string $callback authorized request token callback
     *
     * @return OAuthToken $token the request token
     */
    function getRequestToken($url, $callback = null)
    {
        $params = null;

        if (!is_null($callback)) {
            $params['oauth_callback'] = $callback;
        }

        $response = $this->oAuthGet($url, $params);

        $arr = array();
        parse_str($response, $arr);

        $token   = $arr['oauth_token'];
        $secret  = $arr['oauth_token_secret'];
        $confirm = $arr['oauth_callback_confirmed'];

        if (isset($token) && isset($secret)) {

            $token = new OAuthToken($token, $secret);

            if (isset($confirm)) {
                if ($confirm == 'true') {
                    return $token;
                } else {
                    throw new OAuthClientException(
                        'Callback was not confirmed by remote OAuth side.'
                    );
                }
            }
            return $token;
        } else {
            throw new OAuthClientException(
                'Could not get a request token from remote OAuth side.'
            );
        }
    }

    /**
     * Builds a link that can be redirected to in order to
     * authorize a request token.
     *
     * @param string     $url            endpoint for authorizing request tokens
     * @param OAuthToken $request_token  the request token to be authorized
     *
     * @return string $authorize_url the url to redirect to
     */
    function getAuthorizeLink($url, $request_token)
    {
        $authorize_url = $url . '?oauth_token=' .
            $request_token->key;

        return $authorize_url;
    }

    /**
     * Fetches an access token
     *
     * @param string $url      OAuth endpoint for exchanging authorized request tokens
     *                         for access tokens
     * @param string $verifier 1.0a verifier
     *
     * @return OAuthToken $token the access token
     */
    function getAccessToken($url, $verifier = null)
    {
        $params = array();

        if (!is_null($verifier)) {
            $params['oauth_verifier'] = $verifier;
        }

        $response = $this->oAuthPost($url, $params);

        $arr = array();
        parse_str($response, $arr);

        $token  = $arr['oauth_token'];
        $secret = $arr['oauth_token_secret'];

        if (isset($token) && isset($secret)) {
            $token = new OAuthToken($token, $secret);
            return $token;
        } else {
            throw new OAuthClientException(
                'Could not get a access token from remote OAuth side.'
            );
        }
    }

    /**
     * Use HTTP GET to make a signed OAuth requesta
     *
     * @param string $url    OAuth request token endpoint
     * @param array  $params additional parameters
     *
     * @return mixed the request
     */
    function oAuthGet($url, $params = null)
    {
        $request = OAuthRequest::from_consumer_and_token($this->consumer,
            $this->token, 'GET', $url, $params);
        $request->sign_request($this->sha1_method,
            $this->consumer, $this->token);

        return $this->httpRequest($request->to_url());
    }

    /**
     * Use HTTP POST to make a signed OAuth request
     *
     * @param string $url    OAuth endpoint
     * @param array  $params additional post parameters
     *
     * @return mixed the request
     */
    function oAuthPost($url, $params = null)
    {
        $request = OAuthRequest::from_consumer_and_token($this->consumer,
            $this->token, 'POST', $url, $params);
        $request->sign_request($this->sha1_method,
            $this->consumer, $this->token);

        return $this->httpRequest($request->get_normalized_http_url(),
            $request->to_postdata());
    }

    /**
     * Make a HTTP request.
     *
     * @param string $url    Where to make the
     * @param array  $params post parameters
     *
     * @return mixed the request
     */
    function httpRequest($url, $params = null)
    {
        $request = new HTTPClient($url);
        $request->setConfig(array(
            'connect_timeout' => 120,
            'timeout' => 120,
            'follow_redirects' => true,
            'ssl_verify_peer' => false,
            'ssl_verify_host' => false
        ));

        // Twitter was strict about accepting invalid "Expect" headers
        // between 2008ish and October 2012. Caused "417 Expectation failed"
        //$request->setHeader('Expect', '');

        if (isset($params)) {
            $request->setMethod(HTTP_Request2::METHOD_POST);
            $request->setBody($params);
        }

        try {
            $response = $request->send();
            $code = $response->getStatus();
            if ($code < 200 || $code >= 400) {
                throw new OAuthClientException($response->getBody(), $code);
            }
            return $response->getBody();
        } catch (Exception $e) {
            throw new OAuthClientException($e->getMessage(), $e->getCode());
        }
    }

}

license: mit


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Base class for making daemons that can do several tasks in parallel.
 *
 * 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  Daemon
 * @package   StatusNet
 * @author    Zach Copley <zach@status.net>
 * @author    Evan Prodromou <evan@status.net>
 * @copyright 2009 StatusNet, Inc.
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 * @link      http://status.net/
 */

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

declare(ticks = 1);

/**
 * Daemon able to spawn multiple child processes to do work in parallel
 *
 * @category Daemon
 * @package  StatusNet
 * @author   Zach Copley <zach@status.net>
 * @author   Evan Prodromou <evan@status.net>
 * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 * @link     http://status.net/
 */

class ParallelizingDaemon extends Daemon
{
    private $_children     = array();
    private $_interval     = 0; // seconds
    private $_max_children = 0; // maximum number of children
    private $_debug        = false;

    /**
     *  Constructor
     *
     * @param string  $id           the name/id of this daemon
     * @param int     $interval     sleep this long before doing everything again
     * @param int     $max_children maximum number of child processes at a time
     * @param boolean $debug        debug output flag
     *
     * @return void
     *
     **/

    function __construct($id = null, $interval = 60, $max_children = 2,
                         $debug = null)
    {
        parent::__construct(true); // daemonize

        $this->_interval     = $interval;
        $this->_max_children = $max_children;
        $this->_debug        = $debug;

        if (isset($id)) {
            $this->set_id($id);
        }
    }

    /**
     * Run the daemon
     *
     * @return void
     */

    function run()
    {
        if (isset($this->_debug)) {
            echo $this->name() . " - Debugging output enabled.\n";
        }

        do {

            $objects = $this->getObjects();

            foreach ($objects as $o) {

                // Fork a child for each object

                $pid = pcntl_fork();

                if ($pid == -1) {
                    die ($this->name() . ' - Couldn\'t fork!');
                }

                if ($pid) {

                    // Parent

                    if (isset($this->_debug)) {
                        echo $this->name() .
                          " - Forked new child - pid $pid.\n";

                    }

                    $this->_children[] = $pid;

                } else {

                    // Child

                    // Do something with each object

                    $this->childTask($o);

                    exit();
                }

                // Remove child from ps list as it finishes

                while (($c = pcntl_wait($status, WNOHANG OR WUNTRACED)) > 0) {

                    if (isset($this->_debug)) {
                        echo $this->name() . " - Child $c finished.\n";
                    }

                    $this->removePs($this->_children, $c);
                }

                // Wait! We have too many damn kids.

                if (sizeof($this->_children) >= $this->_max_children) {

                    if (isset($this->_debug)) {
                        echo $this->name() . " - Too many children. Waiting...\n";
                    }

                    if (($c = pcntl_wait($status, WUNTRACED)) > 0) {

                        if (isset($this->_debug)) {
                            echo $this->name() .
                              " - Finished waiting for child $c.\n";
                        }

                        $this->removePs($this->_children, $c);
                    }
                }
            }

            // Remove all children from the process list before restarting
            while (($c = pcntl_wait($status, WUNTRACED)) > 0) {

                if (isset($this->_debug)) {
                    echo $this->name() . " - Child $c finished.\n";
                }

                $this->removePs($this->_children, $c);
            }

            // Rest for a bit

            if (isset($this->_debug)) {
                echo $this->name() . ' - Waiting ' . $this->_interval .
                  " secs before running again.\n";
            }

            if ($this->_interval > 0) {
                sleep($this->_interval);
            }

        } while (true);
    }

    /**
     * Remove a child process from the list of children
     *
     * @param array &$plist array of processes
     * @param int   $ps     process id
     *
     * @return void
     */

    function removePs(&$plist, $ps)
    {
        for ($i = 0; $i < sizeof($plist); $i++) {
            if ($plist[$i] == $ps) {
                unset($plist[$i]);
                $plist = array_values($plist);
                break;
            }
        }
    }

    /**
     * Get a list of objects to work on in parallel
     *
     * @return array An array of objects to work on
     */

    function getObjects()
    {
        die('Implement ParallelizingDaemon::getObjects().');
    }

    /**
     * Do something with each object in parallel
     *
     * @param mixed $object data to work on
     *
     * @return void
     */

    function childTask($object)
    {
        die("Implement ParallelizingDaemon::childTask($object).");
    }

}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Class for an exception when password hashing was unsuccessful
 *
 * 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  Exception
 * @package   GNUsocial
 * @author    Mikael Nordfeldth <mmn@hethane.se>
 * @copyright 2013 Free Software Foundation, Inc.
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3
 * @link      http://www.gnu.org/software/social/
 */

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

class PasswordHashException extends ServerException
{
    public $obj;    // The object with query that gave no results

    public function __construct($msg=null, $code=500)
    {
        if ($msg === null) {
            $msg = _('Password hashing failed.');
        }

        parent::__construct($msg, $code);
    }
}


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/form.php';
require_once INSTALLDIR.'/lib/togglepeopletag.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 PeopletagEditForm extends Form
{
    /**
     * peopletag to edit
     */

    var $peopletag = null;
    var $tagger    = null;

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

        $this->peopletag = $peopletag;
        $this->tagger    = Profile::getKV('id', $peopletag->tagger);
    }

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

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

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

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

    /**
     * Data elements of the form
     *
     * @return void
     */
    function formData()
    {
        $id = $this->peopletag->id;
        $tag = $this->peopletag->tag;
        $description = $this->peopletag->description;
        $private = $this->peopletag->private;

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

        $this->out->elementStart('li');
        $this->out->hidden('id', $id);

        // TRANS: Field label for list.
        $this->out->input('tag', _m('LABEL','List'),
                          ($this->out->arg('tag')) ? $this->out->arg('tag') : $tag,
                          // TRANS: Field title for list.
                          _('Change the list (letters, numbers, -, ., and _ are allowed).'));
        $this->out->elementEnd('li');

        $this->out->elementStart('li');
        $desclimit = Profile_list::maxDescription();
        if ($desclimit == 0) {
            // TRANS: Field title for description of list.
            $descinstr = _('Describe the list or topic.');
        } else {
            // TRANS: Field title for description of list.
            // TRANS: %d is the maximum number of characters for the description.
            $descinstr = sprintf(_m('Describe the list or topic in %d character.',
                                    'Describe the list or topic in %d characters.',
                                    $desclimit),
                                 $desclimit);
        }
        // TRANS: Field label for description of list.
        $this->out->textarea('description', _('Description'),
                             ($this->out->arg('description')) ? $this->out->arg('description') : $description,
                             $descinstr);
        // TRANS: Checkbox label to mark a list private.
        $this->out->checkbox('private', _('Private'), $private);
        $this->out->elementEnd('li');
        $this->out->elementEnd('ul');
    }

    /**
     * Action elements
     *
     * @return void
     */
    function formActions()
    {
        // TRANS: Button text to save a list.
        $this->out->submit('submit', _('Save'));
        $this->out->submit('form_action-yes',
                      // TRANS: Button text to delete a list.
                      _m('BUTTON','Delete'),
                      'submit',
                      'delete',
                      // TRANS: Button title to delete a list.
                      _('Delete this list.'));
    }

    function showProfileList()
    {
        $tagged = $this->peopletag->getTagged();
        // TRANS: Header in list edit form.
        $this->out->element('h2', null, _('Add or remove people'));

        $this->out->elementStart('div', 'profile_search_wrap');
        // TRANS: Header in list edit form.
        $this->out->element('h3', null, _m('HEADER','Search'));
        $search = new SearchProfileForm($this->out, $this->peopletag);
        $search->show();
        $this->out->element('ul', array('id' => 'profile_search_results', 'class' => 'empty'));
        $this->out->elementEnd('div');

        $this->out->elementStart('ul', 'profile-lister');
        while ($tagged->fetch()) {
            $this->out->elementStart('li', 'entity_removable_profile');
            $this->showProfileItem($tagged);
            $this->out->elementStart('span', 'entity_actions');
            $untag = new UntagButton($this->out, $tagged, $this->peopletag);
            $untag->show();
            $this->out->elementEnd('span');
            $this->out->elementEnd('li');
        }
        $this->out->elementEnd('ul');
    }

    function showProfileItem($profile)
    {
        $item = new TaggedProfileItem($this->out, $profile);
        $item->show();
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Base class for all actions (~views)
 *
 * PHP version 5
 *
 * LICENCE: This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @category  Action
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @author    Sarven Capadisli <csarven@status.net>
 * @copyright 2008 StatusNet, Inc.
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 * @link      http://status.net/
 */

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

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

/**
 * Base class for all actions
 *
 * This is the base class for all actions in the package. An action is
 * more or less a "view" in an MVC framework.
 *
 * Actions are responsible for extracting and validating parameters; using
 * model classes to read and write to the database; and doing ouput.
 *
 * @category Output
 * @package  StatusNet
 * @author   Evan Prodromou <evan@status.net>
 * @author   Sarven Capadisli <csarven@status.net>
 * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 * @link     http://status.net/
 *
 * @see      HTMLOutputter
 */
class PeopletagGroupNav extends Widget
{
    var $action = null;

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

    /**
     * Show the menu
     *
     * @return void
     */
    function show()
    {
        $user = null;

	// FIXME: we should probably pass this in

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

        if (common_config('singleuser', 'enabled')) {
            $nickname = User::singleUserNickname();
        } else {
            $nickname = $this->action->arg('tagger');
        }

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

        if ($nickname) {
            $user = User::getKV('nickname', $nickname);
            $user_profile = $user->getProfile();

            if ($tag) {
                $tag = Profile_list::pkeyGet(array('tagger' => $user->id,
                                                   'tag'    => $tag));
            } else {
                $tag = false;
            }

        } else {
            $user_profile = false;
        }

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

        if (Event::handle('StartPeopletagGroupNav', array($this))) {
            // People tag timeline
            $this->out->menuItem(common_local_url('showprofiletag', array('tagger' => $user_profile->nickname,
                                                                          'tag'    => $tag->tag)),
                             // TRANS: Menu item in list navigation panel.
                             _m('MENU','List'),
                             // TRANS: Menu item title in list navigation panel.
                             // TRANS: %1$s is a list, %2$s is a nickname.
                             sprintf(_('%1$s list by %2$s.'), $tag->tag,
                                (($user_profile && $user_profile->fullname) ? $user_profile->fullname : $nickname)),
                             $action == 'showprofiletag', 'nav_timeline_peopletag');

            // Tagged
            $this->out->menuItem(common_local_url('peopletagged', array('tagger' => $user->nickname,
                                                                        'tag'    => $tag->tag)),
                             // TRANS: Menu item in list navigation panel.
                             _m('MENU','Listed'),
                             // TRANS: Menu item title in list navigation panel.
                             // TRANS: %1$s is a list, %2$s is a nickname.
                             sprintf(_('%1$s list by %2$s.'), $tag->tag,
                                (($user_profile && $user_profile->fullname) ? $user_profile->fullname : $nickname)),
                             $action == 'peopletagged', 'nav_peopletag_tagged');

            // Subscribers
            $this->out->menuItem(common_local_url('peopletagsubscribers', array('tagger' => $user->nickname,
                                                                                'tag'    => $tag->tag)),
                             // TRANS: Menu item in list navigation panel.
                             _m('MENU','Subscribers'),
                             // TRANS: Menu item title in list navigation panel.
                             // TRANS: %1$s is a list, %2$s is a nickname.
                             sprintf(_('Subscribers to %1$s list by %2$s.'), $tag->tag,
                                (($user_profile && $user_profile->fullname) ? $user_profile->fullname : $nickname)),
                             $action == 'peopletagsubscribers', 'nav_peopletag_subscribers');

            $cur = common_current_user();
            if (!empty($cur) && $user_profile->id == $cur->id) {
                // Edit
                $this->out->menuItem(common_local_url('editpeopletag', array('tagger' => $user->nickname,
                                                                             'tag'    => $tag->tag)),
                                 // TRANS: Menu item in list navigation panel.
                                 _m('MENU','Edit'),
                                 // TRANS: Menu item title in list navigation panel.
                                 // TRANS: %s is a list.
                                 sprintf(_('Edit %s list by you.'), $tag->tag,
                                    (($user_profile && $user_profile->fullname) ? $user_profile->fullname : $nickname)),
                                 $action == 'editpeopletag', 'nav_peopletag_edit');
            }

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


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Widget to show a list of peopletags
 *
 * PHP version 5
 *
 * LICENCE: This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @category  Public
 * @package   StatusNet
 * @author    Shashi Gowda <connect2shashi@gmail.com>
 * @copyright 2008-2009 StatusNet, Inc.
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 * @link      http://status.net/
 */

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

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

define('PEOPLETAGS_PER_PAGE', 20);

/**
 * Widget to show a list of peopletags
 *
 * @category Public
 * @package  StatusNet
 * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 * @link     http://status.net/
 */
class PeopletagList extends Widget
{
    /** Current peopletag, peopletag query. */
    var $peopletag = null;
    /** current user **/
    var $user = null;

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

        $this->peopletag = $peopletag;

        if (!empty($owner)) {
            $this->user = $owner;
        } else {
            $this->user = common_current_user();
        }
    }

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

        $cnt = 0;

        while ($this->peopletag->fetch()) {
            $cnt++;
            if($cnt > PEOPLETAGS_PER_PAGE) {
                break;
            }
            $this->showPeopletag();
        }

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

        return $cnt;
    }

    function showPeopletag()
    {
        $ptag = new PeopletagListItem($this->peopletag, $this->user, $this->out);
        $ptag->show();
    }
}

class PeopletagListItem extends Widget
{
    var $peopletag = null;
    var $current = null;
    var $profile = null;

    /**
     * constructor
     *
     * Also initializes the owner attribute.
     *
     * @param Notice $notice The notice we'll display
     */
    function __construct($peopletag, $current, $out=null)
    {
        parent::__construct($out);
        $this->peopletag  = $peopletag;
        $this->current = $current;
        $this->profile = Profile::getKV('id', $this->peopletag->tagger);
    }

    /**
     * recipe function for displaying a single peopletag.
     *
     * This uses all the other methods to correctly display a notice. Override
     * it or one of the others to fine-tune the output.
     *
     * @return void
     */
    function url()
    {
        return $this->peopletag->homeUrl();
    }

    function show()
    {
        if (empty($this->peopletag)) {
            common_log(LOG_WARNING, "Trying to show missing peopletag; skipping.");
            return;
        }

        if (Event::handle('StartShowPeopletagItem', array($this))) {
            $this->showStart();
            $this->showPeopletag();
            $this->showStats();
            $this->showEnd();
            Event::handle('EndShowPeopletagItem', array($this));
        }
    }

    function showStart()
    {
        $mode = ($this->peopletag->private) ? 'private' : 'public';
        $this->out->elementStart('li', array('class' => 'h-entry peopletag mode-' . $mode,
                                             'id' => 'peopletag-' . $this->peopletag->id));
    }

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

    function showPeopletag()
    {
        $this->showCreator();
        $this->showTag();
        $this->showPrivacy();
        $this->showUpdated();
        $this->showActions();
        $this->showDescription();
    }

    function showStats()
    {
        $this->out->elementStart('div', 'entry-summary entity_statistics');
        $this->out->elementStart('span', 'tagged-count');
        $this->out->element('a',
            array('href' => common_local_url('peopletagged',
                                              array('tagger' => $this->profile->nickname,
                                                    'tag' => $this->peopletag->tag))),
            // TRANS: Link description for link to list of users tagged with a tag (so part of a list).
            _('Listed'));
        $this->out->raw($this->peopletag->taggedCount());
        $this->out->elementEnd('span');

        $this->out->elementStart('span', 'subscriber-count');
        $this->out->element('a',
            array('href' => common_local_url('peopletagsubscribers',
                                              array('tagger' => $this->profile->nickname,
                                                    'tag' => $this->peopletag->tag))),
            // TRANS: Link description for link to list of users subscribed to a tag.
            _('Subscribers'));
        $this->out->raw($this->peopletag->subscriberCount());
        $this->out->elementEnd('span');
        $this->out->elementEnd('div');
    }

    function showOwnerOptions()
    {
        $this->out->elementStart('li', 'entity_edit');
        $this->out->element('a', array('href' =>
                    common_local_url('editpeopletag', array('tagger' => $this->profile->nickname,
                                                    'tag' => $this->peopletag->tag)),
                                  // TRANS: Title for link to edit list settings.
                                  'title' => _('Edit list settings.')),
                       // TRANS: Text for link to edit list settings.
                       _('Edit'));
        $this->out->elementEnd('li');
    }

    function showSubscribeForm()
    {
        $this->out->elementStart('li');

        if (Event::handle('StartSubscribePeopletagForm', array($this->out, $this->peopletag))) {
            if ($this->current) {
                if ($this->peopletag->hasSubscriber($this->current->id)) {
                    $form = new UnsubscribePeopletagForm($this->out, $this->peopletag);
                    $form->show();
                } else {
                    $form = new SubscribePeopletagForm($this->out, $this->peopletag);
                    $form->show();
                }
            }
            Event::handle('EndSubscribePeopletagForm', array($this->out, $this->peopletag));
        }

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

    function showCreator()
    {
        $attrs = array();
        $attrs['href'] = $this->profile->profileurl;
        $attrs['class'] = 'h-card p-author nickname p-name';
        $attrs['rel'] = 'contact';
        $attrs['title'] = $this->profile->getFancyName();

        $this->out->elementStart('a', $attrs);
        $this->showAvatar($this->profile);
        $this->out->text($this->profile->getNickname());
        $this->out->elementEnd('a');
    }

    function showUpdated()
    {
        if (!empty($this->peopletag->modified)) {
            $this->out->element('abbr',
                array('title' => common_date_w3dtf($this->peopletag->modified),
                      'class' => 'updated'),
                common_date_string($this->peopletag->modified));
        }
    }

    function showPrivacy()
    {
        if ($this->peopletag->private) {
            $this->out->elementStart('a',
                array('href' => common_local_url('peopletagsbyuser',
                    array('nickname' => $this->profile->nickname, 'private' => 1))));
            // TRANS: Privacy mode text in list list item for private list.
            $this->out->element('span', 'privacy_mode', _m('MODE','Private'));
            $this->out->elementEnd('a');
        }
    }

    function showTag()
    {
        $this->out->elementStart('span', 'entry-title tag');
        $this->out->element('a',
            array('rel'   => 'bookmark',
                  'href'  => $this->url()),
            htmlspecialchars($this->peopletag->tag));
        $this->out->elementEnd('span');
    }

    function showActions()
    {
        $this->out->elementStart('div', 'entity_actions');
        $this->out->elementStart('ul');

        if (!$this->peopletag->private) {
            $this->showSubscribeForm();
        }

        if (!empty($this->current) && $this->profile->id == $this->current->id) {
            $this->showOwnerOptions();
        }
        $this->out->elementEnd('ul');
        $this->out->elementEnd('div');
    }

    function showDescription()
    {
        $this->out->element('div', 'e-content description', $this->peopletag->description);
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Tabset for a particular list
 *
 * PHP version 5
 *
 * LICENCE: This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @category  Action
 * @package   StatusNet
 * @author    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/widget.php';

/**
 * Tabset for a group
 *
 * Shows a group of tabs for a particular user group
 *
 * @category Output
 * @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      HTMLOutputter
 */
class PeopletagNav extends Menu
{
    var $group = null;

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

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

        $this->out->elementStart('ul', array('class' => 'nav'));
        if (Event::handle('StartPeopletagGroupNav', array($this))) {
            $this->out->menuItem(common_local_url('peopletagsubscriptions', array('nickname' =>
                                                                     $nickname)),
                                 // TRANS: Menu item in the group navigation page.
                                 _m('MENU','List Subscriptions'),
                                 // TRANS: Tooltip for menu item in the group navigation page.
                                 // TRANS: %s is a user nickname.
                                 sprintf(_m('TOOLTIP','Lists subscribed to by %s.'), $nickname),
                                 $action_name == 'peopletagsubscriptions',
                                 'nav_list_group');
            $this->out->menuItem(common_local_url('peopletagsforuser', array('nickname' =>
                                                                        $nickname)),
                                 // TRANS: Menu item in the group navigation page.
                                 // TRANS: %s is a user nickname.
                                 sprintf(_m('MENU','Lists with %s'), $nickname),
                                 // TRANS: Tooltip for menu item in the group navigation page.
                                 // TRANS: %s is a user nickname.
                                 sprintf(_m('TOOLTIP','Lists with %s.'), $nickname),
                                 $action_name == 'peopletagsforuser',
                                 'nav_lists_with');
            $this->out->menuItem(common_local_url('peopletagsbyuser', array('nickname' =>
                                                                        $nickname)),
                                 // TRANS: Menu item in the group navigation page.
                                 // TRANS: %s is a user nickname.
                                 sprintf(_m('MENU','Lists by %s'), $nickname),
                                 // TRANS: Tooltip for menu item in the group navigation page.
                                 // TRANS: %s is a user nickname.
                                 sprintf(_m('TOOLTIP','Lists by %s.'), $nickname),
                                 $action_name == 'peopletagsbyuser',
                                 'nav_lists_by');
            Event::handle('EndGroupGroupNav', array($this));
        }
        $this->out->elementEnd('ul');
    }
}


code:
<?php
/**
 * StatusNet - the distributed open-source microblogging tool
 * Copyright (C) 2011, StatusNet, Inc.
 *
 * Stream of notices for a list
 *
 * 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('STATUSNET')) {
    // This check helps protect against security problems;
    // your code file can't be executed directly from the web.
    exit(1);
}

/**
 * Stream of notices for a list
 *
 * @category  Stream
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @author    Shashi Gowda <connect2shashi@gmail.com>
 * @copyright 2011 StatusNet, Inc.
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
 * @link      http://status.net/
 */
class PeopletagNoticeStream extends ScopingNoticeStream
{
    function __construct($plist, $profile = -1)
    {
        if (is_int($profile) && $profile == -1) {
            $profile = Profile::current();
        }
        parent::__construct(new CachingNoticeStream(new RawPeopletagNoticeStream($plist),
                                                    'profile_list:notice_ids:' . $plist->id),
                            $profile);
    }
}

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

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

    /**
     * Query notices by users associated with this tag from the database.
     *
     * @param integer $offset   offset
     * @param integer $limit    maximum no of results
     * @param integer $since_id=null    since this id
     * @param integer $max_id=null  maximum id in result
     *
     * @return array array of notice ids.
     */

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

        $notice->selectAdd();
        $notice->selectAdd('notice.id');

        $ptag = new Profile_tag();
        $ptag->tag    = $this->profile_list->tag;
        $ptag->tagger = $this->profile_list->tagger;
        $notice->joinAdd(array('profile_id', 'profile_tag:tagged'));
        $notice->whereAdd('profile_tag.tagger = ' . $this->profile_list->tagger);
        $notice->whereAdd(sprintf('profile_tag.tag = "%s"', $this->profile_list->tag));

        if ($since_id != 0) {
            $notice->whereAdd('notice.id > ' . $since_id);
        }

        if ($max_id != 0) {
            $notice->whereAdd('notice.id <= ' . $max_id);
        }

        $notice->orderBy('notice.id DESC');

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

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

        return $ids;
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Tags for a profile
 *
 * PHP version 5
 *
 * LICENCE: This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @category  Action
 * @package   StatusNet
 * @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/widget.php';

/*
 * Show a bunch of peopletags
 * provide ajax editing if the current user owns the tags
 *
 * @category Action
 * @pacage   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
 */
class PeopletagsWidget extends Widget
{
    /*
     * the query, current peopletag.
     * or an array of strings (tags)
     */

    var $tag=null;

    var $user=null;
    var $tagger=null;
    var $tagged=null;

    function __construct($out, $tagger, $tagged)
    {
        parent::__construct($out);

        $this->user   = common_current_user();
        $this->tag = Profile_tag::getTags($tagger->id, $tagged->id, $this->user);
        $this->tagger = $tagger;
        $this->tagged = $tagged;
    }

    function show()
    {
        if (Event::handle('StartShowPeopletags', array($this, $this->tagger, $this->tagged))) {
            if ($this->tag->N > 0) {
                $this->showTags();
            }
            else {
                $this->showEmptyList();
            }
            Event::handle('EndShowPeopletags', array($this, $this->tagger, $this->tagged));
        }
    }

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

    function label()
    {
        // TRANS: Label in lists widget.
        return _m('LABEL','Your lists');
    }

    function showTags()
    {
        $this->out->elementStart('dl', 'entity_tags user_profile_tags');
        $this->out->element('dt', null, $this->label());
        $this->out->elementStart('dd');

        $class = 'tags xoxo';
        if ($this->isEditable()) {
            $class .= ' editable';
        }

        $tags = array();
        $this->out->elementStart('ul', $class);
        while ($this->tag->fetch()) {
            $mode = $this->tag->private ? 'private' : 'public';
            $tags[] = $this->tag->tag;

            $this->out->elementStart('li', 'hashptag mode-' . $mode);
            // Avoid space by using raw output.
            $pt = '#url($this->tag->tag) .
              '">' . $this->tag->tag . '';
            $this->out->raw($pt);
            $this->out->elementEnd('li');
        }
        $this->out->elementEnd('ul');

        if ($this->isEditable()) {
            $this->showEditTagForm($tags);
        }

        $this->out->elementEnd('dd');
        $this->out->elementEnd('dl');
    }

    function showEditTagForm($tags=null)
    {
        $this->out->elementStart('div', 'form_tag_user_wrap');
        $this->out->elementStart('form', array('method' => 'post',
                                           'class' => 'form_tag_user',
                                           'name' => 'tagprofile',
                                           'action' => common_local_url('tagprofile', array('id' => $this->tagged->id))));

        $this->out->elementStart('fieldset');
        // TRANS: Fieldset legend in lists widget.
        $this->out->element('legend', null, _m('LEGEND','Edit lists'));
        $this->out->hidden('token', common_session_token());
        $this->out->hidden('id', $this->tagged->id);

        if (!$tags) {
            $tags = array();
        }

        $this->out->input('tags', $this->label(),
                     ($this->out->arg('tags')) ? $this->out->arg('tags') : implode(' ', $tags));
        // TRANS: Button text to save tags for a profile.
        $this->out->submit('save', _m('BUTTON','Save'));

        $this->out->elementEnd('fieldset');
        $this->out->elementEnd('form');
        $this->out->elementEnd('div');
    }

    function showEmptyList()
    {
        $this->out->elementStart('dl', 'entity_tags user_profile_tags');
        $this->out->element('dt', null, $this->label());
        $this->out->elementStart('dd');

        $class = 'tags';
        if ($this->isEditable()) {
            $class .= ' editable';
        }

        $this->out->elementStart('ul', $class);
        // TRANS: Empty list message for tags.
        $this->out->element('li', null, _('(None)'));
        $this->out->elementEnd('ul');

        if ($this->isEditable()) {
            $this->showEditTagForm();
        }
        $this->out->elementEnd('dd');
        $this->out->elementEnd('dl');
    }

    function isEditable()
    {
        return !empty($this->user) && $this->tagger->id == $this->user->id;
    }
}

class SelftagsWidget extends PeopletagsWidget
{
    function url($tag)
    {
        // link to self tag page
        return common_local_url('selftag', array('tag' => $tag));
    }

    function label()
    {
        // TRANS: Label in self tags widget.
        return _m('LABEL','Tags');
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Peopletags with the most subscribers section
 *
 * PHP version 5
 *
 * LICENCE: This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @category  Widget
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @copyright 2009 StatusNet, Inc.
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 * @link      http://status.net/
 */

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

/**
 * Peopletags with the most subscribers section
 *
 * @category Widget
 * @package  StatusNet
 * @author   Evan Prodromou <evan@status.net>
 * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 * @link     http://status.net/
 */
class PeopletagsBySubsSection extends PeopletagSection
{
    function getPeopletags()
    {
        $qry = 'SELECT profile_list.*, subscriber_count as value ' .
               'FROM profile_list WHERE profile_list.private = false ' .
               'ORDER BY value DESC ';

        $limit = PEOPLETAGS_PER_SECTION;
        $offset = 0;

        if (common_config('db','type') == 'pgsql') {
            $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
        } else {
            $qry .= ' LIMIT ' . $offset . ', ' . $limit;
        }

        $peopletag = Memcached_DataObject::cachedQuery('Profile_list',
                                                   $qry,
                                                   3600);
        return $peopletag;
    }

    function title()
    {
        // TRANS: Title for section contaning lists with the most subscribers.
        return _('Popular lists');
    }

    function divId()
    {
        return 'top_peopletags_by_subs';
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Base class for sections showing lists of peopletags
 *
 * PHP version 5
 *
 * LICENCE: This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @category  Widget
 * @package   StatusNet
 * @author    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/peopletaglist.php';

define('PEOPLETAGS_PER_SECTION', 6);

/**
 * Base class for sections
 *
 * These are the widgets that show interesting data about a person
 * peopletag, or site.
 *
 * @category Widget
 * @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/
 */
class PeopletagSection extends Section
{
    protected $avatarSize = AVATAR_MINI_SIZE;

    function showContent()
    {
        $tags = $this->getPeopletags();

        if (!$tags) {
            return false;
        }

        $cnt = 0;

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

        while ($tags->fetch() && ++$cnt <= PEOPLETAGS_PER_SECTION) {
            $this->showPeopletag($tags);
        }

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

        return ($cnt > PEOPLETAGS_PER_SECTION);
    }

    function getPeopletags()
    {
        return null;
    }

    function showPeopletag($peopletag)
    {
        $tag = new PeopletagSectionItem($peopletag, null, $this->out);
        $tag->show();
    }
}

class PeopletagSectionItem extends PeopletagListItem
{
    function showStart()
    {
    }

    function showEnd()
    {
    }

    function showPeopletag()
    {
        $this->showCreator();
        $this->showTag();
        $this->showPrivacy();
    }

    function show()
    {
        if (empty($this->peopletag)) {
            common_log(LOG_WARNING, "Trying to show missing peopletag; skipping.");
            return;
        }
        $mode = ($this->peopletag->private) ? 'private' : 'public';

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

        $this->out->elementStart('td', 'peopletag mode-' . $mode);
        $this->showPeopletag();
        $this->out->elementEnd('td');

        if (isset($this->peopletag->value)) {
            $this->out->element('td', 'value', $this->peopletag->value);
        }
        $this->out->elementEnd('tr');
    }

    function showTag()
    {
        // TRANS: List summary. %1$d is the number of users in the list,
        // TRANS: %2$d is the number of subscribers to the list.
        $title = sprintf(_('Listed: %1$d Subscribers: %2$d'),
                         $this->peopletag->taggedCount(),
                         $this->peopletag->subscriberCount());

        $this->out->elementStart('span', 'entry-title tag');

        $this->out->element('a',
            array('rel'   => 'bookmark',
                  'href'  => $this->url(),
                  'title' => $title),
            htmlspecialchars($this->peopletag->tag));
        $this->out->elementEnd('span');
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Lists a user is in
 *
 * PHP version 5
 *
 * LICENCE: This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @category  Widget
 * @package   StatusNet
 * @author    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);
}

/**
 * List a user has is in
 *
 * @category Widget
 * @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/
 */
class PeopletagsForUserSection extends PeopletagSection
{
    var $profile=null;

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

    function getPeopletags()
    {
        $limit = PEOPLETAGS_PER_SECTION+1;
        $offset = 0;

        $auth_user = common_current_user();
        $ptags = $this->profile->getOtherTags($auth_user, $offset, $limit);

        return $ptags;
    }

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

        if (!empty($user) && $this->profile->id == $user->id) {
            // TRANS: Title for page that displays which lists current user is part of.
            return sprintf(_('Lists with you'));
        }
        // TRANS: Title for page that displays which lists a user is part of.
        // TRANS: %s is a profile name.
        return sprintf(_('Lists with %s'), $this->profile->getBestName());
    }

    function link()
    {
        return common_local_url('peopletagsforuser',
                array('nickname' => $this->profile->nickname));
    }

    function moreUrl()
    {
        return $this->link();
    }

    function divId()
    {
        return 'peopletag_subscriptions';
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Peopletags a user has subscribed to
 *
 * PHP version 5
 *
 * LICENCE: This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @category  Widget
 * @package   StatusNet
 * @author    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);
}

/**
 * Peopletags a user has subscribed to
 *
 * @category Widget
 * @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/
 */
class PeopletagSubscriptionsSection extends PeopletagSection
{
    var $profile=null;
    var $ptags=null;

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

        $limit = PEOPLETAGS_PER_SECTION+1;
        $offset = 0;

        $this->ptags = $this->profile->getTagSubscriptions($offset, $limit);
    }

    function getPeopletags()
    {
        return $this->ptags;
    }

    function title()
    {
        // TRANS: Title for page that displays lists a user has subscribed to.
        return _('List subscriptions');
    }

    function link()
    {
        return common_local_url('peopletagsubscriptions',
                array('nickname' => $this->profile->nickname));
    }

    function moreUrl()
    {
        return $this->link();
    }

    function divId()
    {
        return 'peopletag_subscriptions';
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Menu for personal 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>
 * @author    Sarven Capadisli <csarven@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 personal group of actions
 *
 * @category Menu
 * @package  StatusNet
 * @author   Evan Prodromou <evan@status.net>
 * @author   Sarven Capadisli <csarven@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/
 */
class PersonalGroupNav extends Menu
{
    /**
     * Show the menu
     *
     * @return void
     */
    public function show()
    {
        // FIXME: Legacy StatusNet behaviour was to do this, but really it should be the GroupNav
        // of the targeted user! ($this->action->arg('nickname')
        $target = Profile::current();

        if (!$target instanceof Profile) {
            throw new ServerException('Cannot show personal group navigation without a current user.');
        }

        $nickname  = $target->getNickname();
        $name      = $target->getBestName();

        $scoped = Profile::current();

        $action = $this->actionName;
        $mine = ($this->action->arg('nickname') == $nickname); // @fixme kinda vague

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

        if (Event::handle('StartPersonalGroupNav', array($this, $target, $scoped))) {
            $this->out->menuItem(common_local_url('all', array('nickname' =>
                                                               $nickname)),
                                 // 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.
                                 sprintf(_('%s and friends'), $name),
                                 $mine && $action =='all', 'nav_timeline_personal');
            $this->out->menuItem(common_local_url('showstream', array('nickname' =>
                                                                      $nickname)),
                                 // TRANS: Menu item in personal group navigation menu.
                                 _m('MENU','Profile'),
                                 // TRANS: Menu item title in personal group navigation menu.
                                 _('Your profile'),
                                 $mine && $action =='showstream',
                                 'nav_profile');
            $this->out->menuItem(common_local_url('replies', array('nickname' =>
                                                                   $nickname)),
                                 // TRANS: Menu item in personal group navigation menu.
                                 _m('MENU','Replies'),
                                 // TRANS: Menu item title in personal group navigation menu.
                                 // TRANS: %s is a username.
                                 sprintf(_('Replies to %s'), $name),
                                 $mine && $action =='replies', 'nav_timeline_replies');

            Event::handle('EndPersonalGroupNav', array($this, $target, $scoped));
        }
        $this->out->elementEnd('ul');
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Personal tag cloud section
 *
 * PHP version 5
 *
 * LICENCE: This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @category  Widget
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @copyright 2009 StatusNet, Inc.
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 * @link      http://status.net/
 */

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

/**
 * Personal tag cloud section
 *
 * @category Widget
 * @package  StatusNet
 * @author   Evan Prodromou <evan@status.net>
 * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 * @link     http://status.net/
 */
class PersonalTagCloudSection extends TagCloudSection
{
    var $user = null;

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

    function title()
    {
        // TRANS: Title for personal tag cloud section.
        return _m('TITLE','Tags');
    }

    function getTags()
    {
        $weightexpr = common_sql_weight('notice_tag.created', common_config('tag', 'dropoff'));
        // @fixme should we use the cutoff too? Doesn't help with indexing per-user.

        $qry = 'SELECT notice_tag.tag, '.
          $weightexpr . ' as weight ' .
          'FROM notice_tag JOIN notice ' .
          'ON notice_tag.notice_id = notice.id ' .
          'WHERE notice.profile_id = %d ' .
          'GROUP BY notice_tag.tag ' .
          'ORDER BY weight DESC ';

        $limit = TAGS_PER_SECTION;
        $offset = 0;

        if (common_config('db','type') == 'pgsql') {
            $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
        } else {
            $qry .= ' LIMIT ' . $offset . ', ' . $limit;
        }

        $tag = Memcached_DataObject::cachedQuery('Notice_tag',
                                                 sprintf($qry,
                                                         $this->user->id),
                                                 3600);
        return $tag;
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Database schema utilities
 *
 * 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  Database
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @copyright 2009 StatusNet, Inc.
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 * @link      http://status.net/
 */

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

/**
 * Class representing the database schema
 *
 * A class representing the database schema. Can be used to
 * manipulate the schema -- especially for plugins and upgrade
 * utilities.
 *
 * @category Database
 * @package  StatusNet
 * @author   Evan Prodromou <evan@status.net>
 * @author   Brenda Wallace <shiny@cpan.org>
 * @author   Brion Vibber <brion@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 PgsqlSchema extends Schema
{

    /**
     * Returns a table definition array for the table
     * in the schema with the given name.
     *
     * Throws an exception if the table is not found.
     *
     * @param string $table Name of the table to get
     *
     * @return array tabledef for that table.
     */

    public function getTableDef($table)
    {
        $def = array();
        $hasKeys = false;

        // Pull column data from INFORMATION_SCHEMA
        $columns = $this->fetchMetaInfo($table, 'columns', 'ordinal_position');
        if (count($columns) == 0) {
            throw new SchemaTableMissingException("No such table: $table");
        }

        // We'll need to match up fields by ordinal reference
        $orderedFields = array();

        foreach ($columns as $row) {

            $name = $row['column_name'];
            $orderedFields[$row['ordinal_position']] = $name;

            $field = array();
            $field['type'] = $row['udt_name'];

            if ($type == 'char' || $type == 'varchar') {
                if ($row['character_maximum_length'] !== null) {
                    $field['length'] = intval($row['character_maximum_length']);
                }
            }
            if ($type == 'numeric') {
                // Other int types may report these values, but they're irrelevant.
                // Just ignore them!
                if ($row['numeric_precision'] !== null) {
                    $field['precision'] = intval($row['numeric_precision']);
                }
                if ($row['numeric_scale'] !== null) {
                    $field['scale'] = intval($row['numeric_scale']);
                }
            }
            if ($row['is_nullable'] == 'NO') {
                $field['not null'] = true;
            }
            if ($row['column_default'] !== null) {
                $field['default'] = $row['column_default'];
                if ($this->isNumericType($type)) {
                    $field['default'] = intval($field['default']);
                }
            }

            $def['fields'][$name] = $field;
        }

        // Pulling index info from pg_class & pg_index
        // This can give us primary & unique key info, but not foreign key constraints
        // so we exclude them and pick them up later.
        $indexInfo = $this->getIndexInfo($table);
        foreach ($indexInfo as $row) {
            $keyName = $row['key_name'];

            // Dig the column references out!
            //
            // These are inconvenient arrays with partial references to the
            // pg_att table, but since we've already fetched up the column
            // info on the current table, we can look those up locally.
            $cols = array();
            $colPositions = explode(' ', $row['indkey']);
            foreach ($colPositions as $ord) {
                if ($ord == 0) {
                    $cols[] = 'FUNCTION'; // @fixme
                } else {
                    $cols[] = $orderedFields[$ord];
                }
            }

            $def['indexes'][$keyName] = $cols;
        }

        // Pull constraint data from INFORMATION_SCHEMA:
        // Primary key, unique keys, foreign keys
        $keyColumns = $this->fetchMetaInfo($table, 'key_column_usage', 'constraint_name,ordinal_position');
        $keys = array();

        foreach ($keyColumns as $row) {
            $keyName = $row['constraint_name'];
            $keyCol = $row['column_name'];
            if (!isset($keys[$keyName])) {
                $keys[$keyName] = array();
            }
            $keys[$keyName][] = $keyCol;
        }

        foreach ($keys as $keyName => $cols) {
            // name hack -- is this reliable?
            if ($keyName == "{$table}_pkey") {
                $def['primary key'] = $cols;
            } else if (preg_match("/^{$table}_(.*)_fkey$/", $keyName, $matches)) {
                $fkey = $this->getForeignKeyInfo($table, $keyName);
                $colMap = array_combine($cols, $fkey['col_names']);
                $def['foreign keys'][$keyName] = array($fkey['table_name'], $colMap);
            } else {
                $def['unique keys'][$keyName] = $cols;
            }
        }
        return $def;
    }

    /**
     * Pull some INFORMATION.SCHEMA data for the given table.
     *
     * @param string $table
     * @return array of arrays
     */
    function fetchMetaInfo($table, $infoTable, $orderBy=null)
    {
        $query = "SELECT * FROM information_schema.%s " .
                 "WHERE table_name='%s'";
        $sql = sprintf($query, $infoTable, $table);
        if ($orderBy) {
            $sql .= ' ORDER BY ' . $orderBy;
        }
        return $this->fetchQueryData($sql);
    }

    /**
     * Pull some PG-specific index info
     * @param string $table
     * @return array of arrays
     */
    function getIndexInfo($table)
    {
        $query = 'SELECT ' .
                 '(SELECT relname FROM pg_class WHERE oid=indexrelid) AS key_name, ' .
                 '* FROM pg_index ' .
                 'WHERE indrelid=(SELECT oid FROM pg_class WHERE relname=\'%s\') ' .
                 'AND indisprimary=\'f\' AND indisunique=\'f\' ' .
                 'ORDER BY indrelid, indexrelid';
        $sql = sprintf($query, $table);
        return $this->fetchQueryData($sql);
    }

    /**
     * Column names from the foreign table can be resolved with a call to getTableColumnNames()
     * @param <type> $table
     * @return array array of rows with keys: fkey_name, table_name, table_id, col_names (array of strings)
     */
    function getForeignKeyInfo($table, $constraint_name)
    {
        // In a sane world, it'd be easier to query the column names directly.
        // But it's pretty hard to work with arrays such as col_indexes in direct SQL here.
        $query = 'SELECT ' .
                 '(SELECT relname FROM pg_class WHERE oid=confrelid) AS table_name, ' .
                 'confrelid AS table_id, ' .
                 '(SELECT indkey FROM pg_index WHERE indexrelid=conindid) AS col_indexes ' .
                 'FROM pg_constraint ' .
                 'WHERE conrelid=(SELECT oid FROM pg_class WHERE relname=\'%s\') ' .
                 'AND conname=\'%s\' ' .
                 'AND contype=\'f\'';
        $sql = sprintf($query, $table, $constraint_name);
        $data = $this->fetchQueryData($sql);
        if (count($data) < 1) {
            throw new Exception("Could not find foreign key " . $constraint_name . " on table " . $table);
        }

        $row = $data[0];
        return array(
            'table_name' => $row['table_name'],
            'col_names' => $this->getTableColumnNames($row['table_id'], $row['col_indexes'])
        );
    }

    /**
     *
     * @param int $table_id
     * @param array $col_indexes
     * @return array of strings
     */
    function getTableColumnNames($table_id, $col_indexes)
    {
        $indexes = array_map('intval', explode(' ', $col_indexes));
        $query = 'SELECT attnum AS col_index, attname AS col_name ' .
                 'FROM pg_attribute where attrelid=%d ' .
                 'AND attnum IN (%s)';
        $sql = sprintf($query, $table_id, implode(',', $indexes));
        $data = $this->fetchQueryData($sql);

        $byId = array();
        foreach ($data as $row) {
            $byId[$row['col_index']] = $row['col_name'];
        }

        $out = array();
        foreach ($indexes as $id) {
            $out[] = $byId[$id];
        }
        return $out;
    }

    /**
     * Translate the (mostly) mysql-ish column types into somethings more standard
     * @param string column type
     *
     * @return string postgres happy column type
     */
    private function _columnTypeTranslation($type) {
      $map = array(
      'datetime' => 'timestamp',
      );
      if(!empty($map[$type])) {
        return $map[$type];
      }
      return $type;
    }

    /**
     * Return the proper SQL for creating or
     * altering a column.
     *
     * Appropriate for use in CREATE TABLE or
     * ALTER TABLE statements.
     *
     * @param array $cd column to create
     *
     * @return string correct SQL for that column
     */

    function columnSql(array $cd)
    {
        $line = array();
        $line[] = parent::columnSql($cd);

        /*
        if ($table['foreign keys'][$name]) {
            foreach ($table['foreign keys'][$name] as $foreignTable => $foreignColumn) {
                $line[] = 'references';
                $line[] = $this->quoteIdentifier($foreignTable);
                $line[] = '(' . $this->quoteIdentifier($foreignColumn) . ')';
            }
        }
        */

        return implode(' ', $line);
    }

    /**
     * Append phrase(s) to an array of partial ALTER TABLE chunks in order
     * to alter the given column from its old state to a new one.
     *
     * @param array $phrase
     * @param string $columnName
     * @param array $old previous column definition as found in DB
     * @param array $cd current column definition
     */
    function appendAlterModifyColumn(array &$phrase, $columnName, array $old, array $cd)
    {
        $prefix = 'ALTER COLUMN ' . $this->quoteIdentifier($columnName) . ' ';

        $oldType = $this->mapType($old);
        $newType = $this->mapType($cd);
        if ($oldType != $newType) {
            $phrase[] = $prefix . 'TYPE ' . $newType;
        }

        if (!empty($old['not null']) && empty($cd['not null'])) {
            $phrase[] = $prefix . 'DROP NOT NULL';
        } else if (empty($old['not null']) && !empty($cd['not null'])) {
            $phrase[] = $prefix . 'SET NOT NULL';
        }

        if (isset($old['default']) && !isset($cd['default'])) {
            $phrase[] = $prefix . 'DROP DEFAULT';
        } else if (!isset($old['default']) && isset($cd['default'])) {
            $phrase[] = $prefix . 'SET DEFAULT ' . $this->quoteDefaultValue($cd);
        }
    }

    /**
     * Append an SQL statement to drop an index from a table.
     * Note that in PostgreSQL, index names are DB-unique.
     *
     * @param array $statements
     * @param string $table
     * @param string $name
     * @param array $def
     */
    function appendDropIndex(array &$statements, $table, $name)
    {
        $statements[] = "DROP INDEX $name";
    }

    /**
     * Quote a db/table/column identifier if necessary.
     *
     * @param string $name
     * @return string
     */
    function quoteIdentifier($name)
    {
        return $this->conn->quoteIdentifier($name);
    }

    function mapType($column)
    {
        $map = array('serial' => 'bigserial', // FIXME: creates the wrong name for the sequence for some internal sequence-lookup function, so better fix this to do the real 'create sequence' dance.
                     'numeric' => 'decimal',
                     'datetime' => 'timestamp',
                     'blob' => 'bytea');

        $type = $column['type'];
        if (isset($map[$type])) {
            $type = $map[$type];
        }

        if ($type == 'int') {
            if (!empty($column['size'])) {
                $size = $column['size'];
                if ($size == 'small') {
                    return 'int2';
                } else if ($size == 'big') {
                    return 'int8';
                }
            }
            return 'int4';
        }

        return $type;
    }

    // @fixme need name... :P
    function typeAndSize($column)
    {
        if ($column['type'] == 'enum') {
            $vals = array_map(array($this, 'quote'), $column['enum']);
            return "text check ($name in " . implode(',', $vals) . ')';
        } else {
            return parent::typeAndSize($column);
        }
    }

    /**
     * Filter the given table definition array to match features available
     * in this database.
     *
     * This lets us strip out unsupported things like comments, foreign keys,
     * or type variants that we wouldn't get back from getTableDef().
     *
     * @param array $tableDef
     */
    function filterDef(array $tableDef)
    {
        foreach ($tableDef['fields'] as $name => &$col) {
            // No convenient support for field descriptions
            unset($col['description']);

            /*
            if (isset($col['size'])) {
                // Don't distinguish between tinyint and int.
                if ($col['size'] == 'tiny' && $col['type'] == 'int') {
                    unset($col['size']);
                }
            }
             */
            $col['type'] = $this->mapType($col);
            unset($col['size']);
        }
        if (!empty($tableDef['primary key'])) {
            $tableDef['primary key'] = $this->filterKeyDef($tableDef['primary key']);
        }
        if (!empty($tableDef['unique keys'])) {
            foreach ($tableDef['unique keys'] as $i => $def) {
                $tableDef['unique keys'][$i] = $this->filterKeyDef($def);
            }
        }
        return $tableDef;
    }

    /**
     * Filter the given key/index definition to match features available
     * in this database.
     *
     * @param array $def
     * @return array
     */
    function filterKeyDef(array $def)
    {
        // PostgreSQL doesn't like prefix lengths specified on keys...?
        foreach ($def as $i => $item)
        {
            if (is_array($item)) {
                $def[$i] = $item[0];
            }
        }
        return $def;
    }
}


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

function ping_broadcast_notice($notice) {
    if ($notice->is_local != Notice::LOCAL_PUBLIC && $notice->is_local != Notice::LOCAL_NONPUBLIC) {
        return true;
    }

    // Array of servers, URL => type
    $notify = common_config('ping', 'notify');
    try {
        $profile = $notice->getProfile();
    } catch (Exception $e) {
        // @todo: distinguish the 'broken notice/profile' case from more general
        //        transitory errors.
        common_log(LOG_ERR, "Exception getting notice profile: " . $e->getMessage());
        return true;
    }
    $tags = ping_notice_tags($notice);

    foreach ($notify as $notify_url => $type) {
        switch ($type) {
         case 'xmlrpc':
         case 'extended':
            $req = xmlrpc_encode_request('weblogUpdates.ping',
                                         array($profile->nickname, # site name
                                               common_local_url('showstream',
                                                                array('nickname' => $profile->nickname)),
                                               common_local_url('shownotice',
                                                                array('notice' => $notice->id)),
                                               common_local_url('userrss',
                                                                array('nickname' => $profile->nickname)),
                                               $tags));

            $request = HTTPClient::start();
            $request->setConfig('connect_timeout', common_config('ping', 'timeout'));
            $request->setConfig('timeout', common_config('ping', 'timeout'));
            try {
                $httpResponse = $request->post($notify_url, array('Content-Type: text/xml'), $req);
            } catch (Exception $e) {
                common_log(LOG_ERR,
                           "Exception pinging $notify_url: " . $e->getMessage());
                continue;
            }

            if (!$httpResponse || mb_strlen($httpResponse->getBody()) == 0) {
                common_log(LOG_WARNING,
                           "XML-RPC empty results for ping ($notify_url, $notice->id) ");
                continue;
            }

            $response = xmlrpc_decode($httpResponse->getBody());

            if (is_array($response) && xmlrpc_is_fault($response)) {
                common_log(LOG_WARNING,
                           "XML-RPC error for ping ($notify_url, $notice->id) ".
                           "$response[faultString] ($response[faultCode])");
            } else {
                common_log(LOG_INFO,
                           "Ping success for $notify_url $notice->id");
            }
            break;
         case 'get':
         case 'post':
            $args = array('name' => $profile->nickname,
                          'url' => common_local_url('showstream',
                                                    array('nickname' => $profile->nickname)),
                          'changesURL' => common_local_url('userrss',
                                                           array('nickname' => $profile->nickname)));

            $fetcher = Auth_Yadis_Yadis::getHTTPFetcher();

            if ($type === 'get') {
                $result = $fetcher->get($notify_url . '?' . http_build_query($args),
                                        array('User-Agent: ' . HTTPClient::userAgent()));
            } else {
                $result = $fetcher->post($notify_url,
                                         http_build_query($args),
                                         array('User-Agent: ' . HTTPClient::userAgent()));
            }
            if ($result->status != '200') {
                common_log(LOG_WARNING,
                           "Ping error for '$notify_url' ($notice->id): ".
                           "$result->body");
            } else {
                common_log(LOG_INFO,
                           "Ping success for '$notify_url' ($notice->id): ".
                           "'$result->body'");
            }
            break;
         default:
            common_log(LOG_WARNING, 'Unknown notify type for ' . $notify_url . ': ' . $type);
        }
    }

    return true;
}

function ping_notice_tags($notice) {
    $tag = new Notice_tag();
    $tag->notice_id = $notice->id;
    $tags = array();
    if ($tag->find()) {
        while ($tag->fetch()) {
            $tags[] = $tag->tag;
        }
        $tag->free();
        unset($tag);
        return implode('|', $tags);
    }
    return NULL;
}


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

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

    function transport() {
        return 'ping';
    }

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