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

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

/**
 * Miscellaneous settings actions
 *
 * Currently this just manages URL shortening.
 *
 * @category Settings
 * @package  StatusNet
 * @author   Robin Millette <millette@status.net>
 * @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 UrlsettingsAction extends SettingsAction
{
    /**
     * Title of the page
     *
     * @return string Title of the page
     */
    function title()
    {
        // TRANS: Title of URL settings tab in profile settings.
        return _('URL settings');
    }

    /**
     * Instructions for use
     *
     * @return instructions for use
     */
    function getInstructions()
    {
        // TRANS: Instructions for tab "Other" in user profile settings.
        return _('Manage various other options.');
    }

    function showScripts()
    {
        parent::showScripts();
        $this->autofocus('urlshorteningservice');
    }

    /**
     * Content area of the page
     *
     * Shows a form for uploading an avatar.
     *
     * @return void
     */
    function showContent()
    {
        $user = $this->scoped->getUser();

        $this->elementStart('form', array('method' => 'post',
                                          'id' => 'form_settings_other',
                                          'class' => 'form_settings',
                                          'action' =>
                                          common_local_url('urlsettings')));
        $this->elementStart('fieldset');
        $this->hidden('token', common_session_token());
        $this->elementStart('ul', 'form_data');

        $shorteners = array();

        Event::handle('GetUrlShorteners', array(&$shorteners));

        $services = array();

        foreach ($shorteners as $name => $value)
        {
            $services[$name] = $name;
            if ($value['freeService']) {
                // TRANS: Used as a suffix for free URL shorteners in a dropdown list in the tab "Other" of a
                // TRANS: user's profile settings. This message has one space at the beginning. Use your
                // TRANS: language's word separator here if it has one (most likely a single space).
                $services[$name] .= _(' (free service)');
            }
        }

        // Include default values

        // TRANS: Default value for URL shortening settings.
        $services['none']     = _('[none]');
        // TRANS: Default value for URL shortening settings.
        $services['internal'] = _('[internal]');

        if ($services) {
            asort($services);

            $this->elementStart('li');
            // TRANS: Label for dropdown with URL shortener services.
            $this->dropdown('urlshorteningservice', _('Shorten URLs with'),
                            // TRANS: Tooltip for for dropdown with URL shortener services.
                            $services, _('Automatic shortening service to use.'),
                            false, $user->urlshorteningservice);
            $this->elementEnd('li');
        }
        $this->elementStart('li');
        $this->input('maxurllength',
                     // TRANS: Field label in URL settings in profile.
                     _('URL longer than'),
                     (!is_null($this->arg('maxurllength'))) ?
                     $this->arg('maxurllength') : User_urlshortener_prefs::maxUrlLength($user),
                     // TRANS: Field title in URL settings in profile.
                     _('URLs longer than this will be shortened, -1 means never shorten because a URL is long.'));
        $this->elementEnd('li');
        $this->elementStart('li');
        $this->input('maxnoticelength',
                     // TRANS: Field label in URL settings in profile.
                     _('Text longer than'),
                     (!is_null($this->arg('maxnoticelength'))) ?
                     $this->arg('maxnoticelength') : User_urlshortener_prefs::maxNoticeLength($user),
                     // TRANS: Field title in URL settings in profile.
                     _('URLs in notices longer than this will always be shortened, -1 means only shorten if the full post exceeds maximum length.'));
        $this->elementEnd('li');
        $this->elementEnd('ul');
        // TRANS: Button text for saving "Other settings" in profile.
        $this->submit('save', _m('BUTTON','Save'));
        $this->elementEnd('fieldset');
        $this->elementEnd('form');
    }

    protected function doPost()
    {
        $urlshorteningservice = $this->trimmed('urlshorteningservice');

        if (!is_null($urlshorteningservice) && strlen($urlshorteningservice) > 50) {
            // TRANS: Form validation error for form "Other settings" in user profile.
            throw new ClientException(_('URL shortening service is too long (maximum 50 characters).'));
        }

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

        if (!Validate::number($maxurllength, array('min' => -1))) {
            // TRANS: Client exception thrown when the maximum URL settings value is invalid in profile URL settings.
            throw new ClientException(_('Invalid number for maximum URL length.'));
        }

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

        if (!Validate::number($maxnoticelength, array('min' => -1))) {
            // TRANS: Client exception thrown when the maximum notice length settings value is invalid in profile URL settings.
            throw new ClientException(_('Invalid number for maximum notice length.'));
        }

        $user = $this->scoped->getUser();

        $user->query('BEGIN');

        $original = clone($user);

        $user->urlshorteningservice = $urlshorteningservice;

        $result = $user->update($original);

        if ($result === false) {
            common_log_db_error($user, 'UPDATE', __FILE__);
            $user->query('ROLLBACK');
            // TRANS: Server error displayed when "Other" settings in user profile could not be updated on the server.
            throw new ServerException(_('Could not update user.'));
        }

        $prefs = User_urlshortener_prefs::getPrefs($user);
        $orig  = null;

        if (!$prefs instanceof User_urlshortener_prefs) {
            $prefs = new User_urlshortener_prefs();

            $prefs->user_id = $user->id;
            $prefs->created = common_sql_now();
        } else {
            $orig = clone($prefs);
        }

        $prefs->urlshorteningservice = $urlshorteningservice;
        $prefs->maxurllength         = $maxurllength;
        $prefs->maxnoticelength      = $maxnoticelength;

        if ($orig instanceof User_urlshortener_prefs) {
            $result = $prefs->update($orig);
        } else {
            $result = $prefs->insert();
        }

        if ($result === null) {
            $user->query('ROLLBACK');
            // TRANS: Server exception thrown in profile URL settings when preferences could not be saved.
            throw new ServerException(_('Error saving user URL shortening preferences.'));
        }

        $user->query('COMMIT');

        // TRANS: Confirmation message after saving preferences.
        return _('Preferences saved.');
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * User administration panel
 *
 * 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  Settings
 * @package   StatusNet
 * @author    Evan Prodromou <evan@status.net>
 * @author    Zach Copley <zach@status.net>
 * @author    Sarven Capadisli <csarven@status.net>
 * @copyright 2008-2010 StatusNet, Inc.
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 * @link      http://status.net/
 */

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

/**
 * Administer user settings
 *
 * @category Admin
 * @package  StatusNet
 * @author   Evan Prodromou <evan@status.net>
 * @author   Zach Copley <zach@status.net>
 * @author   Sarven Capadisli <csarven@status.net>
 * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 * @link     http://status.net/
 */
class UseradminpanelAction extends AdminPanelAction
{
    /**
     * Returns the page title
     *
     * @return string page title
     */
    function title()
    {
        // TRANS: User admin panel title.
        return _m('TITLE', 'User');
    }

    /**
     * Instructions for using this form.
     *
     * @return string instructions
     */
    function getInstructions()
    {
        // TRANS: Instruction for user admin panel.
        return _('User settings for this StatusNet site');
    }

    /**
     * Show the site admin panel form
     *
     * @return void
     */
    function showForm()
    {
        $form = new UserAdminPanelForm($this);
        $form->show();
        return;
    }

    /**
     * Save settings from the form
     *
     * @return void
     */
    function saveSettings()
    {
        static $settings = array(
                'profile' => array('biolimit'),
                'newuser' => array('welcome', 'default')
        );

        static $booleans = array(
            'invite' => array('enabled')
        );

        $values = array();

        foreach ($settings as $section => $parts) {
            foreach ($parts as $setting) {
                $values[$section][$setting] = $this->trimmed("$section-$setting");
            }
        }

        foreach ($booleans as $section => $parts) {
            foreach ($parts as $setting) {
                $values[$section][$setting] = ($this->boolean("$section-$setting")) ? 1 : 0;
            }
        }

        // This throws an exception on validation errors

        $this->validate($values);

        // assert(all values are valid);

        $config = new Config();

        $config->query('BEGIN');

        foreach ($settings as $section => $parts) {
            foreach ($parts as $setting) {
                Config::save($section, $setting, $values[$section][$setting]);
            }
        }

        foreach ($booleans as $section => $parts) {
            foreach ($parts as $setting) {
                Config::save($section, $setting, $values[$section][$setting]);
            }
        }

        $config->query('COMMIT');

        return;
    }

    function validate(&$values)
    {
        // Validate biolimit

        if (!Validate::number($values['profile']['biolimit'])) {
            // TRANS: Form validation error in user admin panel when a non-numeric character limit was set.
            $this->clientError(_('Invalid bio limit. Must be numeric.'));
        }

        // Validate welcome text

        if (mb_strlen($values['newuser']['welcome']) > 255) {
            // TRANS: Form validation error in user admin panel when welcome text is too long.
            $this->clientError(_('Invalid welcome text. Maximum length is 255 characters.'));
        }

        // Validate default subscription

        if (!empty($values['newuser']['default'])) {
            $defuser = User::getKV('nickname', trim($values['newuser']['default']));
            if (empty($defuser)) {
                $this->clientError(
                    sprintf(
                        // TRANS: Client error displayed when trying to set a non-existing user as default subscription for new
                        // TRANS: users in user admin panel. %1$s is the invalid nickname.
                        _('Invalid default subscripton: "%1$s" is not a user.'),
                        $values['newuser']['default']
                    )
                );
            }
        }
    }
}

// @todo FIXME: Class documentation missing.
class UserAdminPanelForm extends AdminForm
{
    /**
     * ID of the form
     *
     * @return int ID of the form
     */
    function id()
    {
        return 'useradminpanel';
    }

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

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

    /**
     * Data elements of the form
     *
     * @return void
     */
    function formData()
    {
        $this->out->elementStart('fieldset', array('id' => 'settings_user-profile'));
        // TRANS: Fieldset legend in user administration panel.
        $this->out->element('legend', null, _m('LEGEND','Profile'));
        $this->out->elementStart('ul', 'form_data');

        $this->li();
        // TRANS: Field label in user admin panel for setting the character limit for the bio field.
        $this->input('biolimit', _('Bio Limit'),
                     // TRANS: Tooltip in user admin panel for setting the character limit for the bio field.
                     _('Maximum length of a profile bio in characters.'),
                     'profile');
        $this->unli();

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

        $this->out->elementStart('fieldset', array('id' => 'settings_user-newusers'));
        // TRANS: Form legend in user admin panel.
        $this->out->element('legend', null, _('New users'));
        $this->out->elementStart('ul', 'form_data');

        $this->li();
        // TRANS: Field label in user admin panel for setting new user welcome text.
        $this->input('welcome', _('New user welcome'),
                     // TRANS: Tooltip in user admin panel for setting new user welcome text.
                     _('Welcome text for new users (maximum 255 characters).'),
                     'newuser');
        $this->unli();

        $this->li();
        // TRANS: Field label in user admin panel for setting default subscription for new users.
        $this->input('default', _('Default subscription'),
                     // TRANS: Tooltip in user admin panel for setting default subscription for new users.
                     _('Automatically subscribe new users to this user.'),
                     'newuser');
        $this->unli();

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

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

        $this->out->elementStart('fieldset', array('id' => 'settings_user-invitations'));
        // TRANS: Form legend in user admin panel.
        $this->out->element('legend', null, _('Invitations'));
        $this->out->elementStart('ul', 'form_data');

        $this->li();

        // TRANS: Field label for checkbox in user admin panel for allowing users to invite friend using site e-mail.
        $this->out->checkbox('invite-enabled', _('Invitations enabled'),
                              (bool) $this->value('enabled', 'invite'),
                              // TRANS: Tooltip for checkbox in user admin panel for allowing users to invite friend using site e-mail.
                              _('Whether to allow users to invite new users.'));
        $this->unli();

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

    /**
     * Utility to simplify some of the duplicated code around
     * params and settings.  Overrided from base class to be
     * more specific about input ids.
     *
     * @param string $setting      Name of the setting
     * @param string $title        Title to use for the input
     * @param string $instructions Instructions for this field
     * @param string $section      config section, default = 'site'
     *
     * @return void
     */
    function input($setting, $title, $instructions, $section='site')
    {
        $this->out->input("$section-$setting", $title, $this->value($setting, $section), $instructions);
    }

    /**
     * Action elements
     *
     * @return void
     */
    function formActions()
    {
        $this->out->submit('submit',
                           // TRANS: Button text to save user settings in user admin panel.
                           _m('BUTTON','Save'),
                           'submit',
                           null,
                           // TRANS: Button title to save user settings in user admin panel.
                           _('Save user settings.'));
    }
}

repo_name: andremichelle/gnu

license: mit


code:
<?php
/**
 * User by ID action class.
 *
 * PHP version 5
 *
 * @category Action
 * @package  StatusNet
 * @author   Evan Prodromou <evan@status.net>
 * @author   Robin Millette <millette@status.net>
 * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
 * @link     http://status.net/

 * StatusNet - the distributed open-source microblogging tool
 * Copyright (C) 2008, 2009, StatusNet, Inc.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

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

/**
 * User by ID action class.
 *
 * @category Action
 * @package  StatusNet
 * @author   Evan Prodromou <evan@status.net>
 * @author   Robin Millette <millette@status.net>
 * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
 * @link     http://status.net/
 */
class UserbyidAction extends ShowstreamAction
{
    protected function doPreparation()
    {
        // accessing by ID just requires an ID, not a nickname
        $this->target = Profile::getByID($this->trimmed('id'));

        // For local users when accessed by id number, redirect with
        // the nickname as argument instead of id.
        if ($this->target->isLocal()) {
            // Support redirecting to FOAF rdf/xml if the agent prefers it...
            // Internet Explorer doesn't specify "text/html" and does list "*/*"
            // at least through version 8. We need to list text/html up front to
            // ensure that only user-agents who specifically ask for RDF get it.
            $page_prefs = 'text/html,application/xhtml+xml,application/rdf+xml,application/xml;q=0.3,text/xml;q=0.2';
            $httpaccept = isset($_SERVER['HTTP_ACCEPT']) ? $_SERVER['HTTP_ACCEPT'] : null;
            $type       = common_negotiate_type(common_accept_to_prefs($httpaccept),
                                                common_accept_to_prefs($page_prefs));
            $page       = $type === 'application/rdf+xml' ? 'foaf' : 'showstream';
            $url        = common_local_url($page, array('nickname' => $this->target->getNickname()));
            common_redirect($url, 303);
        }
    }
}


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

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

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

/**
 * User groups page
 *
 * Show the groups a user belongs to
 *
 * @category Personal
 * @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 UsergroupsAction extends GalleryAction
{
    function title()
    {
        if ($this->page == 1) {
            // TRANS: Page title for first page of groups for a user.
            // TRANS: %s is a nickname.
            return sprintf(_('%s groups'), $this->getTarget()->getNickname());
        } else {
            // TRANS: Page title for all but the first page of groups for a user.
            // TRANS: %1$s is a nickname, %2$d is a page number.
            return sprintf(_('%1$s groups, page %2$d'),
                           $this->getTarget()->getNickname(),
                           $this->page);
        }
    }

    function showPageNotice()
    {
        if ($this->scoped instanceof Profile && $this->scoped->sameAs($this->getTarget())) {
            $this->element('p', 'instructions',
                           // TRANS: Page notice for page with an overview of all subscribed groups
                           // TRANS: of the logged in user's own profile.
                           _('These are the groups whose notices '.
                             'you listen to.'));
        } else {
            $this->element('p', 'instructions',
                           // TRANS: Page notice for page with an overview of all groups a user other
                           // TRANS: than the logged in user. %s is the user nickname.
                           sprintf(_('These are the groups whose '.
                                     'notices %s listens to.'),
                                   $this->target->getNickname()));
        }
    }

    function showContent()
    {
        if ($this->scoped instanceof Profile && $this->scoped->sameAs($this->getTarget())) {
	  $notice =
          // TRANS: Page notice of user's groups page.
          // TRANS: %%%%action.groupsearch%%%% and %%%%action.newgroup%%%% are URLs. Do not change them.
          // TRANS: This message contains Markdown links in the form [link text](link).
          sprintf(_('Groups let you find and talk with ' .
		    'people of similar interests. ' .
		    'You can [search for groups](%%%%action.groups%%%%) in your instance or ' .
                    '[create a new group](%%%%action.newgroup%%%%). ' .
		    'You can also follow groups ' .
		    'from other GNU social instances: click on the remote button below ' .
		    'and copy the group\'s link. ' .
		    'You can find a list of GNU social groups [here](http://skilledtests.com/wiki/List_of_federated_GNU_social_groups)' .
		    ''));
	  $this->elementStart('div', 'instructions');
	  $this->raw(common_markup_to_html($notice));
	  $this->elementEnd('div');
	}

        if (Event::handle('StartShowUserGroupsContent', array($this))) {
            $offset = ($this->page-1) * GROUPS_PER_PAGE;
            $limit =  GROUPS_PER_PAGE + 1;

            $groups = $this->getTarget()->getGroups($offset, $limit);

            if ($groups instanceof User_group) {
                $gl = new GroupList($groups, $this->getTarget(), $this);
                $cnt = $gl->show();
		if (0 == $cnt) {
		  $this->showEmptyListMessage();
		} else {
		  $this->pagination($this->page > 1, $cnt > GROUPS_PER_PAGE,
				    $this->page, 'usergroups',
				    array('nickname' => $this->getTarget()->getNickname()));
		}
            }

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

    function showEmptyListMessage()
    {
        // TRANS: Text on group page for a user that is not a member of any group.
        // TRANS: %s is a user nickname.
        $message = sprintf(_('%s is not a member of any group.'), $this->getTarget()->getNickname()) . ' ';
        if (common_logged_in()) {
            if ($this->scoped->sameAs($this->getTarget())) {
                // TRANS: Text on group page for a user that is not a member of any group. This message contains
                // TRANS: a Markdown link in the form [link text](link) and a variable that should not be changed.
	        $message = _('You are not member of any group yet. After you join a group ' .
			     'you can send messages to its members using the ' .
			     'syntax "!groupname".');
            }
	}
        $this->elementStart('div', 'guide');
        $this->raw(common_markup_to_html($message));
        $this->elementEnd('div');
    }

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


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('GNUSOCIAL')) { exit(1); }

// Formatting of RSS handled by Rss10Action

class UserrssAction extends TargetedRss10Action
{
    protected $tag = null;

    protected function doStreamPreparation()
    {
        parent::doStreamPreparation();

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

    protected function getNotices()
    {
        if (!empty($this->tag)) {
            $stream = $this->getTarget()->getTaggedNotices($this->tag, 0, $this->limit);
            return $stream->fetchAll();
        }
        // otherwise we fetch a normal user stream

        $stream = $this->getTarget()->getNotices(0, $this->limit);
        return $stream->fetchAll();
    }

    function getChannel()
    {
        $c = array('url' => common_local_url('userrss',
                                             array('nickname' =>
                                                   $this->target->getNickname())),
                   // TRANS: Message is used as link title. %s is a user nickname.
                   'title' => sprintf(_('%s timeline'), $this->target->getNickname()),
                   'link' => $this->target->getUrl(),
                   // TRANS: Message is used as link description. %1$s is a username, %2$s is a site name.
                   'description' => sprintf(_('Updates from %1$s on %2$s!'),
                                            $this->target->getNickname(), common_config('site', 'name')));
        return $c;
    }

    // override parent to add X-SUP-ID URL

    function initRss()
    {
        $url = common_local_url('sup', null, null, $this->target->getID());
        header('X-SUP-ID: '.$url);
        parent::initRss();
    }

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


code:
<?php
/**
 * StatusNet - the distributed open-source microblogging tool
 * Copyright (C) 2008-2011, StatusNet, Inc.
 *
 * Show version information for this software and plugins
 *
 * 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 Info
 * @package  GNUsocial
 * @author   Evan Prodromou <evan@status.net>
 * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3
 * @link     http://status.net/
 */

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

/**
 * Version info page
 *
 * A page that shows version information for this site. Helpful for
 * debugging, for giving credit to authors, and for linking to more
 * complete documentation for admins.
 *
 * @category Info
 * @package  GNUsocial
 * @author   Evan Prodromou <evan@status.net>
 * @author   Craig Andrews <candrews@integralblue.com>
 * @copyright 2009-2011 Free Software Foundation, Inc http://www.fsf.org
 * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3
 * @link     http://status.net/
 */
class VersionAction extends Action
{
    var $pluginVersions = array();

    /**
     * Return true since we're read-only.
     *
     * @param array $args other arguments
     *
     * @return boolean is read only action?
     */
    function isReadOnly($args)
    {
        return true;
    }

    /**
     * Returns the page title
     *
     * @return string page title
     */
    function title()
    {
        // TRANS: Title for version page. %1$s is the engine name, %2$s is the engine version.
        return sprintf(_('%1$s %2$s'), GNUSOCIAL_ENGINE, GNUSOCIAL_VERSION);
    }

    /**
     * Prepare to run
     *
     * Fire off an event to let plugins report their
     * versions.
     *
     * @param array $args array misc. arguments
     *
     * @return boolean true
     */
    protected function prepare(array $args=array())
    {
        parent::prepare($args);

        Event::handle('PluginVersion', array(&$this->pluginVersions));

        return true;
    }

    /**
     * Execute the action
     *
     * Shows a page with the version information in the
     * content area.
     *
     * @param array $args ignored.
     *
     * @return void
     */
    protected function handle()
    {
        parent::handle();
        $this->showPage();
    }

    /*
    * Override to add h-entry, and content-inner classes
    *
    * @return void
    */
    function showContentBlock()
     {
         $this->elementStart('div', array('id' => 'content', 'class' => 'h-entry'));
         $this->showPageTitle();
         $this->showPageNoticeBlock();
         $this->elementStart('div', array('id' => 'content_inner',
                                          'class' => 'e-content'));
         // show the actual content (forms, lists, whatever)
         $this->showContent();
         $this->elementEnd('div');
         $this->elementEnd('div');
     }

    /*
    * Overrride to add entry-title class
    *
    * @return void
    */
    function showPageTitle() {
        $this->element('h1', array('class' => 'entry-title'), $this->title());
    }

    /**
     * Show version information
     *
     * @return void
     */
    function showContent()
    {
        $this->elementStart('p');

        // TRANS: Content part of engine version page.
        // TRANS: %1$s is the engine name (GNU social) and %2$s is the GNU social version.
        $this->raw(sprintf(_('This site is powered by %1$s version %2$s, '.
                             'Copyright 2010 Free Software Foundation, Inc.'),
                           XMLStringer::estring('a', array('href' => GNUSOCIAL_ENGINE_URL),
                                                // TRANS: Engine name.
                                                GNUSOCIAL_ENGINE),
                           GNUSOCIAL_VERSION));
        $this->elementEnd('p');

        // TRANS: Header for engine software contributors section on the version page.
        $this->element('h2', null, _('Contributors'));

        $this->elementStart('p');
        $this->raw(sprintf('See %s for a full list of contributors.',
                           XMLStringer::estring('a', array('href' => 'https://notabug.org/diogo/gnu-social/src/nightly/CREDITS.md'),
                                                'https://notabug.org/diogo/gnu-social/src/nightly/CREDITS.md')));
        $this->elementEnd('p');

        // TRANS: Header for engine software license section on the version page.
        $this->element('h2', null, _('License'));

        $this->element('p', null,
                       // TRANS: Content part of engine software version page. %1s is engine name
                       sprintf(_('%1$s 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.'), GNUSOCIAL_ENGINE));

        $this->element('p', null,
                       // TRANS: Content part of engine software version page.
                       _('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.'));

        $this->elementStart('p');
        // TRANS: Content part of engine version page.
        // TRANS: %s is a link to the AGPL license with link description "http://www.gnu.org/licenses/agpl.html".
        $this->raw(sprintf(_('You should have received a copy of the GNU Affero General Public License '.
                             'along with this program.  If not, see %s.'),
                           XMLStringer::estring('a', array('href' => 'https://www.gnu.org/licenses/agpl.html'),
                                                'https://www.gnu.org/licenses/agpl.html')));
        $this->elementEnd('p');

        // XXX: Theme information?

        if (count($this->pluginVersions)) {
            // TRANS: Header for engine plugins section on the version page.
            $this->element('h2', null, _('Plugins'));

            $this->elementStart('table', array('id' => 'plugins_enabled'));

            $this->elementStart('thead');
            $this->elementStart('tr');
            // TRANS: Column header for plugins table on version page.
            $this->element('th', array('id' => 'plugin_name'), _m('HEADER','Name'));
            // TRANS: Column header for plugins table on version page.
            $this->element('th', array('id' => 'plugin_version'), _m('HEADER','Version'));
            // TRANS: Column header for plugins table on version page.
            $this->element('th', array('id' => 'plugin_authors'), _m('HEADER','Author(s)'));
            // TRANS: Column header for plugins table on version page.
            $this->element('th', array('id' => 'plugin_description'), _m('HEADER','Description'));
            $this->elementEnd('tr');
            $this->elementEnd('thead');

            $this->elementStart('tbody');
            foreach ($this->pluginVersions as $plugin) {
                $this->elementStart('tr');
                if (array_key_exists('homepage', $plugin)) {
                    $this->elementStart('th');
                    $this->element('a', array('href' => $plugin['homepage']),
                                   $plugin['name']);
                    $this->elementEnd('th');
                } else {
                    $this->element('th', null, $plugin['name']);
                }

                $this->element('td', null, $plugin['version']);

                if (array_key_exists('author', $plugin)) {
                    $this->element('td', null, $plugin['author']);
                }

                if (array_key_exists('rawdescription', $plugin)) {
                    $this->elementStart('td');
                    $this->raw($plugin['rawdescription']);
                    $this->elementEnd('td');
                } else if (array_key_exists('description', $plugin)) {
                    $this->element('td', null, $plugin['description']);
                }
                $this->elementEnd('tr');
            }
            $this->elementEnd('tbody');
            $this->elementEnd('table');
        }

    }
}


code:
<?php
/*
 * GNU social - a federating social network
 * Copyright (C) 2014, Free Software Foundation, 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/>.
 */

class Attention extends Managed_DataObject
{
    public $__table = 'attention';  // table name
    public $notice_id;              // int(4) primary_key not_null
    public $profile_id;             // int(4) primary_key not_null
    public $reason;                 // varchar(191)   not 255 because utf8mb4 takes more space
    public $created;                // datetime()   not_null
    public $modified;               // timestamp   not_null default_CURRENT_TIMESTAMP

    public static function schemaDef()
    {
        return array(
            'description' => 'Notice attentions to profiles (that are not a mention and not result of a subscription)',
            'fields' => array(
                'notice_id' => array('type' => 'int', 'not null' => true, 'description' => 'notice_id to give attention'),
                'profile_id' => array('type' => 'int', 'not null' => true, 'description' => 'profile_id for feed receiver'),
                'reason' => array('type' => 'varchar', 'length' => 191, 'description' => 'Optional reason why this was brought to the attention of profile_id'),
                'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
                'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
            ),
            'primary key' => array('notice_id', 'profile_id'),
            'foreign keys' => array(
                'attention_notice_id_fkey' => array('notice', array('notice_id' => 'id')),
                'attention_profile_id_fkey' => array('profile', array('profile_id' => 'id')),
            ),
            'indexes' => array(
                'attention_notice_id_idx' => array('notice_id'),
                'attention_profile_id_idx' => array('profile_id'),
            ),
        );
    }

    public static function saveNew(Notice $notice, Profile $target, $reason=null)
    {
        try {
            $att = Attention::getByKeys(['notice_id'=>$notice->getID(), 'profile_id'=>$target->getID()]);
            throw new AlreadyFulfilledException('Attention already exists with reason: '._ve($att->reason));
        } catch (NoResultException $e) {
            $att = new Attention();

            $att->notice_id = $notice->getID();
            $att->profile_id = $target->getID();
            $att->reason = $reason;
            $att->created = common_sql_now();
            $result = $att->insert();

            if ($result === false) {
                throw new Exception('Failed Attention::saveNew for notice id=='.$notice->getID().' target id=='.$target->getID().', reason=="'.$reason.'"');
            }
        }
        self::blow('attention:stream:%d', $target->getID());
        return $att;
    }
}


code:
<?php

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

/**
 * Table Definition for avatar
 */

class Avatar extends Managed_DataObject
{
    public $__table = 'avatar';                          // table name
    public $profile_id;                      // int(4)  primary_key not_null
    public $original;                        // tinyint(1)
    public $width;                           // int(4)  primary_key not_null
    public $height;                          // int(4)  primary_key not_null
    public $mediatype;                       // varchar(32)   not_null
    public $filename;                        // varchar(191)   not 255 because utf8mb4 takes more space
    public $created;                         // datetime()   not_null
    public $modified;                        // timestamp()   not_null default_CURRENT_TIMESTAMP

    public static function schemaDef()
    {
        return array(
            'fields' => array(
                'profile_id' => array('type' => 'int', 'not null' => true, 'description' => 'foreign key to profile table'),
                'original' => array('type' => 'int', 'size' => 'tiny', 'default' => 0, 'description' => 'uploaded by user or generated?'),
                'width' => array('type' => 'int', 'not null' => true, 'description' => 'image width'),
                'height' => array('type' => 'int', 'not null' => true, 'description' => 'image height'),
                'mediatype' => array('type' => 'varchar', 'length' => 32, 'not null' => true, 'description' => 'file type'),
                'filename' => array('type' => 'varchar', 'length' => 191, 'description' => 'local filename, if local'),
                'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
                'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
            ),
            'primary key' => array('profile_id', 'width', 'height'),
            'unique keys' => array(
//                'avatar_filename_key' => array('filename'),
            ),
            'foreign keys' => array(
                'avatar_profile_id_fkey' => array('profile', array('profile_id' => 'id')),
            ),
            'indexes' => array(
                'avatar_profile_id_idx' => array('profile_id'),
            ),
        );
    }

    // We clean up the file, too
    function delete($useWhere=false)
    {
        $filename = $this->filename;
        if (file_exists(Avatar::path($filename))) {
            @unlink(Avatar::path($filename));
        }

        return parent::delete($useWhere);
    }

    /*
     * Deletes all avatars (but may spare the original) from a profile.
     *
     * @param   Profile $target     The profile we're deleting avatars of.
     * @param   boolean $original   Whether original should be removed or not.
     */
    public static function deleteFromProfile(Profile $target, $original=true) {
        try {
            $avatars = self::getProfileAvatars($target);
            foreach ($avatars as $avatar) {
                if ($avatar->original && !$original) {
                    continue;
                }
                $avatar->delete();
            }
        } catch (NoAvatarException $e) {
            // There are no avatars to delete, a sort of success.
        }

        return true;
    }

    static protected $_avatars = array();

    /*
     * Get an avatar by profile. Currently can't call newSize with $height
     */
    public static function byProfile(Profile $target, $width=null, $height=null)
    {
        $width  = intval($width);
        $height = !is_null($height) ? intval($height) : null;
        if (is_null($height)) {
            $height = $width;
        }

        $size = "{$width}x{$height}";
        if (!isset(self::$_avatars[$target->id])) {
            self::$_avatars[$target->id] = array();
        } elseif (isset(self::$_avatars[$target->id][$size])){
            return self::$_avatars[$target->id][$size];
        }

        $avatar = null;
        if (Event::handle('StartProfileGetAvatar', array($target, $width, &$avatar))) {
            $avatar = self::pkeyGet(
                array(
                    'profile_id' => $target->id,
                    'width'      => $width,
                    'height'     => $height,
                )
            );
            Event::handle('EndProfileGetAvatar', array($target, $width, &$avatar));
        }

        if (is_null($avatar)) {
            // Obviously we can't find an avatar, so let's resize the original!
            $avatar = Avatar::newSize($target, $width);
        } elseif (!($avatar instanceof Avatar)) {
            throw new NoAvatarException($target, $avatar);
        }

        self::$_avatars[$target->id]["{$avatar->width}x{$avatar->height}"] = $avatar;
        return $avatar;
    }

    public static function getUploaded(Profile $target)
    {
        $avatar = new Avatar();
        $avatar->profile_id = $target->id;
        $avatar->original = true;
        if (!$avatar->find(true)) {
            throw new NoAvatarException($target, $avatar);
        }
        if (!file_exists(Avatar::path($avatar->filename))) {
            // The delete call may be odd for, say, unmounted filesystems
            // that cause a file to currently not exist, but actually it does...
            $avatar->delete();
            throw new NoAvatarException($target, $avatar);
        }
        return $avatar;
    }

    public static function getProfileAvatars(Profile $target) {
        $avatar = new Avatar();
        $avatar->profile_id = $target->id;
        if (!$avatar->find()) {
            throw new NoAvatarException($target, $avatar);
        }
        return $avatar->fetchAll();
    }

    /**
     * Where should the avatar go for this user?
     */
    static function filename($id, $extension, $size=null, $extra=null)
    {
        if ($size) {
            return $id . '-' . $size . (($extra) ? ('-' . $extra) : '') . $extension;
        } else {
            return $id . '-original' . (($extra) ? ('-' . $extra) : '') . $extension;
        }
    }

    static function path($filename)
    {
        $dir = common_config('avatar', 'dir');

        if ($dir[strlen($dir)-1] != '/') {
            $dir .= '/';
        }

        return $dir . $filename;
    }

    static function url($filename)
    {
        $path = common_config('avatar', 'path');

        if ($path[strlen($path)-1] != '/') {
            $path .= '/';
        }

        if ($path[0] != '/') {
            $path = '/'.$path;
        }

        $server = common_config('avatar', 'server');

        if (empty($server)) {
            $server = common_config('site', 'server');
        }

        $ssl = (common_config('avatar', 'ssl') || GNUsocial::useHTTPS());

        $protocol = ($ssl) ? 'https' : 'http';

        return $protocol.'://'.$server.$path.$filename;
    }

    function displayUrl()
    {
        return Avatar::url($this->filename);
    }

    static function urlByProfile(Profile $target, $width=null, $height=null) {
        try {
            return self::byProfile($target,  $width, $height)->displayUrl();
        } catch (Exception $e) {
            return self::defaultImage($width);
        }
    }

    static function defaultImage($size=null)
    {
        if (is_null($size)) {
            $size = AVATAR_PROFILE_SIZE;
        }
        static $sizenames = array(AVATAR_PROFILE_SIZE => 'profile',
                                  AVATAR_STREAM_SIZE => 'stream',
                                  AVATAR_MINI_SIZE => 'mini');
        return Theme::path('default-avatar-'.$sizenames[$size].'.png');
    }

    static function newSize(Profile $target, $width) {
        $width = intval($width);
        if ($width < 1 || $width > common_config('avatar', 'maxsize')) {
            // TRANS: An error message when avatar size is unreasonable
            throw new Exception(_m('Avatar size too large'));
        }
        // So far we only have square avatars and I don't have time to
        // rewrite support for non-square ones right now ;)
        $height = $width;

        $original = Avatar::getUploaded($target);

        $imagefile = new ImageFile(null, Avatar::path($original->filename));
        $filename = Avatar::filename($target->getID(), image_type_to_extension($imagefile->preferredType()),
                                     $width, common_timestamp());
        $imagefile->resizeTo(Avatar::path($filename), array('width'=>$width, 'height'=>$height));

        $scaled = clone($original);
        $scaled->original = false;
        $scaled->width = $width;
        $scaled->height = $height;
        $scaled->filename = $filename;
        $scaled->created = common_sql_now();

        if (!$scaled->insert()) {
            // TRANS: An error message when unable to insert avatar data into the db
            throw new Exception(_m('Could not insert new avatar data to database'));
        }

        // Return the new avatar object
        return $scaled;
    }
}


code:
<?php
/*
 * Laconica - a distributed open-source microblogging tool
 * Copyright (C) 2008, 2009, Control Yourself, Inc.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.     See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.     If not, see <http://www.gnu.org/licenses/>.
 */

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

/**
 * Table Definition for config
 */

class Config extends Managed_DataObject
{
    ###START_AUTOCODE
    /* the code below is auto generated do not remove the above tag */

    public $__table = 'config';                          // table name
    public $section;                         // varchar(32)  primary_key not_null
    public $setting;                         // varchar(32)  primary_key not_null
    public $value;                           // text

    /* the code above is auto generated do not remove the tag below */
    ###END_AUTOCODE

    public static function schemaDef()
    {
        return array(
            'fields' => array(
                'section' => array('type' => 'varchar', 'length' => 32, 'not null' => true, 'default' => '', 'description' => 'configuration section'),
                'setting' => array('type' => 'varchar', 'length' => 32, 'not null' => true, 'default' => '', 'description' => 'configuration setting'),
                'value' => array('type' => 'text', 'description' => 'configuration value'),
            ),
            'primary key' => array('section', 'setting'),
        );
    }

    const settingsKey = 'config:settings';

    static function loadSettings()
    {
        try {
            $settings = self::_getSettings();
            if (!empty($settings)) {
                self::_applySettings($settings);
            }
        } catch (Exception $e) {
            return;
        }
    }

    static function _getSettings()
    {
        $c = self::memcache();

        if (!empty($c)) {
            $settings = $c->get(Cache::key(self::settingsKey));
            if ($settings !== false) {
                return $settings;
            }
        }

        $settings = array();

        $config = new Config();

        $config->find();

        while ($config->fetch()) {
            $settings[] = array($config->section, $config->setting, $config->value);
        }

        $config->free();

        if (!empty($c)) {
            $c->set(Cache::key(self::settingsKey), $settings);
        }

        return $settings;
    }

    static function _applySettings($settings)
    {
        global $config;

        foreach ($settings as $s) {
            list($section, $setting, $value) = $s;
            $config[$section][$setting] = $value;
        }
    }

    function insert()
    {
        $result = parent::insert();
        if ($result) {
            Config::_blowSettingsCache();
        }
        return $result;
    }

    function delete($useWhere=false)
    {
        $result = parent::delete($useWhere);
        if ($result !== false) {
            Config::_blowSettingsCache();
        }
        return $result;
    }

    function update($dataObject=false)
    {
        $result = parent::update($dataObject);
        if ($result !== false) {
            Config::_blowSettingsCache();
        }
        return $result;
    }

    static function save($section, $setting, $value)
    {
        $result = null;

        $config = Config::pkeyGet(array('section' => $section,
                                        'setting' => $setting));

        if (!empty($config)) {
            $orig = clone($config);
            $config->value = $value;
            $result = $config->update($orig);
        } else {
            $config = new Config();

            $config->section = $section;
            $config->setting = $setting;
            $config->value   = $value;

            $result = $config->insert();
        }

        return $result;
    }

    function _blowSettingsCache()
    {
        $c = self::memcache();

        if (!empty($c)) {
            $c->delete(Cache::key(self::settingsKey));
        }
    }
}


code:
<?php
/**
 * Table Definition for confirm_address
 */

class Confirm_address extends Managed_DataObject
{
    public $__table = 'confirm_address';                 // table name
    public $code;                            // varchar(32)  primary_key not_null
    public $user_id;                         // int(4)   not_null
    public $address;                         // varchar(191)   not_null   not 255 because utf8mb4 takes more space
    public $address_extra;                   // varchar(191)   not_null   not 255 because utf8mb4 takes more space
    public $address_type;                    // varchar(8)   not_null
    public $claimed;                         // datetime()
    public $sent;                            // datetime()
    public $modified;                        // timestamp()   not_null default_CURRENT_TIMESTAMP

    public static function schemaDef()
    {
        return array(
            'fields' => array(
                'code' => array('type' => 'varchar', 'length' => 32, 'not null' => true, 'description' => 'good random code'),
                'user_id' => array('type' => 'int', 'default' => 0, 'description' => 'user who requested confirmation'),
                'address' => array('type' => 'varchar', 'length' => 191, 'not null' => true, 'description' => 'address (email, xmpp, SMS, etc.)'),
                'address_extra' => array('type' => 'varchar', 'length' => 191, 'description' => 'carrier ID, for SMS'),
                'address_type' => array('type' => 'varchar', 'length' => 8, 'not null' => true, 'description' => 'address type ("email", "xmpp", "sms")'),
                'claimed' => array('type' => 'datetime', 'description' => 'date this was claimed for queueing'),
                'sent' => array('type' => 'datetime', 'description' => 'date this was sent for queueing'),
                'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
            ),
            'primary key' => array('code'),
            'foreign keys' => array(
                'confirm_address_user_id_fkey' => array('user', array('user_id' => 'id')),
            ),
        );
    }

    static function getByAddress($address, $addressType)
    {
        $ca = new Confirm_address();

        $ca->address      = $address;
        $ca->address_type = $addressType;

        if (!$ca->find(true)) {
            throw new NoResultException($ca);
        }

        return $ca;
    }

    static function saveNew($user, $address, $addressType, $extra=null)
    {
        $ca = new Confirm_address();

        if (!empty($user)) {
            $ca->user_id = $user->id;
        }

        $ca->address       = $address;
        $ca->address_type  = $addressType;
        $ca->address_extra = $extra;
        $ca->code          = common_confirmation_code(64);

        $ca->insert();

        return $ca;
    }

    public function getAddress()
    {
        return $this->address;
    }

    public function getAddressType()
    {
        return $this->address_type;
    }

    public function getCode()
    {
        return $this->code;
    }

    public function getProfile()
    {
        return Profile::getByID($this->user_id);
    }

    public function getUrl()
    {
        return common_local_url('confirmaddress', array('code' => $this->code));
    }

    /**
     * Supply arguments in $args. Currently known args:
     *  headers     Array with headers (only used for email)
     *  nickname    How we great the user (defaults to nickname, but can be any string)
     *  sitename    Name we sign the email with (defaults to sitename, but can be any string)
     *  url         The confirmation address URL.
     */
    public function sendConfirmation(array $args=array())
    {
        common_debug('Sending confirmation URL for user '._ve($this->user_id).' using '._ve($this->address_type));

        $defaults = [
                     'headers'  => array(),
                     'nickname' => $this->getProfile()->getNickname(),
                     'sitename' => common_config('site', 'name'),
                     'url'      => $this->getUrl(),
                    ];
        foreach (array_keys($defaults) as $key) {
            if (!isset($args[$key])) {
                $args[$key] = $defaults[$key];
            }
        }

        switch ($this->getAddressType()) {
        case 'email':
            $this->sendEmailConfirmation($args);
            break;
        default:
            throw ServerException('Unable to handle confirm_address address type: '._ve($this->address_type));
        }
    }

    public function sendEmailConfirmation(array $args=array())
    {
        // TRANS: Subject for address confirmation email.
        $subject = _('Email address confirmation');

        // TRANS: Body for address confirmation email.
        // TRANS: %1$s is the addressed user's nickname, %2$s is the StatusNet sitename,
        // TRANS: %3$s is the URL to confirm at.
        $body = sprintf(_("Hey, %1\$s.\n\n".
                          "Someone just entered this email address on %2\$s.\n\n" .
                          "If it was you, and you want to confirm your entry, ".
                          "use the URL below:\n\n\t%3\$s\n\n" .
                          "If not, just ignore this message.\n\n".
                          "Thanks for your time, \n%2\$s\n"),
                        $args['nickname'],
                        $args['sitename'],
                        $args['url']);

        require_once(INSTALLDIR . '/lib/mail.php');
        return mail_to_user($this->getProfile()->getUser(), $subject, $body, $args['headers'], $this->getAddress());
    }

    public function delete($useWhere=false)
    {
        $result = parent::delete($useWhere);

        if ($result === false) {
            common_log_db_error($confirm, 'DELETE', __FILE__);
            // TRANS: Server error displayed when an address confirmation code deletion from the
            // TRANS: database fails in the contact address confirmation action.
            throw new ServerException(_('Could not delete address confirmation.'));
        }
        return $result;
    }
}


code:
<?php
/**
 * Table Definition for consumer
 */
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';

class Consumer extends Managed_DataObject
{
    ###START_AUTOCODE
    /* the code below is auto generated do not remove the above tag */

    public $__table = 'consumer';                        // table name
    public $consumer_key;                    // varchar(191)  primary_key not_null   not 255 because utf8mb4 takes more space
    public $consumer_secret;                 // varchar(191)   not_null   not 255 because utf8mb4 takes more space
    public $seed;                            // char(32)   not_null
    public $created;                         // datetime   not_null
    public $modified;                        // timestamp   not_null default_CURRENT_TIMESTAMP

    /* the code above is auto generated do not remove the tag below */
    ###END_AUTOCODE

    public static function schemaDef()
    {
        return array(
            'description' => 'OAuth consumer record',
            'fields' => array(
                'consumer_key' => array('type' => 'varchar', 'length' => 191, 'not null' => true, 'description' => 'unique identifier, root URL'),
                'consumer_secret' => array('type' => 'varchar', 'length' => 191, 'not null' => true, 'description' => 'secret value'),
                'seed' => array('type' => 'char', 'length' => 32, 'not null' => true, 'description' => 'seed for new tokens by this consumer'),

                'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
                'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
            ),
            'primary key' => array('consumer_key'),
        );
    }

    static function generateNew()
    {
        $cons = new Consumer();
        $rand = common_random_hexstr(16);

        $cons->seed            = $rand;
        $cons->consumer_key    = md5(time() + $rand);
        $cons->consumer_secret = md5(md5(time() + time() + $rand));
        $cons->created         = common_sql_now();

        return $cons;
    }

    /**
     * Delete a Consumer and related tokens and nonces
     *
     * XXX: Should this happen in an OAuthDataStore instead?
     *
     */
    function delete($useWhere=false)
    {
        // XXX: Is there any reason NOT to do this kind of cleanup?

        $this->_deleteTokens();
        $this->_deleteNonces();

        return parent::delete($useWhere);
    }

    function _deleteTokens()
    {
        $token = new Token();
        $token->consumer_key = $this->consumer_key;
        $token->delete();
    }

    function _deleteNonces()
    {
        $nonce = new Nonce();
        $nonce->consumer_key = $this->consumer_key;
        $nonce->delete();
    }
}


code:
<?php
/**
 * StatusNet, the distributed open-source microblogging tool
 *
 * Data class for Conversations
 *
 * 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  Data
 * @package   StatusNet
 * @author    Zach Copley <zach@status.net>
 * @author    Mikael Nordfeldth <mmn@hethane.se>
 * @copyright 2010 StatusNet Inc.
 * @copyright 2009-2014 Free Software Foundation, Inc http://www.fsf.org
 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 * @link      http://status.net/
 */

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

class Conversation extends Managed_DataObject
{
    public $__table = 'conversation';        // table name
    public $id;                              // int(4)  primary_key not_null auto_increment
    public $uri;                             // varchar(191)  unique_key   not 255 because utf8mb4 takes more space
    public $url;                             // varchar(191)  unique_key   not 255 because utf8mb4 takes more space
    public $created;                         // datetime   not_null
    public $modified;                        // timestamp   not_null default_CURRENT_TIMESTAMP

    public static function schemaDef()
    {
        return array(
            'fields' => array(
                'id' => array('type' => 'serial', 'not null' => true, 'description' => 'Unique identifier, (again) unrelated to notice id since 2016-01-06'),
                'uri' => array('type' => 'varchar', 'not null'=>true, 'length' => 191, 'description' => 'URI of the conversation'),
                'url' => array('type' => 'varchar', 'length' => 191, 'description' => 'Resolvable URL, preferrably remote (local can be generated on the fly)'),
                'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
                'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
            ),
            'primary key' => array('id'),
            'unique keys' => array(
                'conversation_uri_key' => array('uri'),
            ),
        );
    }

    static public function beforeSchemaUpdate()
    {
        $table = strtolower(get_called_class());
        $schema = Schema::get();
        $schemadef = $schema->getTableDef($table);

        // 2016-01-06 We have to make sure there is no conversation with id==0 since it will screw up auto increment resequencing
        if ($schemadef['fields']['id']['auto_increment']) {
            // since we already have auto incrementing ('serial') we can continue
            return;
        }

        // The conversation will be recreated in upgrade.php, which will
        // generate a new URI, but that's collateral damage for you.
        $conv = new Conversation();
        $conv->id = 0;
        if ($conv->find()) {
            while ($conv->fetch()) {
                // Since we have filtered on 0 this only deletes such entries
                // which I have been afraid wouldn't work, but apparently does!
                // (I thought it would act as null or something and find _all_ conversation entries)
                $conv->delete();
            }
        }
    }

    /**
     * Factory method for creating a new conversation.
     *
     * Use this for locally initiated conversations. Remote notices should
     * preferrably supply their own conversation URIs in the OStatus feed.
     *
     * @return Conversation the new conversation DO
     */
    static function create(ActivityContext $ctx=null, $created=null)
    {
        // Be aware that the Notice does not have an id yet since it's not inserted!
        $conv = new Conversation();
        $conv->created = $created ?: common_sql_now();
        if ($ctx instanceof ActivityContext) {
            $conv->uri = $ctx->conversation;
            $conv->url = $ctx->conversation_url;
        } else {
            $conv->uri = sprintf('%s%s=%s:%s=%s',
                             TagURI::mint(),
                             'objectType', 'thread',
                             'nonce', common_random_hexstr(8));
            $conv->url = null;  // locally generated Conversation objects don't get static URLs stored
        }
        // This insert throws exceptions on failure
        $conv->insert();

        return $conv;
    }

    static function noticeCount($id)
    {
        $keypart = sprintf('conversation:notice_count:%d', $id);

        $cnt = self::cacheGet($keypart);

        if ($cnt !== false) {
            return $cnt;
        }

        $notice               = new Notice();
        $notice->conversation = $id;
        $notice->whereAddIn('verb', array(ActivityVerb::POST, ActivityUtils::resolveUri(ActivityVerb::POST, true)), $notice->columnType('verb'));
        $cnt                  = $notice->count();

        self::cacheSet($keypart, $cnt);

        return $cnt;
    }

    static public function getUrlFromNotice(Notice $notice, $anchor=true)
    {
        $conv = Conversation::getByID($notice->conversation);
        return $conv->getUrl($anchor ? $notice->getID() : null);
    }

    public function getUri()
    {
        return $this->uri;
    }

    public function getUrl($noticeId=null)
    {
        // FIXME: the URL router should take notice-id as an argument...
        return common_local_url('conversation', array('id' => $this->getID())) .
                ($noticeId===null ? '' : "#notice-{$noticeId}");
    }

    // FIXME: ...will 500 ever be too low? Taken from ConversationAction::MAX_NOTICES
    public function getNotices(Profile $scoped=null, $offset=0, $limit=500)
    {
        $stream = new ConversationNoticeStream($this->getID(), $scoped);
        $notices = $stream->getNotices($offset, $limit);
        return $notices;
    }

    public function insert()
    {
        $result = parent::insert();
        if ($result === false) {
            common_log_db_error($this, 'INSERT', __FILE__);
            throw new ServerException(_('Failed to insert Conversation into database'));
        }
        return $result;
    }
}