Merge branch 'pgsql_support' into nightly

This commit is contained in:
Alexei Sorokin 2019-09-12 12:01:50 +03:00
commit 8f309bc768
121 changed files with 5854 additions and 5316 deletions

View File

@ -164,10 +164,9 @@ The ones that you may want to set are listed below for clarity.
* `database` (string, required, default null): a DSN (Data Source Name) for your
GNU social database. This is in the format
'protocol://username:password@hostname/databasename', where 'protocol' is '
mysql' or 'mysqli' (or possibly 'postgresql', if you really know what
you're doing), 'username' is the username, 'password' is the password,
and etc.
'protocol://username:password@hostname/databasename', where 'protocol' is
'mysqli' or 'pgsql' or 'mysql', 'username' is the username, 'password' is
the password, and etc.
* `ini_yourdbname` (string, default null): if your database is not named 'statusnet',
you'll need to set this to point to the location of the statusnet.ini file.
@ -178,12 +177,9 @@ The ones that you may want to set are listed below for clarity.
'MDB2' to use the other driver type for DB_DataObject, but note that it
breaks the OpenID libraries, which only support PEAR::DB.
* `quote_identifiers`(boolean, default false): Set this to true if you're using
postgresql.
* `type` (enum["mysql", "postgresql"], default 'mysql'): Used for certain
database-specific optimization code. Assumes mysql if not set. MySQL also
covers MySQLi and MariaDB.
* `type` (enum["mysql", "pgsql"], default 'mysql'): Used for certain
database-specific optimization code. Assumes mysql if not set. "mysql"
covers MariaDB, Oracle MySQL, mysqli or otherwise.
* `mirror` (array, default null): you can set this to an array of DSNs, in the
format of the above 'database' value. If it's set, certain read-only

View File

@ -1,55 +1,45 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* StatusNet, the distributed open-source microblogging tool
*
* Show the newest groups
*
* PHP version 5
*
* LICENCE: This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category API
* @package StatusNet
* @package GNUsocial
* @author Craig Andrews <candrews@integralblue.com>
* @author Evan Prodromou <evan@status.net>
* @author Jeffery To <jeffery.to@gmail.com>
* @author Zach Copley <zach@status.net>
* @copyright 2009 StatusNet, Inc.
* @copyright 2009 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/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('STATUSNET')) {
exit(1);
}
defined('GNUSOCIAL') || die();
/**
* Returns of the lastest 20 groups for the site
*
* @category API
* @package StatusNet
* @author Craig Andrews <candrews@integralblue.com>
* @author Evan Prodromou <evan@status.net>
* @author Jeffery To <jeffery.to@gmail.com>
* @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/
* @copyright 2009 StatusNet, Inc.
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
class ApiGroupListAllAction extends ApiPrivateAuthAction
{
var $groups = null;
public $groups = null;
/**
* Take arguments for running
@ -58,7 +48,7 @@ class ApiGroupListAllAction extends ApiPrivateAuthAction
*
* @return boolean success flag
*/
function prepare(array $args = array())
public function prepare(array $args = [])
{
parent::prepare($args);
@ -77,7 +67,7 @@ class ApiGroupListAllAction extends ApiPrivateAuthAction
*
* @return void
*/
function handle()
public function handle()
{
parent::handle();
@ -90,7 +80,7 @@ class ApiGroupListAllAction extends ApiPrivateAuthAction
// TRANS: Message is used as a subtitle when listing the latest 20 groups. %s is a site name.
$subtitle = sprintf(_("groups on %s"), $sitename);
switch($this->format) {
switch ($this->format) {
case 'xml':
$this->showXmlGroups($this->groups);
break;
@ -128,21 +118,20 @@ class ApiGroupListAllAction extends ApiPrivateAuthAction
*
* @return array groups
*/
function getGroups()
public function getGroups()
{
$qry = 'SELECT user_group.* '.
'from user_group join local_group on user_group.id = local_group.group_id '.
'order by created desc ';
$offset = intval($this->page - 1) * intval($this->count);
$limit = intval($this->count);
if (common_config('db', 'type') == 'pgsql') {
$qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
} else {
$qry .= ' LIMIT ' . $offset . ', ' . $limit;
}
$group = new User_group();
$group->query($qry);
$offset = intval($this->page - 1) * intval($this->count);
$limit = intval($this->count);
$group->query(
'SELECT user_group.* '.
'FROM user_group INNER JOIN local_group ' .
'ON user_group.id = local_group.group_id '.
'ORDER BY created DESC ' .
'LIMIT ' . $limit . ' OFFSET ' . $offset
);
$groups = array();
while ($group->fetch()) {
@ -159,7 +148,7 @@ class ApiGroupListAllAction extends ApiPrivateAuthAction
*
* @return boolean true
*/
function isReadOnly($args)
public function isReadOnly($args)
{
return true;
}
@ -169,7 +158,7 @@ class ApiGroupListAllAction extends ApiPrivateAuthAction
*
* @return string datestamp of the site's latest group
*/
function lastModified()
public function lastModified()
{
if (!empty($this->groups) && (count($this->groups) > 0)) {
return strtotime($this->groups[0]->created);
@ -186,10 +175,9 @@ class ApiGroupListAllAction extends ApiPrivateAuthAction
*
* @return string etag
*/
function etag()
public function etag()
{
if (!empty($this->groups) && (count($this->groups) > 0)) {
$last = count($this->groups) - 1;
return '"' . implode(

View File

@ -1,48 +1,40 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* StatusNet, the distributed open-source microblogging tool
*
* Settings for email
*
* 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
* @package GNUsocial
* @author Evan Prodromou <evan@status.net>
* @author Zach Copley <zach@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/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('GNUSOCIAL')) { exit(1); }
defined('GNUSOCIAL') || die();
/**
* Settings for email
*
* @category Settings
* @package StatusNet
* @author Evan Prodromou <evan@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/
* @copyright 2008-2009 StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*
* @see Widget
*/
class EmailsettingsAction extends SettingsAction
{
/**
@ -50,7 +42,7 @@ class EmailsettingsAction extends SettingsAction
*
* @return string Title of the page
*/
function title()
public function title()
{
// TRANS: Title for e-mail settings.
return _('Email settings');
@ -61,7 +53,7 @@ class EmailsettingsAction extends SettingsAction
*
* @return instructions for use
*/
function getInstructions()
public function getInstructions()
{
// XXX: For consistency of parameters in messages, this should be a
// regular parameters, replaced with sprintf().
@ -70,7 +62,7 @@ class EmailsettingsAction extends SettingsAction
return _('Manage how you get email from %%site.name%%.');
}
function showScripts()
public function showScripts()
{
parent::showScripts();
$this->script('emailsettings.js');
@ -85,7 +77,7 @@ class EmailsettingsAction extends SettingsAction
*
* @return void
*/
function showContent()
public function showContent()
{
$user = $this->scoped->getUser();
@ -106,50 +98,58 @@ class EmailsettingsAction extends SettingsAction
$this->element('p', array('class' => 'form_note'), _('Current confirmed email address.'));
$this->hidden('email', $user->email);
// TRANS: Button label to remove a confirmed e-mail address.
$this->submit('remove', _m('BUTTON','Remove'));
$this->submit('remove', _m('BUTTON', 'Remove'));
} else {
try {
$confirm = $this->getConfirmation();
$this->element('p', array('id' => 'form_unconfirmed'), $confirm->address);
$this->element('p', array('class' => 'form_note'),
// TRANS: Form note in e-mail settings form.
_('Awaiting confirmation on this address. '.
'Check your inbox (and spam box!) for a message '.
'with further instructions.'));
$this->element(
'p',
['class' => 'form_note'],
// TRANS: Form note in e-mail settings form.
_('Awaiting confirmation on this address. '.
'Check your inbox (and spam box!) for a message '.
'with further instructions.')
);
$this->hidden('email', $confirm->address);
// TRANS: Button label to cancel an e-mail address confirmation procedure.
$this->submit('cancel', _m('BUTTON','Cancel'));
$this->submit('cancel', _m('BUTTON', 'Cancel'));
} catch (NoResultException $e) {
$this->elementStart('ul', 'form_data');
$this->elementStart('li');
// TRANS: Field label for e-mail address input in e-mail settings form.
$this->input('email', _('Email address'),
$this->trimmed('email') ?: null,
// TRANS: Instructions for e-mail address input form. Do not translate
// TRANS: "example.org". It is one of the domain names reserved for
// TRANS: use in examples by http://www.rfc-editor.org/rfc/rfc2606.txt.
// TRANS: Any other domain may be owned by a legitimate person or
// TRANS: organization.
_('Email address, like "UserName@example.org"'));
$this->input(
'email',
_('Email address'),
$this->trimmed('email') ?: null,
// TRANS: Instructions for e-mail address input form. Do not translate
// TRANS: "example.org". It is one of the domain names reserved for
// TRANS: use in examples by http://www.rfc-editor.org/rfc/rfc2606.txt.
// TRANS: Any other domain may be owned by a legitimate person or
// TRANS: organization.
_('Email address, like "UserName@example.org"')
);
$this->elementEnd('li');
$this->elementEnd('ul');
// TRANS: Button label for adding an e-mail address in e-mail settings form.
$this->submit('add', _m('BUTTON','Add'));
$this->submit('add', _m('BUTTON', 'Add'));
}
}
$this->elementEnd('fieldset');
if (common_config('emailpost', 'enabled') && $user->email) {
if (common_config('emailpost', 'enabled') && $user->email) {
$this->elementStart('fieldset', array('id' => 'settings_email_incoming'));
// TRANS: Form legend for incoming e-mail settings form.
$this->element('legend', null, _('Incoming email'));
$this->elementStart('ul', 'form_data');
$this->elementStart('li');
$this->checkbox('emailpost',
// TRANS: Checkbox label in e-mail preferences form.
_('I want to post notices by email.'),
$user->emailpost);
$this->checkbox(
'emailpost',
// TRANS: Checkbox label in e-mail preferences form.
_('I want to post notices by email.'),
$user->emailpost
);
$this->elementEnd('li');
$this->elementEnd('ul');
@ -168,12 +168,15 @@ class EmailsettingsAction extends SettingsAction
$this->element('span', 'address', $user->incomingemail);
// @todo XXX: Looks a little awkward in the UI.
// Something like "xxxx@identi.ca Send email ..". Needs improvement.
$this->element('span', 'input_instructions',
// TRANS: Form instructions for incoming e-mail form in e-mail settings.
_('Send email to this address to post new notices.'));
$this->element(
'span',
'input_instructions',
// TRANS: Form instructions for incoming e-mail form in e-mail settings.
_('Send email to this address to post new notices.')
);
$this->elementEnd('p');
// TRANS: Button label for removing a set sender e-mail address to post notices from.
$this->submit('removeincoming', _m('BUTTON','Remove'));
$this->submit('removeincoming', _m('BUTTON', 'Remove'));
}
$this->elementStart('p');
@ -189,7 +192,7 @@ class EmailsettingsAction extends SettingsAction
$this->elementEnd('p');
// TRANS: Button label for adding an e-mail address to send notices from.
$this->submit('newincoming', _m('BUTTON','New'));
$this->submit('newincoming', _m('BUTTON', 'New'));
$this->elementEnd('div'); // div#emailincoming
@ -204,34 +207,42 @@ class EmailsettingsAction extends SettingsAction
if (Event::handle('StartEmailFormData', array($this, $this->scoped))) {
$this->elementStart('li');
$this->checkbox('emailnotifysub',
// TRANS: Checkbox label in e-mail preferences form.
_('Send me notices of new subscriptions through email.'),
$user->emailnotifysub);
$this->checkbox(
'emailnotifysub',
// TRANS: Checkbox label in e-mail preferences form.
_('Send me notices of new subscriptions through email.'),
$user->emailnotifysub
);
$this->elementEnd('li');
$this->elementStart('li');
$this->checkbox('emailnotifymsg',
// TRANS: Checkbox label in e-mail preferences form.
_('Send me email when someone sends me a private message.'),
$user->emailnotifymsg);
$this->checkbox(
'emailnotifymsg',
// TRANS: Checkbox label in e-mail preferences form.
_('Send me email when someone sends me a private message.'),
$user->emailnotifymsg
);
$this->elementEnd('li');
$this->elementStart('li');
$this->checkbox('emailnotifyattn',
// TRANS: Checkbox label in e-mail preferences form.
_('Send me email when someone sends me an "@-reply".'),
$user->emailnotifyattn);
$this->checkbox(
'emailnotifyattn',
// TRANS: Checkbox label in e-mail preferences form.
_('Send me email when someone sends me an "@-reply".'),
$user->emailnotifyattn
);
$this->elementEnd('li');
$this->elementStart('li');
$this->checkbox('emailnotifynudge',
// TRANS: Checkbox label in e-mail preferences form.
_('Allow friends to nudge me and send me an email.'),
$user->emailnotifynudge);
$this->checkbox(
'emailnotifynudge',
// TRANS: Checkbox label in e-mail preferences form.
_('Allow friends to nudge me and send me an email.'),
$user->emailnotifynudge
);
$this->elementEnd('li');
Event::handle('EndEmailFormData', array($this, $this->scoped));
}
$this->elementEnd('ul');
// TRANS: Button label to save e-mail preferences.
$this->submit('save', _m('BUTTON','Save'));
$this->submit('save', _m('BUTTON', 'Save'));
$this->elementEnd('fieldset');
$this->elementEnd('fieldset');
$this->elementEnd('form');
@ -242,7 +253,7 @@ class EmailsettingsAction extends SettingsAction
*
* @return Confirm_address Email address confirmation for user, or null
*/
function getConfirmation()
public function getConfirmation()
{
$confirm = new Confirm_address();
@ -260,15 +271,15 @@ class EmailsettingsAction extends SettingsAction
{
if ($this->arg('save')) {
return $this->savePreferences();
} else if ($this->arg('add')) {
} elseif ($this->arg('add')) {
return $this->addAddress();
} else if ($this->arg('cancel')) {
} elseif ($this->arg('cancel')) {
return $this->cancelConfirmation();
} else if ($this->arg('remove')) {
} elseif ($this->arg('remove')) {
return $this->removeAddress();
} else if ($this->arg('removeincoming')) {
} elseif ($this->arg('removeincoming')) {
return $this->removeIncoming();
} else if ($this->arg('newincoming')) {
} elseif ($this->arg('newincoming')) {
return $this->newIncoming();
}
@ -281,14 +292,14 @@ class EmailsettingsAction extends SettingsAction
*
* @return void
*/
function savePreferences()
public function savePreferences()
{
if (Event::handle('StartEmailSaveForm', array($this, $this->scoped))) {
$emailnotifysub = $this->booleanintstring('emailnotifysub');
$emailnotifymsg = $this->booleanintstring('emailnotifymsg');
$emailnotifynudge = $this->booleanintstring('emailnotifynudge');
$emailnotifyattn = $this->booleanintstring('emailnotifyattn');
$emailpost = $this->booleanintstring('emailpost');
$emailnotifysub = $this->boolean('emailnotifysub');
$emailnotifymsg = $this->boolean('emailnotifymsg');
$emailnotifynudge = $this->boolean('emailnotifynudge');
$emailnotifyattn = $this->boolean('emailnotifyattn');
$emailpost = $this->boolean('emailpost');
$user = $this->scoped->getUser();
$user->query('BEGIN');
@ -322,7 +333,7 @@ class EmailsettingsAction extends SettingsAction
*
* @return void
*/
function addAddress()
public function addAddress()
{
$user = $this->scoped->getUser();
@ -344,16 +355,15 @@ class EmailsettingsAction extends SettingsAction
if (!Validate::email($email, common_config('email', 'check_domain'))) {
// TRANS: Message given saving e-mail address that not valid.
throw new ClientException(_('Not a valid email address.'));
} else if ($user->email == $email) {
} elseif ($user->email === $email) {
// TRANS: Message given saving e-mail address that is already set.
throw new ClientException(_('That is already your email address.'));
} else if ($this->emailExists($email)) {
} elseif ($this->emailExists($email)) {
// TRANS: Message given saving e-mail address that is already set for another user.
throw new ClientException(_('That email address already belongs to another user.'));
}
if (Event::handle('StartAddEmailAddress', array($user, $email))) {
$confirm = new Confirm_address();
$confirm->address = $email;
@ -385,7 +395,7 @@ class EmailsettingsAction extends SettingsAction
*
* @return void
*/
function cancelConfirmation()
public function cancelConfirmation()
{
$email = $this->trimmed('email');
@ -411,7 +421,7 @@ class EmailsettingsAction extends SettingsAction
*
* @return void
*/
function removeAddress()
public function removeAddress()
{
$user = common_current_user();
@ -425,7 +435,7 @@ class EmailsettingsAction extends SettingsAction
}
$original = clone($user);
$user->email = null;
$user->email = DB_DataObject_Cast::sql('NULL');
// Throws exception on failure. Also performs it within a transaction.
$user->updateWithKeys($original);
@ -438,7 +448,7 @@ class EmailsettingsAction extends SettingsAction
*
* @return void
*/
function removeIncoming()
public function removeIncoming()
{
$user = common_current_user();
@ -448,8 +458,8 @@ class EmailsettingsAction extends SettingsAction
}
$orig = clone($user);
$user->incomingemail = null;
$user->emailpost = 0;
$user->incomingemail = DB_DataObject_Cast::sql('NULL');
$user->emailpost = false;
// Throws exception on failure. Also performs it within a transaction.
$user->updateWithKeys($orig);
@ -462,12 +472,12 @@ class EmailsettingsAction extends SettingsAction
*
* @return void
*/
function newIncoming()
public function newIncoming()
{
$user = common_current_user();
$orig = clone($user);
$user->incomingemail = mail_new_incoming_address();
$user->emailpost = 1;
$user->emailpost = true;
// Throws exception on failure. Also performs it within a transaction.
$user->updateWithKeys($orig);
@ -485,7 +495,7 @@ class EmailsettingsAction extends SettingsAction
* @return boolean Whether the email already exists.
*/
function emailExists($email)
public function emailExists($email)
{
$user = common_current_user();

View File

@ -1,36 +1,31 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* StatusNet, the distributed open-source microblogging tool
*
* List of featured users
*
* 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
* @package GNUsocial
* @author Zach Copley <zach@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/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
defined('GNUSOCIAL') || die();
require_once INSTALLDIR . '/lib/profile/profilelist.php';
require_once INSTALLDIR . '/lib/groups/publicgroupnav.php';
@ -38,23 +33,19 @@ require_once INSTALLDIR . '/lib/groups/publicgroupnav.php';
/**
* List of featured users
*
* @category Public
* @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/
* @copyright 2008-2009 StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
class FeaturedAction extends Action
{
var $page = null;
public $page = null;
function isReadOnly($args)
public function isReadOnly($args)
{
return true;
}
function prepare(array $args = array())
public function prepare(array $args = [])
{
parent::prepare($args);
$this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1;
@ -62,7 +53,7 @@ class FeaturedAction extends Action
return true;
}
function title()
public function title()
{
if ($this->page == 1) {
// TRANS: Page title for first page of featured users.
@ -74,14 +65,14 @@ class FeaturedAction extends Action
}
}
function handle()
public function handle()
{
parent::handle();
$this->showPage();
}
function showPageNotice()
public function showPageNotice()
{
$instr = $this->getInstructions();
$output = common_markup_to_html($instr);
@ -90,14 +81,16 @@ class FeaturedAction extends Action
$this->elementEnd('div');
}
function getInstructions()
public function getInstructions()
{
// TRANS: Description on page displaying featured users.
return sprintf(_('A selection of some great users on %s.'),
common_config('site', 'name'));
return sprintf(
_('A selection of some great users on %s.'),
common_config('site', 'name')
);
}
function showContent()
public function showContent()
{
// XXX: Note I'm doing it this two-stage way because a raw query
// with a JOIN was *not* working. --Zach
@ -105,7 +98,6 @@ class FeaturedAction extends Action
$featured_nicks = common_config('nickname', 'featured');
if (count($featured_nicks) > 0) {
$quoted = array();
foreach ($featured_nicks as $nick) {
@ -115,7 +107,7 @@ class FeaturedAction extends Action
$user = new User;
$user->whereAdd(sprintf('nickname IN (%s)', implode(',', $quoted)));
$user->limit(($this->page - 1) * PROFILES_PER_PAGE, PROFILES_PER_PAGE + 1);
$user->orderBy(common_database_tablename('user') .'.nickname ASC');
$user->orderBy($user->escapedTableName() . '.nickname ASC');
$user->find();
@ -138,8 +130,12 @@ class FeaturedAction extends Action
$profile->free();
$this->pagination($this->page > 1, $cnt > PROFILES_PER_PAGE,
$this->page, 'featured');
$this->pagination(
$this->page > 1,
$cnt > PROFILES_PER_PAGE,
$this->page,
'featured'
);
}
}
}

View File

@ -1,50 +1,41 @@
<?php
/**
* Make another user an admin of a group
*
* PHP version 5
*
* @category Action
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/
*
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2008, 2009, StatusNet, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* Make another user an admin of a group
*
* @category Action
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/
* @category Action
* @package GNUsocial
* @author Evan Prodromou <evan@status.net>
* @copyright 2008, 2009 StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
defined('GNUSOCIAL') || die();
/**
* Make another user an admin of a group
*
* @copyright 2008, 2009 StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
class MakeadminAction extends RedirectingAction
{
var $profile = null;
var $group = null;
public $profile = null;
public $group = null;
/**
* Take arguments for running
@ -54,7 +45,7 @@ class MakeadminAction extends RedirectingAction
* @return boolean success flag
*/
function prepare(array $args = array())
public function prepare(array $args = [])
{
parent::prepare($args);
if (!common_logged_in()) {
@ -95,10 +86,14 @@ class MakeadminAction extends RedirectingAction
if ($this->profile->isAdmin($this->group)) {
// TRANS: Client error displayed when trying to make another user admin on the Make Admin page who already is admin.
// TRANS: %1$s is the user that is already admin, %2$s is the group user is already admin for.
$this->clientError(sprintf(_('%1$s is already an admin for group "%2$s".'),
$this->profile->getBestName(),
$this->group->getBestName()),
401);
$this->clientError(
sprintf(
_('%1$s is already an admin for group "%2$s".'),
$this->profile->getBestName(),
$this->group->getBestName()
),
401
);
}
return true;
}
@ -111,7 +106,7 @@ class MakeadminAction extends RedirectingAction
* @return void
*/
function handle()
public function handle()
{
parent::handle();
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
@ -125,7 +120,7 @@ class MakeadminAction extends RedirectingAction
* @return void
*/
function makeAdmin()
public function makeAdmin()
{
$member = Group_member::pkeyGet(array('group_id' => $this->group->id,
'profile_id' => $this->profile->id));
@ -134,14 +129,16 @@ class MakeadminAction extends RedirectingAction
// TRANS: Server error displayed when trying to make another user admin on the Make Admin page fails
// TRANS: because the group membership record could not be gotten.
// TRANS: %1$s is the to be admin user, %2$s is the group user should be admin for.
$this->serverError(_('Can\'t get membership record for %1$s in group %2$s.'),
$this->profile->getBestName(),
$this->group->getBestName());
$this->serverError(
_('Can\'t get membership record for %1$s in group %2$s.'),
$this->profile->getBestName(),
$this->group->getBestName()
);
}
$orig = clone($member);
$member->is_admin = 1;
$member->is_admin = true;
$result = $member->update($orig);
@ -150,9 +147,11 @@ class MakeadminAction extends RedirectingAction
// TRANS: Server error displayed when trying to make another user admin on the Make Admin page fails
// TRANS: because the group adminship record coud not be saved properly.
// TRANS: %1$s is the to be admin user, %2$s is the group user is already admin for.
$this->serverError(_('Can\'t make %1$s an admin for group %2$s.'),
$this->profile->getBestName(),
$this->group->getBestName());
$this->serverError(
_('Can\'t make %1$s an admin for group %2$s.'),
$this->profile->getBestName(),
$this->group->getBestName()
);
}
$this->returnToPrevious();
@ -161,13 +160,14 @@ class MakeadminAction extends RedirectingAction
/**
* If we reached this form without returnto arguments, default to
* the top of the group's member list.
*
*
* @return string URL
*/
function defaultReturnTo()
public function defaultReturnTo()
{
return common_local_url('groupmembers',
array('nickname' => $this->group->nickname));
return common_local_url(
'groupmembers',
['nickname' => $this->group->nickname]
);
}
}

View File

@ -1,46 +1,38 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* StatusNet, the distributed open-source microblogging tool
*
* Change profile 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
* @package GNUsocial
* @author Evan Prodromou <evan@status.net>
* @author Zach Copley <zach@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/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('GNUSOCIAL')) { exit(1); }
defined('GNUSOCIAL') || die();
/**
* Change profile settings
*
* @category Settings
* @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/
* @copyright 2008-2009 StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
class ProfilesettingsAction extends SettingsAction
{
@ -49,7 +41,7 @@ class ProfilesettingsAction extends SettingsAction
*
* @return string Title of the page
*/
function title()
public function title()
{
// TRANS: Page title for profile settings.
return _('Profile settings');
@ -60,14 +52,14 @@ class ProfilesettingsAction extends SettingsAction
*
* @return instructions for use
*/
function getInstructions()
public function getInstructions()
{
// TRANS: Usage instructions for profile settings.
return _('You can update your personal profile info here '.
'so people know more about you.');
}
function showScripts()
public function showScripts()
{
parent::showScripts();
$this->autofocus('fullname');
@ -80,7 +72,7 @@ class ProfilesettingsAction extends SettingsAction
*
* @return void
*/
function showContent()
public function showContent()
{
$user = $this->scoped->getUser();
@ -98,29 +90,40 @@ class ProfilesettingsAction extends SettingsAction
if (Event::handle('StartProfileFormData', array($this))) {
$this->elementStart('li');
// TRANS: Field label in form for profile settings.
$this->input('nickname', _('Nickname'),
$this->trimmed('nickname') ?: $this->scoped->getNickname(),
// TRANS: Tooltip for field label in form for profile settings.
_('1-64 lowercase letters or numbers, no punctuation or spaces.'),
null, false, // "name" (will be set to id), then "required"
!common_config('profile', 'changenick')
? array('disabled' => 'disabled', 'placeholder' => null)
: array('placeholder' => null));
$this->input(
'nickname',
_('Nickname'),
$this->trimmed('nickname') ?: $this->scoped->getNickname(),
// TRANS: Tooltip for field label in form for profile settings.
_('1-64 lowercase letters or numbers, no punctuation or spaces.'),
null,
false, // "name" (will be set to id), then "required"
(common_config('profile', 'changenick')
? ['placeholder' => null]
: ['disabled' => 'disabled', 'placeholder' => null])
);
$this->elementEnd('li');
$this->elementStart('li');
// TRANS: Field label in form for profile settings.
$this->input('fullname', _('Full name'),
$this->trimmed('fullname') ?: $this->scoped->getFullname(),
// TRANS: Instructions for full name text field on profile settings
_('A full name is required, if empty it will be set to your nickname.'),
null, true);
$this->input(
'fullname',
_('Full name'),
$this->trimmed('fullname') ?: $this->scoped->getFullname(),
// TRANS: Instructions for full name text field on profile settings
_('A full name is required, if empty it will be set to your nickname.'),
null,
true
);
$this->elementEnd('li');
$this->elementStart('li');
// TRANS: Field label in form for profile settings.
$this->input('homepage', _('Homepage'),
$this->trimmed('homepage') ?: $this->scoped->getHomepage(),
// TRANS: Tooltip for field label in form for profile settings.
_('URL of your homepage, blog, or profile on another site.'));
$this->input(
'homepage',
_('Homepage'),
$this->trimmed('homepage') ?: $this->scoped->getHomepage(),
// TRANS: Tooltip for field label in form for profile settings.
_('URL of your homepage, blog, or profile on another site.')
);
$this->elementEnd('li');
$this->elementStart('li');
$maxBio = Profile::maxBio();
@ -128,97 +131,129 @@ class ProfilesettingsAction extends SettingsAction
// TRANS: Tooltip for field label in form for profile settings. Plural
// TRANS: is decided by the number of characters available for the
// TRANS: biography (%d).
$bioInstr = sprintf(_m('Describe yourself and your interests in %d character.',
'Describe yourself and your interests in %d characters.',
$maxBio),
$maxBio);
$bioInstr = sprintf(
_m('Describe yourself and your interests in %d character.',
'Describe yourself and your interests in %d characters.',
$maxBio),
$maxBio
);
} else {
// TRANS: Tooltip for field label in form for profile settings.
$bioInstr = _('Describe yourself and your interests.');
}
// TRANS: Text area label in form for profile settings where users can provide
// TRANS: their biography.
$this->textarea('bio', _('Bio'),
$this->trimmed('bio') ?: $this->scoped->getDescription(),
$bioInstr);
$this->textarea(
'bio',
_('Bio'),
($this->trimmed('bio') ?: $this->scoped->getDescription()),
$bioInstr
);
$this->elementEnd('li');
$this->elementStart('li');
// TRANS: Field label in form for profile settings.
$this->input('location', _('Location'),
$this->trimmed('location') ?: $this->scoped->location,
// TRANS: Tooltip for field label in form for profile settings.
_('Where you are, like "City, State (or Region), Country".'));
$this->input(
'location',
_('Location'),
($this->trimmed('location') ?: $this->scoped->location),
// TRANS: Tooltip for field label in form for profile settings.
_('Where you are, like "City, State (or Region), Country".')
);
$this->elementEnd('li');
if (common_config('location', 'share') == 'user') {
$this->elementStart('li');
// TRANS: Checkbox label in form for profile settings.
$this->checkbox('sharelocation', _('Share my current location when posting notices'),
($this->arg('sharelocation')) ?
$this->boolean('sharelocation') : $this->scoped->shareLocation());
$this->checkbox(
'sharelocation',
_('Share my current location when posting notices'),
($this->arg('sharelocation') ?
$this->boolean('sharelocation') : $this->scoped->shareLocation())
);
$this->elementEnd('li');
}
Event::handle('EndProfileFormData', array($this));
$this->elementStart('li');
// TRANS: Field label in form for profile settings.
$this->input('tags', _('Tags'),
$this->trimmed('tags') ?: implode(' ', Profile_tag::getSelfTagsArray($this->scoped)),
// TRANS: Tooltip for field label in form for profile settings.
_('Tags for yourself (letters, numbers, -, ., and _), comma- or space- separated.'));
$this->input(
'tags',
_('Tags'),
($this->trimmed('tags') ?: implode(' ', Profile_tag::getSelfTagsArray($this->scoped))),
// TRANS: Tooltip for field label in form for profile settings.
_('Tags for yourself (letters, numbers, -, ., and _), comma- or space- separated.')
);
$this->elementEnd('li');
$this->elementStart('li');
$language = common_language();
// TRANS: Dropdownlist label in form for profile settings.
$this->dropdown('language', _('Language'),
// TRANS: Tooltip for dropdown list label in form for profile settings.
get_nice_language_list(), _('Preferred language.'),
false, $language);
$this->dropdown(
'language',
_('Language'),
// TRANS: Tooltip for dropdown list label in form for profile settings.
get_nice_language_list(),
_('Preferred language.'),
false,
$language
);
$this->elementEnd('li');
$timezone = common_timezone();
$timezones = array();
foreach(DateTimeZone::listIdentifiers() as $k => $v) {
foreach (DateTimeZone::listIdentifiers() as $k => $v) {
$timezones[$v] = $v;
}
$this->elementStart('li');
// TRANS: Dropdownlist label in form for profile settings.
$this->dropdown('timezone', _('Timezone'),
// TRANS: Tooltip for dropdown list label in form for profile settings.
$timezones, _('What timezone are you normally in?'),
true, $timezone);
$this->dropdown(
'timezone',
_('Timezone'),
// TRANS: Tooltip for dropdown list label in form for profile settings.
$timezones,
_('What timezone are you normally in?'),
true,
$timezone
);
$this->elementEnd('li');
$this->elementStart('li');
$this->checkbox('autosubscribe',
// TRANS: Checkbox label in form for profile settings.
_('Automatically subscribe to whoever '.
'subscribes to me (best for non-humans)'),
($this->arg('autosubscribe')) ?
$this->boolean('autosubscribe') : $user->autosubscribe);
$this->checkbox(
'autosubscribe',
// TRANS: Checkbox label in form for profile settings.
_('Automatically subscribe to whoever '.
'subscribes to me (best for non-humans)'),
($this->arg('autosubscribe') ?
$this->boolean('autosubscribe') : $user->autosubscribe)
);
$this->elementEnd('li');
$this->elementStart('li');
$this->dropdown('subscribe_policy',
// TRANS: Dropdown field label on profile settings, for what policies to apply when someone else tries to subscribe to your updates.
_('Subscription policy'),
// TRANS: Dropdown field option for following policy.
array(User::SUBSCRIBE_POLICY_OPEN => _('Let anyone follow me'),
// TRANS: Dropdown field option for following policy.
User::SUBSCRIBE_POLICY_MODERATE => _('Ask me first')),
// TRANS: Dropdown field title on group edit form.
_('Whether other users need your permission to follow your updates.'),
false,
(empty($user->subscribe_policy)) ? User::SUBSCRIBE_POLICY_OPEN : $user->subscribe_policy);
$this->dropdown(
'subscribe_policy',
// TRANS: Dropdown field label on profile settings, for what policies to apply when someone else tries to subscribe to your updates.
_('Subscription policy'),
[
// TRANS: Dropdown field option for following policy.
User::SUBSCRIBE_POLICY_OPEN => _('Let anyone follow me'),
// TRANS: Dropdown field option for following policy.
User::SUBSCRIBE_POLICY_MODERATE => _('Ask me first'),
],
// TRANS: Dropdown field title on group edit form.
_('Whether other users need your permission to follow your updates.'),
false,
(empty($user->subscribe_policy) ? User::SUBSCRIBE_POLICY_OPEN : $user->subscribe_policy)
);
$this->elementEnd('li');
}
if (common_config('profile', 'allowprivate') || $user->private_stream) {
$this->elementStart('li');
$this->checkbox('private_stream',
// TRANS: Checkbox label in profile settings.
_('Make updates visible only to my followers'),
($this->arg('private_stream')) ?
$this->boolean('private_stream') : $user->private_stream);
$this->checkbox(
'private_stream',
// TRANS: Checkbox label in profile settings.
_('Make updates visible only to my followers'),
($this->arg('private_stream') ?
$this->boolean('private_stream') : $user->private_stream)
);
$this->elementEnd('li');
}
$this->elementEnd('ul');
// TRANS: Button to save input in profile settings.
$this->submit('save', _m('BUTTON','Save'));
$this->submit('save', _m('BUTTON', 'Save'));
$this->elementEnd('fieldset');
$this->elementEnd('form');
@ -255,7 +290,7 @@ class ProfilesettingsAction extends SettingsAction
$homepage = $this->trimmed('homepage');
$bio = $this->trimmed('bio');
$location = $this->trimmed('location');
$autosubscribe = $this->booleanintstring('autosubscribe');
$autosubscribe = $this->boolean('autosubscribe');
$subscribe_policy = $this->trimmed('subscribe_policy');
$language = $this->trimmed('language');
$timezone = $this->trimmed('timezone');
@ -266,24 +301,26 @@ class ProfilesettingsAction extends SettingsAction
!common_valid_http_url($homepage)) {
// TRANS: Validation error in form for profile settings.
throw new ClientException(_('Homepage is not a valid URL.'));
} else if (!is_null($fullname) && mb_strlen($fullname) > 191) {
} elseif (!is_null($fullname) && mb_strlen($fullname) > 191) {
// TRANS: Validation error in form for profile settings.
throw new ClientException(_('Full name is too long (maximum 191 characters).'));
} else if (Profile::bioTooLong($bio)) {
} elseif (Profile::bioTooLong($bio)) {
// TRANS: Validation error in form for profile settings.
// TRANS: Plural form is used based on the maximum number of allowed
// TRANS: characters for the biography (%d).
throw new ClientException(sprintf(_m('Bio is too long (maximum %d character).',
'Bio is too long (maximum %d characters).',
Profile::maxBio()),
Profile::maxBio()));
} else if (!is_null($location) && mb_strlen($location) > 191) {
throw new ClientException(sprintf(
_m('Bio is too long (maximum %d character).',
'Bio is too long (maximum %d characters).',
Profile::maxBio()),
Profile::maxBio()
));
} elseif (!is_null($location) && mb_strlen($location) > 191) {
// TRANS: Validation error in form for profile settings.
throw new ClientException(_('Location is too long (maximum 191 characters).'));
} else if (is_null($timezone) || !in_array($timezone, DateTimeZone::listIdentifiers())) {
} elseif (is_null($timezone) || !in_array($timezone, DateTimeZone::listIdentifiers())) {
// TRANS: Validation error in form for profile settings.
throw new ClientException(_('Timezone not selected.'));
} else if (!is_null($language) && strlen($language) > 50) {
} elseif (!is_null($language) && strlen($language) > 50) {
// TRANS: Validation error in form for profile settings.
throw new ClientException(_('Language is too long (maximum 50 characters).'));
}
@ -291,7 +328,6 @@ class ProfilesettingsAction extends SettingsAction
$tags = array();
$tag_priv = array();
if (is_string($tagstring) && strlen($tagstring) > 0) {
$tags = preg_split('/[\s,]+/', $tagstring);
foreach ($tags as &$tag) {
@ -314,21 +350,19 @@ class ProfilesettingsAction extends SettingsAction
// Only allow setting private_stream if site policy allows it
// (or user already _has_ a private stream, then you can unset it)
if (common_config('profile', 'allowprivate') || $user->private_stream) {
$private_stream = $this->booleanintstring('private_stream');
$private_stream = $this->boolean('private_stream');
} else {
// if not allowed, we set to the existing value
$private_stream = $user->private_stream;
$private_stream = (bool) $user->private_stream;
}
// $user->nickname is updated through Profile->update();
// XXX: XOR
if (($user->autosubscribe ^ $autosubscribe)
|| ($user->private_stream ^ $private_stream)
if ((bool) $user->autosubscribe != $autosubscribe
|| (bool) $user->private_stream != $private_stream
|| $user->timezone != $timezone
|| $user->language != $language
|| $user->subscribe_policy != $subscribe_policy) {
$original = clone($user);
$user->autosubscribe = $autosubscribe;
@ -378,7 +412,6 @@ class ProfilesettingsAction extends SettingsAction
}
if (common_config('location', 'share') == 'user') {
$exists = false;
$prefs = User_location_prefs::getKV('user_id', $this->scoped->getID());
@ -393,7 +426,7 @@ class ProfilesettingsAction extends SettingsAction
$orig = clone($prefs);
}
$prefs->share_location = $this->booleanintstring('sharelocation');
$prefs->share_location = $this->boolean('sharelocation');
if ($exists) {
$result = $prefs->update($orig);
@ -429,11 +462,11 @@ class ProfilesettingsAction extends SettingsAction
// TRANS: Confirmation shown when user profile settings are saved.
return _('Settings saved.');
}
}
function showAside() {
public function showAside()
{
$this->elementStart('div', array('id' => 'aside_primary',
'class' => 'aside'));
@ -443,26 +476,32 @@ class ProfilesettingsAction extends SettingsAction
if (Event::handle('StartProfileSettingsActions', array($this))) {
if ($this->scoped->hasRight(Right::BACKUPACCOUNT)) {
$this->elementStart('li');
$this->element('a',
array('href' => common_local_url('backupaccount')),
// TRANS: Option in profile settings to create a backup of the account of the currently logged in user.
_('Backup account'));
$this->element(
'a',
['href' => common_local_url('backupaccount')],
// TRANS: Option in profile settings to create a backup of the account of the currently logged in user.
_('Backup account')
);
$this->elementEnd('li');
}
if ($this->scoped->hasRight(Right::DELETEACCOUNT)) {
$this->elementStart('li');
$this->element('a',
array('href' => common_local_url('deleteaccount')),
// TRANS: Option in profile settings to delete the account of the currently logged in user.
_('Delete account'));
$this->element(
'a',
['href' => common_local_url('deleteaccount')],
// TRANS: Option in profile settings to delete the account of the currently logged in user.
_('Delete account')
);
$this->elementEnd('li');
}
if ($this->scoped->hasRight(Right::RESTOREACCOUNT)) {
$this->elementStart('li');
$this->element('a',
array('href' => common_local_url('restoreaccount')),
// TRANS: Option in profile settings to restore the account of the currently logged in user from a backup.
_('Restore account'));
$this->element(
'a',
['href' => common_local_url('restoreaccount')],
// TRANS: Option in profile settings to restore the account of the currently logged in user from a backup.
_('Restore account')
);
$this->elementEnd('li');
}
Event::handle('EndProfileSettingsActions', array($this));

View File

@ -1,53 +1,45 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* StatusNet, the distributed open-source microblogging tool
*
* Action for showing profiles self-tagged with a given tag
*
* 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
* @package GNUsocial
* @author Evan Prodromou <evan@status.net>
* @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/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
defined('GNUSOCIAL') || die();
/**
* This class outputs a paginated list of profiles self-tagged with a given tag
*
* @category Output
* @package StatusNet
* @author Evan Prodromou <evan@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/
* @category Output
* @copyright 2009 StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*
* @see Action
* @see Action
*/
class SelftagAction extends Action
{
var $tag = null;
var $page = null;
public $tag = null;
public $page = null;
/**
* For initializing members of the class.
@ -57,7 +49,7 @@ class SelftagAction extends Action
* @return boolean true
* @throws ClientException
*/
function prepare(array $args = [])
public function prepare(array $args = [])
{
parent::prepare($args);
@ -66,8 +58,10 @@ class SelftagAction extends Action
if (!common_valid_profile_tag($this->tag)) {
// TRANS: Client error displayed when trying to list a profile with an invalid list.
// TRANS: %s is the invalid list name.
$this->clientError(sprintf(_('Not a valid list: %s.'),
$this->tag));
$this->clientError(sprintf(
_('Not a valid list: %s.'),
$this->tag
));
return null;
}
@ -83,7 +77,7 @@ class SelftagAction extends Action
*
* @return void is read only action?
*/
function handle()
public function handle()
{
parent::handle();
$this->showPage();
@ -94,19 +88,13 @@ class SelftagAction extends Action
* people tag and page, initalizes a ProfileList widget, and displays
* it to the user.
*/
function showContent()
public function showContent()
{
$profile = new Profile();
$offset = ($this->page - 1) * PROFILES_PER_PAGE;
$limit = PROFILES_PER_PAGE + 1;
if (common_config('db', 'type') == 'pgsql') {
$lim = ' LIMIT ' . $limit . ' OFFSET ' . $offset;
} else {
$lim = ' LIMIT ' . $offset . ', ' . $limit;
}
// XXX: memcached this
$qry = 'SELECT profile.* ' .
@ -125,18 +113,21 @@ class SelftagAction extends Action
' OR profile_list.private = false) ';
}
$qry .= 'ORDER BY profile_tag.modified DESC%s';
$qry .= 'ORDER BY profile_tag.modified DESC ' .
'LIMIT ' . $limit . ' OFFSET ' . $offset;
$profile->query(sprintf($qry, $this->tag, $lim));
$profile->query(sprintf($qry, $this->tag));
$ptl = new SelfTagProfileList($profile, $this); // pass the ammunition
$cnt = $ptl->show();
$this->pagination($this->page > 1,
$cnt > PROFILES_PER_PAGE,
$this->page,
'selftag',
array('tag' => $this->tag));
$this->pagination(
$this->page > 1,
$cnt > PROFILES_PER_PAGE,
$this->page,
'selftag',
['tag' => $this->tag]
);
}
/**
@ -144,18 +135,21 @@ class SelftagAction extends Action
*
* @return string page title
*/
function title()
public function title()
{
// TRANS: Page title for page showing self tags.
// TRANS: %1$s is a tag, %2$d is a page number.
return sprintf(_('Users self-tagged with %1$s, page %2$d'),
$this->tag, $this->page);
return sprintf(
_('Users self-tagged with %1$s, page %2$d'),
$this->tag,
$this->page
);
}
}
class SelfTagProfileList extends ProfileList
{
function newListItem(Profile $target)
public function newListItem(Profile $target)
{
return new SelfTagProfileListItem($target, $this->action);
}
@ -163,7 +157,7 @@ class SelfTagProfileList extends ProfileList
class SelfTagProfileListItem extends ProfileListItem
{
function linkAttributes()
public function linkAttributes()
{
$aAttrs = parent::linkAttributes();
@ -174,7 +168,7 @@ class SelfTagProfileListItem extends ProfileListItem
return $aAttrs;
}
function homepageAttributes()
public function homepageAttributes()
{
$aAttrs = parent::linkAttributes();
@ -185,7 +179,7 @@ class SelfTagProfileListItem extends ProfileListItem
return $aAttrs;
}
function showTags()
public function showTags()
{
$selftags = new SelfTagsWidget($this->out, $this->profile, $this->profile);
$selftags->show();

View File

@ -1,46 +1,39 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* StatusNet, the distributed open-source microblogging tool
* Settings for SMS.
*
* Settings for SMS
*
* 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
* @category Setting
* @package GNUsocial
* @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/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('GNUSOCIAL')) { exit(1); }
defined('GNUSOCIAL') || die();
/**
* Settings for SMS
*
* @category Settings
* @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/
* @copyright 2008-2009 StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*
* @see SettingsAction
*/
class SmssettingsAction extends SettingsAction
{
protected function doPreparation()
@ -56,7 +49,7 @@ class SmssettingsAction extends SettingsAction
*
* @return string Title of the page
*/
function title()
public function title()
{
// TRANS: Title for SMS settings.
return _('SMS settings');
@ -67,7 +60,7 @@ class SmssettingsAction extends SettingsAction
*
* @return instructions for use
*/
function getInstructions()
public function getInstructions()
{
// XXX: For consistency of parameters in messages, this should be a
// regular parameters, replaced with sprintf().
@ -76,7 +69,7 @@ class SmssettingsAction extends SettingsAction
return _('You can receive SMS messages through email from %%site.name%%.');
}
function showScripts()
public function showScripts()
{
parent::showScripts();
$this->autofocus('sms');
@ -90,7 +83,7 @@ class SmssettingsAction extends SettingsAction
*
* @return void
*/
function showContent()
public function showContent()
{
$user = $this->scoped->getUser();
@ -107,80 +100,105 @@ class SmssettingsAction extends SettingsAction
if ($user->sms) {
$carrier = $user->getCarrier();
$this->element('p', 'form_confirmed',
$user->sms . ' (' . $carrier->name . ')');
$this->element('p', 'form_guide',
// TRANS: Form guide in SMS settings form.
_('Current confirmed SMS-enabled phone number.'));
$this->element(
'p',
'form_confirmed',
$user->sms . ' (' . $carrier->name . ')'
);
$this->element(
'p',
'form_guide',
// TRANS: Form guide in SMS settings form.
_('Current confirmed SMS-enabled phone number.')
);
$this->hidden('sms', $user->sms);
$this->hidden('carrier', $user->carrier);
// TRANS: Button label to remove a confirmed SMS address.
$this->submit('remove', _m('BUTTON','Remove'));
$this->submit('remove', _m('BUTTON', 'Remove'));
} else {
try {
$confirm = $this->getConfirmation();
$carrier = Sms_carrier::getKV($confirm->address_extra);
$this->element('p', 'form_unconfirmed',
$confirm->address . ' (' . $carrier->name . ')');
$this->element('p', 'form_guide',
// TRANS: Form guide in IM settings form.
_('Awaiting confirmation on this phone number.'));
$this->element(
'p',
'form_unconfirmed',
$confirm->address . ' (' . $carrier->name . ')'
);
$this->element(
'p',
'form_guide',
// TRANS: Form guide in IM settings form.
_('Awaiting confirmation on this phone number.')
);
$this->hidden('sms', $confirm->address);
$this->hidden('carrier', $confirm->address_extra);
// TRANS: Button label to cancel a SMS address confirmation procedure.
$this->submit('cancel', _m('BUTTON','Cancel'));
$this->submit('cancel', _m('BUTTON', 'Cancel'));
$this->elementStart('ul', 'form_data');
$this->elementStart('li');
// TRANS: Field label for SMS address input in SMS settings form.
$this->input('code', _('Confirmation code'), null,
// TRANS: Form field instructions in SMS settings form.
_('Enter the code you received on your phone.'));
$this->input(
'code',
_('Confirmation code'),
null,
// TRANS: Form field instructions in SMS settings form.
_('Enter the code you received on your phone.')
);
$this->elementEnd('li');
$this->elementEnd('ul');
// TRANS: Button label to confirm SMS confirmation code in SMS settings.
$this->submit('confirm', _m('BUTTON','Confirm'));
$this->submit('confirm', _m('BUTTON', 'Confirm'));
} catch (NoResultException $e) {
$this->elementStart('ul', 'form_data');
$this->elementStart('li');
// TRANS: Field label for SMS phone number input in SMS settings form.
$this->input('sms', _('SMS phone number'),
($this->arg('sms')) ? $this->arg('sms') : null,
// TRANS: SMS phone number input field instructions in SMS settings form.
_('Phone number, no punctuation or spaces, '.
'with area code.'));
$this->input(
'sms',
_('SMS phone number'),
($this->arg('sms') ?: null),
// TRANS: SMS phone number input field instructions in SMS settings form.
_('Phone number, no punctuation or spaces, ' .
'with area code.')
);
$this->elementEnd('li');
$this->elementEnd('ul');
$this->carrierSelect();
// TRANS: Button label for adding a SMS phone number in SMS settings form.
$this->submit('add', _m('BUTTON','Add'));
$this->submit('add', _m('BUTTON', 'Add'));
}
}
$this->elementEnd('fieldset');
if ($user->sms) {
$this->elementStart('fieldset', array('id' => 'settings_sms_incoming_email'));
$this->elementStart('fieldset', ['id' => 'settings_sms_incoming_email']);
// XXX: Confused! This is about SMS. Should this message be updated?
// TRANS: Form legend for incoming SMS settings form.
$this->element('legend', null, _('Incoming email'));
if ($user->incomingemail) {
$this->element('p', 'form_unconfirmed', $user->incomingemail);
$this->element('p', 'form_note',
// XXX: Confused! This is about SMS. Should this message be updated?
// TRANS: Form instructions for incoming SMS e-mail address form in SMS settings.
_('Send email to this address to post new notices.'));
$this->element(
'p',
'form_note',
// XXX: Confused! This is about SMS. Should this message be updated?
// TRANS: Form instructions for incoming SMS e-mail address form in SMS settings.
_('Send email to this address to post new notices.')
);
// TRANS: Button label for removing a set sender SMS e-mail address to post notices from.
$this->submit('removeincoming', _m('BUTTON','Remove'));
$this->submit('removeincoming', _m('BUTTON', 'Remove'));
}
$this->element('p', 'form_guide',
// XXX: Confused! This is about SMS. Should this message be updated?
// TRANS: Instructions for incoming SMS e-mail address input form.
_('Make a new email address for posting to; '.
'cancels the old one.'));
$this->element(
'p',
'form_guide',
// XXX: Confused! This is about SMS. Should this message be updated?
// TRANS: Instructions for incoming SMS e-mail address input form.
_('Make a new email address for posting to; ' .
'cancels the old one.')
);
// TRANS: Button label for adding an SMS e-mail address to send notices from.
$this->submit('newincoming', _m('BUTTON','New'));
$this->submit('newincoming', _m('BUTTON', 'New'));
$this->elementEnd('fieldset');
}
@ -190,17 +208,19 @@ class SmssettingsAction extends SettingsAction
$this->elementStart('ul', 'form_data');
$this->elementStart('li');
$this->checkbox('smsnotify',
// TRANS: Checkbox label in SMS preferences form.
_('Send me notices through SMS; '.
'I understand I may incur '.
'exorbitant charges from my carrier.'),
$user->smsnotify);
$this->checkbox(
'smsnotify',
// TRANS: Checkbox label in SMS preferences form.
_('Send me notices through SMS; ' .
'I understand I may incur ' .
'exorbitant charges from my carrier.'),
$user->smsnotify
);
$this->elementEnd('li');
$this->elementEnd('ul');
// TRANS: Button label to save SMS preferences.
$this->submit('save', _m('BUTTON','Save'));
$this->submit('save', _m('BUTTON', 'Save'));
$this->elementEnd('fieldset');
$this->elementEnd('form');
@ -213,7 +233,7 @@ class SmssettingsAction extends SettingsAction
*
* @todo very similar to EmailsettingsAction::getConfirmation(); refactor?
*/
function getConfirmation()
public function getConfirmation()
{
$confirm = new Confirm_address();
@ -229,20 +249,19 @@ class SmssettingsAction extends SettingsAction
protected function doPost()
{
if ($this->arg('save')) {
return $this->savePreferences();
} else if ($this->arg('add')) {
} elseif ($this->arg('add')) {
return $this->addAddress();
} else if ($this->arg('cancel')) {
} elseif ($this->arg('cancel')) {
return $this->cancelConfirmation();
} else if ($this->arg('remove')) {
} elseif ($this->arg('remove')) {
return $this->removeAddress();
} else if ($this->arg('removeincoming')) {
} elseif ($this->arg('removeincoming')) {
return $this->removeIncoming();
} else if ($this->arg('newincoming')) {
} elseif ($this->arg('newincoming')) {
return $this->newIncoming();
} else if ($this->arg('confirm')) {
} elseif ($this->arg('confirm')) {
return $this->confirmCode();
}
// TRANS: Message given submitting a form with an unknown action in SMS settings.
@ -256,7 +275,7 @@ class SmssettingsAction extends SettingsAction
*
* @return void
*/
function savePreferences()
public function savePreferences()
{
$user = $this->scoped->getUser();
@ -288,7 +307,7 @@ class SmssettingsAction extends SettingsAction
*
* @return void
*/
function addAddress()
public function addAddress()
{
$user = common_current_user();
@ -312,7 +331,7 @@ class SmssettingsAction extends SettingsAction
if ($user->sms === $sms) {
// TRANS: Message given saving SMS phone number that is already set.
throw new AlreadyFulfilledException(_('That is already your phone number.'));
} else if ($this->smsExists($sms)) {
} elseif ($this->smsExists($sms)) {
// TRANS: Message given saving SMS phone number that is already set for another user.
throw new ClientException(_('That phone number already belongs to another user.'));
}
@ -335,9 +354,11 @@ class SmssettingsAction extends SettingsAction
$carrier = Sms_carrier::getKV($carrier_id);
mail_confirm_sms($confirm->code,
$user->nickname,
$carrier->toEmailAddress($sms));
mail_confirm_sms(
$confirm->code,
$user->nickname,
$carrier->toEmailAddress($sms)
);
// TRANS: Message given saving valid SMS phone number that is to be confirmed.
return _('A confirmation code was sent to the phone number you added. '.
@ -352,7 +373,7 @@ class SmssettingsAction extends SettingsAction
*
* @return void
*/
function cancelConfirmation()
public function cancelConfirmation()
{
$sms = $this->trimmed('sms');
$carrier = $this->trimmed('carrier');
@ -379,7 +400,7 @@ class SmssettingsAction extends SettingsAction
*
* @return void
*/
function removeAddress()
public function removeAddress()
{
$user = $this->scoped->getUser();
@ -396,9 +417,9 @@ class SmssettingsAction extends SettingsAction
$original = clone($user);
$user->sms = null;
$user->carrier = null;
$user->smsemail = null;
$user->sms = DB_DataObject_Cast::sql('NULL');
$user->carrier = DB_DataObject_Cast::sql('NULL');
$user->smsemail = DB_DataObject_Cast::sql('NULL');
// Throws exception on failure. Also performs it within a transaction.
$user->updateWithKeys($original);
@ -416,7 +437,7 @@ class SmssettingsAction extends SettingsAction
*
* @return boolean does the number exist
*/
function smsExists($sms)
public function smsExists($sms)
{
$other = User::getKV('sms', $sms);
@ -432,7 +453,7 @@ class SmssettingsAction extends SettingsAction
*
* @return void
*/
function carrierSelect()
public function carrierSelect()
{
$carrier = new Sms_carrier();
@ -444,22 +465,33 @@ class SmssettingsAction extends SettingsAction
$this->element('label', array('for' => 'carrier'), _('Mobile carrier'));
$this->elementStart('select', array('name' => 'carrier',
'id' => 'carrier'));
$this->element('option', array('value' => 0),
// TRANS: Default option for mobile carrier dropdown menu in SMS settings.
_('Select a carrier'));
$this->element(
'option',
['value' => 0],
// TRANS: Default option for mobile carrier dropdown menu in SMS settings.
_('Select a carrier')
);
while ($carrier->fetch()) {
$this->element('option', array('value' => $carrier->id),
$carrier->name);
$this->element(
'option',
['value' => $carrier->id],
$carrier->name
);
}
$this->elementEnd('select');
$this->element('p', 'form_guide',
// TRANS: Form instructions for mobile carrier dropdown menu in SMS settings.
// TRANS: %s is an administrative contact's e-mail address.
sprintf(_('Mobile carrier for your phone. '.
'If you know a carrier that accepts ' .
'SMS over email but isn\'t listed here, ' .
'send email to let us know at %s.'),
common_config('site', 'email')));
$this->element(
'p',
'form_guide',
// TRANS: Form instructions for mobile carrier dropdown menu in SMS settings.
// TRANS: %s is an administrative contact's e-mail address.
sprintf(
_('Mobile carrier for your phone. ' .
'If you know a carrier that accepts ' .
'SMS over email but isn\'t listed here, ' .
'send email to let us know at %s.'),
common_config('site', 'email')
)
);
$this->elementEnd('li');
$this->elementEnd('ul');
}
@ -471,7 +503,7 @@ class SmssettingsAction extends SettingsAction
*
* @return void
*/
function confirmCode()
public function confirmCode()
{
$code = $this->trimmed('code');
@ -488,7 +520,7 @@ class SmssettingsAction extends SettingsAction
*
* @return void
*/
function removeIncoming()
public function removeIncoming()
{
$user = common_current_user();
@ -499,7 +531,7 @@ class SmssettingsAction extends SettingsAction
$orig = clone($user);
$user->incomingemail = null;
$user->incomingemail = DB_DataObject_Cast::sql('NULL');
// Throws exception on failure. Also performs it within a transaction.
$user->updateWithKeys($orig);
@ -515,7 +547,7 @@ class SmssettingsAction extends SettingsAction
*
* @see Emailsettings::newIncoming
*/
function newIncoming()
public function newIncoming()
{
$user = $this->scoped->getUser();

View File

@ -1,28 +1,25 @@
<?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/>.
*/
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
defined('GNUSOCIAL') || die();
// @todo FIXME: documentation needed.
class SupAction extends Action
{
function handle()
public function handle()
{
parent::handle();
@ -43,21 +40,23 @@ class SupAction extends Action
'updates' => $updates));
}
function availablePeriods()
public function availablePeriods()
{
static $periods = array(86400, 43200, 21600, 7200,
3600, 1800, 600, 300, 120,
60, 30, 15);
$available = array();
foreach ($periods as $period) {
$available[$period] = common_local_url('sup',
array('seconds' => $period));
$available[$period] = common_local_url(
'sup',
['seconds' => $period]
);
}
return $available;
}
function getUpdates($seconds)
public function getUpdates($seconds)
{
$notice = new Notice();
@ -69,9 +68,7 @@ class SupAction extends Action
$notice->query('SELECT profile_id, max(id) AS max_id ' .
'FROM ( ' .
'SELECT profile_id, id FROM notice ' .
((common_config('db','type') == 'pgsql') ?
'WHERE extract(epoch from created) > (extract(epoch from now()) - ' . $seconds . ') ' :
'WHERE created > "'.$divider.'" ' ) .
"WHERE created > TIMESTAMP '" . $divider . "' " .
') AS latest ' .
'GROUP BY profile_id');
@ -84,7 +81,7 @@ class SupAction extends Action
return $updates;
}
function isReadOnly($args)
public function isReadOnly($args)
{
return true;
}

View File

@ -1,6 +1,20 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
if (!defined('GNUSOCIAL')) { exit(1); }
defined('GNUSOCIAL') || die();
/**
* Table Definition for avatar
@ -10,20 +24,20 @@ class Avatar extends Managed_DataObject
{
public $__table = 'avatar'; // table name
public $profile_id; // int(4) primary_key not_null
public $original; // tinyint(1)
public $original; // bool default_false
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 default_0000-00-00%2000%3A00%3A00
public $modified; // datetime() 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?'),
'original' => array('type' => 'bool', 'default' => false, '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'),
@ -45,7 +59,7 @@ class Avatar extends Managed_DataObject
}
// We clean up the file, too
function delete($useWhere=false)
public function delete($useWhere = false)
{
$filename = $this->filename;
if (file_exists(Avatar::path($filename))) {
@ -57,11 +71,12 @@ class Avatar extends Managed_DataObject
/*
* 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) {
public static function deleteFromProfile(Profile $target, $original = true)
{
try {
$avatars = self::getProfileAvatars($target);
foreach ($avatars as $avatar) {
@ -77,7 +92,7 @@ class Avatar extends Managed_DataObject
return true;
}
static protected $_avatars = array();
protected static $_avatars = [];
/*
* Get an avatar by profile. Currently can't call newSize with $height
@ -93,7 +108,7 @@ class Avatar extends Managed_DataObject
$size = "{$width}x{$height}";
if (!isset(self::$_avatars[$target->id])) {
self::$_avatars[$target->id] = array();
} elseif (isset(self::$_avatars[$target->id][$size])){
} elseif (isset(self::$_avatars[$target->id][$size])) {
return self::$_avatars[$target->id][$size];
}
@ -137,7 +152,8 @@ class Avatar extends Managed_DataObject
return $avatar;
}
public static function getProfileAvatars(Profile $target) {
public static function getProfileAvatars(Profile $target)
{
$avatar = new Avatar();
$avatar->profile_id = $target->id;
if (!$avatar->find()) {
@ -149,7 +165,7 @@ class Avatar extends Managed_DataObject
/**
* Where should the avatar go for this user?
*/
static function filename($id, $extension, $size=null, $extra=null)
public static function filename($id, $extension, $size = null, $extra = null)
{
if ($size) {
return $id . '-' . $size . (($extra) ? ('-' . $extra) : '') . $extension;
@ -158,7 +174,7 @@ class Avatar extends Managed_DataObject
}
}
static function path($filename)
public static function path($filename)
{
$dir = common_config('avatar', 'dir');
@ -169,7 +185,7 @@ class Avatar extends Managed_DataObject
return $dir . $filename;
}
static function url($filename)
public static function url($filename)
{
$path = common_config('avatar', 'path');
@ -194,20 +210,21 @@ class Avatar extends Managed_DataObject
return $protocol.'://'.$server.$path.$filename;
}
function displayUrl()
public function displayUrl()
{
return Avatar::url($this->filename);
}
static function urlByProfile(Profile $target, $width=null, $height=null) {
public static function urlByProfile(Profile $target, $width = null, $height = null)
{
try {
return self::byProfile($target, $width, $height)->displayUrl();
return self::byProfile($target, $width, $height)->displayUrl();
} catch (Exception $e) {
return self::defaultImage($width);
}
}
static function defaultImage($size=null)
public static function defaultImage($size = null)
{
if (is_null($size)) {
$size = AVATAR_PROFILE_SIZE;
@ -218,7 +235,8 @@ class Avatar extends Managed_DataObject
return Theme::path('default-avatar-'.$sizenames[$size].'.png');
}
static function newSize(Profile $target, $width) {
public 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
@ -231,8 +249,12 @@ class Avatar extends Managed_DataObject
$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());
$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);

View File

@ -1,35 +1,32 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* 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
* @package GNUsocial
* @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/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('GNUSOCIAL')) { exit(1); }
defined('GNUSOCIAL') || die();
class Conversation extends Managed_DataObject
{
@ -57,14 +54,14 @@ class Conversation extends Managed_DataObject
);
}
static public function beforeSchemaUpdate()
public static 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']) {
if ($schemadef['fields']['id']['auto_increment'] ?? false) {
// since we already have auto incrementing ('serial') we can continue
return;
}
@ -91,7 +88,7 @@ class Conversation extends Managed_DataObject
*
* @return Conversation the new conversation DO
*/
static function create(ActivityContext $ctx=null, $created=null)
public 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();
@ -100,11 +97,16 @@ class Conversation extends Managed_DataObject
$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
$conv->uri = sprintf(
'%s%s=%s:%s=%s',
TagURI::mint(),
'objectType',
'thread',
'nonce',
common_random_hexstr(8)
);
// locally generated Conversation objects don't get static URLs stored
$conv->url = DB_DataObject_Cast::sql('NULL');
}
// This insert throws exceptions on failure
$conv->insert();
@ -112,7 +114,7 @@ class Conversation extends Managed_DataObject
return $conv;
}
static function noticeCount($id)
public static function noticeCount($id)
{
$keypart = sprintf('conversation:notice_count:%d', $id);
@ -132,7 +134,7 @@ class Conversation extends Managed_DataObject
return $cnt;
}
static public function getUrlFromNotice(Notice $notice, $anchor=true)
public static function getUrlFromNotice(Notice $notice, $anchor = true)
{
$conv = Conversation::getByID($notice->conversation);
return $conv->getUrl($anchor ? $notice->getID() : null);

View File

@ -1,29 +1,26 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* GNU social - a federating social network
*
* Abstraction for files
*
* 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 Files
* @package GNUsocial
* @author Mikael Nordfeldth <mmn@hethane.se>
* @author Miguel Dantas <biodantas@gmail.com>
* @copyright 2008-2009, 2019 Free Software Foundation http://fsf.org
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link https://www.gnu.org/software/social/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
defined('GNUSOCIAL') || die();
@ -248,14 +245,14 @@ class File extends Managed_DataObject
// TRANS: gettext support multiple plurals in the same message, unfortunately...
throw new ClientException(
sprintf(
_m(
_m(
'No file may be larger than %1$d byte and the file you sent was %2$s. Try to upload a smaller version.',
'No file may be larger than %1$d bytes and the file you sent was %2$s. Try to upload a smaller version.',
$fileQuota
),
$fileQuota,
$fileSizeText
)
$fileQuota,
$fileSizeText
)
);
}
@ -277,13 +274,13 @@ class File extends Managed_DataObject
// TRANS: %d (number) is the user quota in bytes and is used for plural.
throw new ClientException(
sprintf(
_m(
_m(
'A file this large would exceed your user quota of %d byte.',
'A file this large would exceed your user quota of %d bytes.',
common_config('attachments', 'user_quota')
),
common_config('attachments', 'user_quota')
)
common_config('attachments', 'user_quota')
)
);
}
$query .= ' AND EXTRACT(month FROM file.modified) = EXTRACT(month FROM now()) AND EXTRACT(year FROM file.modified) = EXTRACT(year FROM now())';
@ -295,13 +292,13 @@ class File extends Managed_DataObject
// TRANS: $d (number) is the monthly user quota in bytes and is used for plural.
throw new ClientException(
sprintf(
_m(
_m(
'A file this large would exceed your monthly quota of %d byte.',
'A file this large would exceed your monthly quota of %d bytes.',
common_config('attachments', 'monthly_quota')
),
common_config('attachments', 'monthly_quota')
)
common_config('attachments', 'monthly_quota')
)
);
}
return true;
@ -346,7 +343,8 @@ class File extends Managed_DataObject
* @param string $filename
* @return string|bool Value from the 'extblacklist' array, in the config
*/
public static function getSafeExtension(string $filename) {
public static function getSafeExtension(string $filename)
{
if (preg_match('/^.+?\.([A-Za-z0-9]+)$/', $filename, $matches) === 1) {
// we matched on a file extension, so let's see if it means something.
$ext = mb_strtolower($matches[1]);
@ -888,7 +886,11 @@ class File extends Managed_DataObject
echo "\nFound old $table table, upgrading it to contain 'urlhash' field...";
$file = new File();
$file->query(sprintf('SELECT id, LEFT(url, 191) AS shortenedurl, COUNT(*) AS c FROM %1$s WHERE LENGTH(url)>191 GROUP BY shortenedurl HAVING c > 1', $schema->quoteIdentifier($table)));
$file->query(sprintf(
'SELECT id, LEFT(url, 191) AS shortenedurl, COUNT(*) FROM %1$s ' .
'WHERE LENGTH(url) > 191 GROUP BY id, shortenedurl HAVING COUNT(*) > 1',
common_database_tablename($table)
));
print "\nFound {$file->N} URLs with too long entries in file table\n";
while ($file->fetch()) {
// We've got a URL that is too long for our future file table
@ -941,13 +943,20 @@ class File extends Managed_DataObject
$tablefix = new $classname;
// urlhash is hash('sha256', $url) in the File table
echo "Updating urlhash fields in $table table...";
// Maybe very MySQL specific :(
switch (common_config('db', 'type')) {
case 'pgsql':
$url_sha256 = 'encode(sha256(CAST("url" AS bytea)), \'hex\')';
break;
case 'mysql':
$url_sha256 = 'sha2(`url`, 256)';
break;
default:
throw new ServerException('Unknown DB type selected.');
}
$tablefix->query(sprintf(
'UPDATE %1$s SET %2$s=%3$s;',
$schema->quoteIdentifier($table),
'urlhash',
// The line below is "result of sha256 on column `url`"
'SHA2(url, 256)'
'UPDATE %1$s SET urlhash = %2$s;',
$tablefix->escapedTableName(),
$url_sha256
));
echo "DONE.\n";
echo "Resuming core schema upgrade...";

View File

@ -1,28 +1,24 @@
<?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/>.
*/
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
if (!defined('GNUSOCIAL')) { exit(1); }
defined('GNUSOCIAL') || die();
/**
* Table Definition for file_redirection
*/
class File_redirection extends Managed_DataObject
{
###START_AUTOCODE
@ -54,17 +50,18 @@ class File_redirection extends Managed_DataObject
),
'primary key' => array('urlhash'),
'foreign keys' => array(
'file_redirection_file_id_fkey' => array('file' => array('file_id' => 'id')),
'file_redirection_file_id_fkey' => array('file', array('file_id' => 'id')),
),
);
}
static public function getByUrl($url)
public static function getByUrl($url)
{
return self::getByPK(array('urlhash' => File::hashurl($url)));
}
static function _commonHttp($url, $redirs) {
public static function _commonHttp($url, $redirs)
{
$request = new HTTPClient($url);
$request->setConfig(array(
'connect_timeout' => 10, // # seconds to wait
@ -96,10 +93,13 @@ class File_redirection extends Managed_DataObject
* size (optional): byte size from Content-Length header
* time (optional): timestamp from Last-Modified header
*/
static function lookupWhere($short_url, $redirs = 10, $protected = false) {
if ($redirs < 0) return false;
public static function lookupWhere($short_url, $redirs = 10, $protected = false)
{
if ($redirs < 0) {
return false;
}
if(strpos($short_url,'://') === false){
if (strpos($short_url, '://') === false) {
return $short_url;
}
try {
@ -128,13 +128,13 @@ class File_redirection extends Managed_DataObject
common_log(LOG_ERR, "Error while following redirects for $short_url: " . $e->getMessage());
return $short_url;
}
// if last url after all redirections is protected,
// use the url before it in the redirection chain
// if last url after all redirections is protected,
// use the url before it in the redirection chain
if ($response->getRedirectCount() && File::isProtected($response->getEffectiveUrl())) {
$return_url = $response->redirUrls[$response->getRedirectCount()-1];
$return_url = $response->redirUrls[$response->getRedirectCount() - 1];
} else {
$return_url = $response->getEffectiveUrl();
$return_url = $response->getEffectiveUrl();
}
$ret = array('code' => $response->getStatus()
@ -142,12 +142,20 @@ class File_redirection extends Managed_DataObject
, 'url' => $return_url);
$type = $response->getHeader('Content-Type');
if ($type) $ret['type'] = $type;
if ($protected) $ret['protected'] = true;
if ($type) {
$ret['type'] = $type;
}
if ($protected) {
$ret['protected'] = true;
}
$size = $response->getHeader('Content-Length'); // @fixme bytes?
if ($size) $ret['size'] = $size;
if ($size) {
$ret['size'] = $size;
}
$time = $response->getHeader('Last-Modified');
if ($time) $ret['time'] = strtotime($time);
if ($time) {
$ret['time'] = strtotime($time);
}
return $ret;
}
@ -164,7 +172,8 @@ class File_redirection extends Managed_DataObject
* @param boolean $discover true to attempt dereferencing the redirect if we don't know it already
* @return File_redirection
*/
static function where($in_url, $discover=true) {
public static function where($in_url, $discover = true)
{
$redir = new File_redirection();
$redir->url = $in_url;
$redir->urlhash = File::hashurl($redir->url);
@ -179,14 +188,16 @@ class File_redirection extends Managed_DataObject
$r->redir_url = $f->url;
} catch (NoResultException $e) {
// Invalid entry, delete and run again
common_log(LOG_ERR, "Could not find File with id=".$r->file_id." referenced in File_redirection, deleting File redirection entry and and trying again...");
common_log(
LOG_ERR,
'Could not find File with id=' . $r->file_id . ' referenced in File_redirection, deleting File redirection entry and and trying again...'
);
$r->delete();
return self::where($in_url);
return self::where($in_url);
}
// File_redirecion and File record found, return both
return $r;
} catch (NoResultException $e) {
// File_redirecion record not found, but this might be a direct link to a file
try {
@ -194,15 +205,15 @@ class File_redirection extends Managed_DataObject
$redir->file_id = $f->id;
$redir->file = $f;
return $redir;
} catch (NoResultException $e) {
} catch (NoResultException $e) {
// nope, this was not a direct link to a file either, let's keep going
}
}
if ($discover) {
// try to follow redirects and get the final url
if ($discover) {
// try to follow redirects and get the final url
$redir_info = File_redirection::lookupWhere($in_url);
if(is_string($redir_info)) {
if (is_string($redir_info)) {
$redir_info = array('url' => $redir_info);
}
@ -212,29 +223,32 @@ class File_redirection extends Managed_DataObject
try {
$r = File_redirection::getByUrl($redir_info['url']);
$f = File::getKV('id',$r->file_id);
$f = File::getKV('id', $r->file_id);
if($f instanceof File) {
if ($f instanceof File) {
$redir->file = $f;
$redir->redir_url = $f->url;
$redir->redir_url = $f->url;
} else {
// Invalid entry in File_redirection, delete and run again
common_log(LOG_ERR, "Could not find File with id=".$r->file_id." referenced in File_redirection, deleting File_redirection entry and trying again...");
common_log(
LOG_ERR,
'Could not find File with id=' . $r->file_id . ' referenced in File_redirection, deleting File_redirection entry and trying again...'
);
$r->delete();
return self::where($in_url);
return self::where($in_url);
}
} catch (NoResultException $e) {
// save the file now when we know that we don't have it in File_redirection
try {
$redir->file = File::saveNew($redir_info,$redir_info['url']);
$redir->file = File::saveNew($redir_info, $redir_info['url']);
} catch (ServerException $e) {
common_log(LOG_ERR, $e);
}
}
}
// If this is a redirection and we have a file to redirect to, save it
// (if it doesn't exist in File_redirection already)
if($redir->file instanceof File && $redir_info['url'] != $in_url) {
// (if it doesn't exist in File_redirection already)
if ($redir->file instanceof File && $redir_info['url'] != $in_url) {
try {
$file_redir = File_redirection::getByUrl($in_url);
} catch (NoResultException $e) {
@ -243,12 +257,12 @@ class File_redirection extends Managed_DataObject
$file_redir->url = $in_url;
$file_redir->file_id = $redir->file->getID();
$file_redir->insert();
$file_redir->redir_url = $redir->file->url;
}
$file_redir->redir_url = $redir->file->url;
}
$file_redir->file = $redir->file;
return $file_redir;
}
$file_redir->file = $redir->file;
return $file_redir;
}
}
return $redir;
@ -268,7 +282,7 @@ class File_redirection extends Managed_DataObject
* @param User $user whose shortening options to use; defaults to the current web session user
* @return string
*/
static function makeShort($long_url, $user=null)
public static function makeShort($long_url, $user = null)
{
$canon = File_redirection::_canonUrl($long_url);
@ -293,7 +307,7 @@ class File_redirection extends Managed_DataObject
* @return string
*/
static function forceShort($long_url, $user)
public static function forceShort($long_url, $user)
{
$canon = File_redirection::_canonUrl($long_url);
@ -303,7 +317,8 @@ class File_redirection extends Managed_DataObject
return !empty($short_url) ? $short_url : $long_url;
}
static function _userMakeShort($long_url, User $user=null, $force = false) {
public static function _userMakeShort($long_url, User $user = null, $force = false)
{
$short_url = common_shorten_url($long_url, $user, $force);
if (!empty($short_url) && $short_url != $long_url) {
$short_url = (string)$short_url;
@ -343,8 +358,11 @@ class File_redirection extends Managed_DataObject
* @param string $default_scheme if given a bare link; defaults to 'http://'
* @return string
*/
static function _canonUrl($in_url, $default_scheme = 'http://') {
if (empty($in_url)) return false;
public static function _canonUrl($in_url, $default_scheme = 'http://')
{
if (empty($in_url)) {
return false;
}
$out_url = $in_url;
$p = parse_url($out_url);
if (empty($p['host']) || empty($p['scheme'])) {
@ -377,13 +395,17 @@ class File_redirection extends Managed_DataObject
default:
$out_url = $default_scheme . ltrim($out_url, '/');
$p = parse_url($out_url);
if (empty($p['scheme'])) return false;
if (empty($p['scheme'])) {
return false;
}
break;
}
}
if (('ftp' == $p['scheme']) || ('ftps' == $p['scheme']) || ('http' == $p['scheme']) || ('https' == $p['scheme'])) {
if (empty($p['host'])) return false;
if (empty($p['host'])) {
return false;
}
if (empty($p['path'])) {
$out_url .= '/';
}
@ -392,7 +414,8 @@ class File_redirection extends Managed_DataObject
return $out_url;
}
static function saveNew($data, $file_id, $url) {
public static function saveNew($data, $file_id, $url)
{
$file_redir = new File_redirection;
$file_redir->urlhash = File::hashurl($url);
$file_redir->url = $url;
@ -402,7 +425,7 @@ class File_redirection extends Managed_DataObject
$file_redir->insert();
}
static public function beforeSchemaUpdate()
public static function beforeSchemaUpdate()
{
$table = strtolower(get_called_class());
$schema = Schema::get();
@ -416,16 +439,16 @@ class File_redirection extends Managed_DataObject
echo "\nFound old $table table, upgrading it to contain 'urlhash' field...";
// We have to create a urlhash that is _not_ the primary key,
// transfer data and THEN run checkSchema
$schemadef['fields']['urlhash'] = array (
'type' => 'varchar',
'length' => 64,
'not null' => true,
'description' => 'sha256 hash of the URL',
);
$schemadef['fields']['url'] = array (
'type' => 'text',
'description' => 'short URL (or any other kind of redirect) for file (id)',
);
$schemadef['fields']['urlhash'] = [
'type' => 'varchar',
'length' => 64,
'not null' => true,
'description' => 'sha256 hash of the URL',
];
$schemadef['fields']['url'] = [
'type' => 'text',
'description' => 'short URL (or any other kind of redirect) for file (id)',
];
unset($schemadef['primary key']);
$schema->ensureTable($table, $schemadef);
echo "DONE.\n";
@ -434,17 +457,27 @@ class File_redirection extends Managed_DataObject
$tablefix = new $classname;
// urlhash is hash('sha256', $url) in the File table
echo "Updating urlhash fields in $table table...";
// Maybe very MySQL specific :(
$tablefix->query(sprintf('UPDATE %1$s SET %2$s=%3$s;',
$schema->quoteIdentifier($table),
'urlhash',
// The line below is "result of sha256 on column `url`"
'SHA2(url, 256)'));
switch (common_config('db', 'type')) {
case 'pgsql':
$url_sha256 = 'encode(sha256(CAST("url" AS bytea)), \'hex\')';
break;
case 'mysql':
$url_sha256 = 'sha2(`url`, 256)';
break;
default:
throw new ServerException('Unknown DB type selected.');
}
$tablefix->query(sprintf(
'UPDATE %1$s SET urlhash = %2$s;',
$tablefix->escapedTableName(),
$url_sha256
));
echo "DONE.\n";
echo "Resuming core schema upgrade...";
}
public function getFile() {
public function getFile()
{
if (!$this->file instanceof File) {
$this->file = File::getByID($this->file_id);
}

View File

@ -1,28 +1,29 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/*
* 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/>.
* @copyright 2008-2009 StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('GNUSOCIAL')) { exit(1); }
defined('GNUSOCIAL') || die();
/**
* Table Definition for file_thumbnail
*/
class File_thumbnail extends Managed_DataObject
{
public $__table = 'file_thumbnail'; // table name
@ -44,8 +45,8 @@ class File_thumbnail extends Managed_DataObject
'urlhash' => array('type' => 'varchar', 'length' => 64, 'description' => 'sha256 of url field if non-empty'),
'url' => array('type' => 'text', 'description' => 'URL of thumbnail'),
'filename' => array('type' => 'text', 'description' => 'if stored locally, filename is put here'),
'width' => array('type' => 'int', 'description' => 'width of thumbnail'),
'height' => array('type' => 'int', 'description' => 'height of thumbnail'),
'width' => array('type' => 'int', 'not null' => true, 'description' => 'width of thumbnail'),
'height' => array('type' => 'int', 'not null' => true, 'description' => 'height of thumbnail'),
'modified' => array('type' => 'datetime', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was modified'),
),
'primary key' => array('file_id', 'width', 'height'),
@ -65,21 +66,26 @@ class File_thumbnail extends Managed_DataObject
* @param object $data
* @param int $file_id
*/
public static function saveNew($data, $file_id) {
public static function saveNew($data, $file_id)
{
if (!empty($data->thumbnail_url)) {
// Non-photo types such as video will usually
// show us a thumbnail, though it's not required.
self::saveThumbnail($file_id,
$data->thumbnail_url,
$data->thumbnail_width,
$data->thumbnail_height);
} else if ($data->type == 'photo') {
self::saveThumbnail(
$file_id,
$data->thumbnail_url,
$data->thumbnail_width,
$data->thumbnail_height
);
} elseif ($data->type == 'photo') {
// The inline photo URL given should also fit within
// our requested thumbnail size, per oEmbed spec.
self::saveThumbnail($file_id,
$data->url,
$data->width,
$data->height);
self::saveThumbnail(
$file_id,
$data->url,
$data->width,
$data->height
);
}
}
@ -92,7 +98,8 @@ class File_thumbnail extends Managed_DataObject
* @return File_thumbnail
* @throws NoResultException if no File_thumbnail matched the criteria
*/
static function byFile(File $file, $notNullUrl=true) {
public static function byFile(File $file, $notNullUrl = true)
{
$thumb = new File_thumbnail();
$thumb->file_id = $file->getID();
if ($notNullUrl) {
@ -116,7 +123,7 @@ class File_thumbnail extends Managed_DataObject
* @param int $width
* @param int $height
*/
static function saveThumbnail($file_id, $url, $width, $height, $filename=null)
public static function saveThumbnail($file_id, $url, $width, $height, $filename = null)
{
$tn = new File_thumbnail;
$tn->file_id = $file_id;
@ -128,7 +135,7 @@ class File_thumbnail extends Managed_DataObject
return $tn;
}
static function path($filename)
public static function path($filename)
{
File::tryFilename($filename);
@ -142,7 +149,7 @@ class File_thumbnail extends Managed_DataObject
return $dir . $filename;
}
static function url($filename)
public static function url($filename)
{
File::tryFilename($filename);
@ -276,7 +283,7 @@ class File_thumbnail extends Managed_DataObject
return $this->file_id;
}
static public function hashurl($url)
public static function hashurl($url)
{
if (!mb_strlen($url)) {
throw new Exception('No URL provided to hash algorithm.');

View File

@ -1,4 +1,21 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
defined('GNUSOCIAL') || die();
/**
* Table Definition for request_queue
*/
@ -23,7 +40,7 @@ class Group_join_queue extends Managed_DataObject
'description' => 'Holder for group join requests awaiting moderation.',
'fields' => array(
'profile_id' => array('type' => 'int', 'not null' => true, 'description' => 'remote or local profile making the request'),
'group_id' => array('type' => 'int', 'description' => 'remote or local group to join, if any'),
'group_id' => array('type' => 'int', 'not null' => true, 'description' => 'remote or local group to join, if any'),
'created' => array('type' => 'datetime', 'not null' => true, 'default' => '0000-00-00 00:00:00', 'description' => 'date this record was created'),
),
'primary key' => array('profile_id', 'group_id'),
@ -48,27 +65,27 @@ class Group_join_queue extends Managed_DataObject
return $rq;
}
function getMember()
public function getMember()
{
$member = Profile::getKV('id', $this->profile_id);
if (empty($member)) {
// TRANS: Exception thrown providing an invalid profile ID.
// TRANS: %s is the invalid profile ID.
throw new Exception(sprintf(_('Profile ID %s is invalid.'),$this->profile_id));
throw new Exception(sprintf(_('Profile ID %s is invalid.'), $this->profile_id));
}
return $member;
}
function getGroup()
public function getGroup()
{
$group = User_group::getKV('id', $this->group_id);
if (empty($group)) {
// TRANS: Exception thrown providing an invalid group ID.
// TRANS: %s is the invalid group ID.
throw new Exception(sprintf(_('Group ID %s is invalid.'),$this->group_id));
throw new Exception(sprintf(_('Group ID %s is invalid.'), $this->group_id));
}
return $group;
@ -77,7 +94,7 @@ class Group_join_queue extends Managed_DataObject
/**
* Abort the pending group join...
*/
function abort()
public function abort()
{
$profile = $this->getMember();
$group = $this->getGroup();
@ -93,7 +110,7 @@ class Group_join_queue extends Managed_DataObject
*
* @return Group_member object on success
*/
function complete()
public function complete()
{
$join = null;
$profile = $this->getMember();

View File

@ -1,4 +1,21 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
defined('GNUSOCIAL') || die();
/**
* Table Definition for group_member
*/
@ -11,7 +28,7 @@ class Group_member extends Managed_DataObject
public $__table = 'group_member'; // table name
public $group_id; // int(4) primary_key not_null
public $profile_id; // int(4) primary_key not_null
public $is_admin; // tinyint(1)
public $is_admin; // bool default_false
public $uri; // varchar(191) not 255 because utf8mb4 takes more space
public $created; // datetime() not_null default_0000-00-00%2000%3A00%3A00
public $modified; // datetime() not_null default_CURRENT_TIMESTAMP
@ -25,7 +42,7 @@ class Group_member extends Managed_DataObject
'fields' => array(
'group_id' => array('type' => 'int', 'not null' => true, 'description' => 'foreign key to user_group'),
'profile_id' => array('type' => 'int', 'not null' => true, 'description' => 'foreign key to profile table'),
'is_admin' => array('type' => 'int', 'size' => 'tiny', 'default' => 0, 'description' => 'is this user an admin?'),
'is_admin' => array('type' => 'bool', 'default' => false, 'description' => 'is this user an admin?'),
'uri' => array('type' => 'varchar', 'length' => 191, 'description' => 'universal identifier'),
'created' => array('type' => 'datetime', 'not null' => true, 'default' => '0000-00-00 00:00:00', 'description' => 'date this record was created'),
'modified' => array('type' => 'datetime', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was modified'),
@ -54,20 +71,22 @@ class Group_member extends Managed_DataObject
*
* @param integer $group_id Group to add to
* @param integer $profile_id Profile being added
*
*
* @return Group_member new membership object
*/
static function join($group_id, $profile_id)
public static function join($group_id, $profile_id)
{
$member = new Group_member();
$member->group_id = $group_id;
$member->profile_id = $profile_id;
$member->created = common_sql_now();
$member->uri = self::newUri(Profile::getByID($profile_id),
User_group::getByID($group_id),
$member->created);
$member->uri = self::newUri(
Profile::getByID($profile_id),
User_group::getByID($group_id),
$member->created
);
$result = $member->insert();
@ -80,7 +99,7 @@ class Group_member extends Managed_DataObject
return $member;
}
static function leave($group_id, $profile_id)
public static function leave($group_id, $profile_id)
{
$member = Group_member::pkeyGet(array('group_id' => $group_id,
'profile_id' => $profile_id));
@ -101,27 +120,27 @@ class Group_member extends Managed_DataObject
return true;
}
function getMember()
public function getMember()
{
$member = Profile::getKV('id', $this->profile_id);
if (empty($member)) {
// TRANS: Exception thrown providing an invalid profile ID.
// TRANS: %s is the invalid profile ID.
throw new Exception(sprintf(_("Profile ID %s is invalid."),$this->profile_id));
throw new Exception(sprintf(_("Profile ID %s is invalid."), $this->profile_id));
}
return $member;
}
function getGroup()
public function getGroup()
{
$group = User_group::getKV('id', $this->group_id);
if (empty($group)) {
// TRANS: Exception thrown providing an invalid group ID.
// TRANS: %s is the invalid group ID.
throw new Exception(sprintf(_("Group ID %s is invalid."),$this->group_id));
throw new Exception(sprintf(_('Group ID %s is invalid.'), $this->group_id));
}
return $group;
@ -137,7 +156,7 @@ class Group_member extends Managed_DataObject
* @return Group_member stream of memberships, use fetch() to iterate
*/
static function byMember($memberId, $offset=0, $limit=GROUPS_PER_PAGE)
public static function byMember($memberId, $offset = 0, $limit = GROUPS_PER_PAGE)
{
$membership = new Group_member();
@ -152,7 +171,7 @@ class Group_member extends Managed_DataObject
return $membership;
}
function asActivity()
public function asActivity()
{
$member = $this->getMember();
@ -180,13 +199,19 @@ class Group_member extends Managed_DataObject
// TRANS: Success message for subscribe to group attempt through OStatus.
// TRANS: %1$s is the member name, %2$s is the subscribed group's name.
$act->content = sprintf(_('%1$s has joined group %2$s.'),
$member->getBestName(),
$group->getBestName());
$act->content = sprintf(
_('%1$s has joined group %2$s.'),
$member->getBestName(),
$group->getBestName()
);
$url = common_local_url('AtomPubShowMembership',
array('profile' => $member->id,
'group' => $group->id));
$url = common_local_url(
'AtomPubShowMembership',
[
'profile' => $member->id,
'group' => $group->id,
]
);
$act->selfLink = $url;
$act->editLink = $url;
@ -203,7 +228,7 @@ class Group_member extends Managed_DataObject
mail_notify_group_join($this->getGroup(), $this->getMember());
}
function getUri()
public function getUri()
{
return $this->uri ?: self::newUri($this->getMember(), $this->getGroup()->getProfile(), $this->created);
}

View File

@ -1,28 +1,31 @@
<?php
/*
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2010, StatusNet, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* Wrapper for Memcached_DataObject which knows its own schema definition.
* Builds its own damn settings from a schema definition.
*
* @author Brion Vibber <brion@status.net>
* @package GNUsocial
* @author Brion Vibber <brion@status.net>
* @copyright 2010 Free Software Foundation, Inc http://www.fsf.org
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
defined('GNUSOCIAL') || die();
abstract class Managed_DataObject extends Memcached_DataObject
{
/**
@ -42,7 +45,7 @@ abstract class Managed_DataObject extends Memcached_DataObject
* @return get_called_class() object if found, or null for no hits
*
*/
static function getKV($k,$v=NULL)
public static function getKV($k, $v = null)
{
return parent::getClassKV(get_called_class(), $k, $v);
}
@ -59,12 +62,12 @@ abstract class Managed_DataObject extends Memcached_DataObject
* @return get_called_class() object if found, or null for no hits
*
*/
static function pkeyGet(array $kv)
public static function pkeyGet(array $kv)
{
return parent::pkeyGetClass(get_called_class(), $kv);
}
static function pkeyCols()
public static function pkeyCols()
{
return parent::pkeyColsClass(get_called_class());
}
@ -78,10 +81,10 @@ abstract class Managed_DataObject extends Memcached_DataObject
*
* @return array Array of objects, in order
*/
static function multiGet($keyCol, array $keyVals, $skipNulls=true)
{
return parent::multiGetClass(get_called_class(), $keyCol, $keyVals, $skipNulls);
}
public static function multiGet($keyCol, array $keyVals, $skipNulls = true)
{
return parent::multiGetClass(get_called_class(), $keyCol, $keyVals, $skipNulls);
}
/**
* Get multiple items from the database by key
@ -92,10 +95,10 @@ abstract class Managed_DataObject extends Memcached_DataObject
*
* @return array Array mapping $keyVals to objects, or null if not found
*/
static function pivotGet($keyCol, array $keyVals, array $otherCols=array())
{
return parent::pivotGetClass(get_called_class(), $keyCol, $keyVals, $otherCols);
}
public static function pivotGet($keyCol, array $keyVals, array $otherCols = [])
{
return parent::pivotGetClass(get_called_class(), $keyCol, $keyVals, $otherCols);
}
/**
* Get a multi-instance object
@ -110,7 +113,7 @@ abstract class Managed_DataObject extends Memcached_DataObject
* Exception is thrown when no entries are found.
*
*/
static function listFind($keyCol, array $keyVals)
public static function listFind($keyCol, array $keyVals)
{
return parent::listFindClass(get_called_class(), $keyCol, $keyVals);
}
@ -128,7 +131,7 @@ abstract class Managed_DataObject extends Memcached_DataObject
* @return array with an get_called_class() object for each $keyVals entry
*
*/
static function listGet($keyCol, array $keyVals)
public static function listGet($keyCol, array $keyVals)
{
return parent::listGetClass(get_called_class(), $keyCol, $keyVals);
}
@ -149,11 +152,11 @@ abstract class Managed_DataObject extends Memcached_DataObject
* get/set an array of table primary keys
*
* Key info is pulled from the table definition array.
*
*
* @access private
* @return array
*/
function keys()
public function keys()
{
return array_keys($this->keyTypes());
}
@ -167,7 +170,7 @@ abstract class Managed_DataObject extends Memcached_DataObject
* @return array (column,use_native,sequence_name)
*/
function sequenceKey()
public function sequenceKey()
{
$table = static::schemaDef();
foreach ($table['fields'] as $name => $column) {
@ -191,7 +194,7 @@ abstract class Managed_DataObject extends Memcached_DataObject
* @return array key definitions
*/
function keyTypes()
public function keyTypes()
{
$table = static::schemaDef();
$keys = array();
@ -218,16 +221,17 @@ abstract class Managed_DataObject extends Memcached_DataObject
* @param array $column
* @return int
*/
function columnBitmap($column)
public function columnBitmap($column)
{
$type = $column['type'];
// For quoting style...
$intTypes = array('int',
'integer',
'float',
'serial',
'numeric');
$intTypes = [
'int',
'float',
'serial',
'numeric'
];
if (in_array($type, $intTypes)) {
$style = DB_DATAOBJECT_INT;
} else {
@ -235,12 +239,15 @@ abstract class Managed_DataObject extends Memcached_DataObject
}
// Data type formatting style...
$formatStyles = array('blob' => DB_DATAOBJECT_BLOB,
'text' => DB_DATAOBJECT_TXT,
'date' => DB_DATAOBJECT_DATE,
'time' => DB_DATAOBJECT_TIME,
'datetime' => DB_DATAOBJECT_DATE | DB_DATAOBJECT_TIME,
'timestamp' => DB_DATAOBJECT_MYSQLTIMESTAMP);
$formatStyles = [
'blob' => DB_DATAOBJECT_BLOB,
'text' => DB_DATAOBJECT_TXT,
'bool' => DB_DATAOBJECT_BOOL,
'date' => DB_DATAOBJECT_DATE,
'time' => DB_DATAOBJECT_TIME,
'datetime' => DB_DATAOBJECT_DATE | DB_DATAOBJECT_TIME,
'timestamp' => DB_DATAOBJECT_MYSQLTIMESTAMP,
];
if (isset($formatStyles[$type])) {
$style |= $formatStyles[$type];
@ -254,7 +261,7 @@ abstract class Managed_DataObject extends Memcached_DataObject
return $style;
}
function links()
public function links()
{
$links = array();
@ -277,7 +284,7 @@ abstract class Managed_DataObject extends Memcached_DataObject
*
* @return array of strings
*/
function _allCacheKeys()
public function _allCacheKeys()
{
$table = static::schemaDef();
$ckeys = array();
@ -322,7 +329,7 @@ abstract class Managed_DataObject extends Memcached_DataObject
* @return Managed_DataObject of the get_called_class() type
* @throws NoResultException if no object with that primary key
*/
static function getByPK(array $vals)
public static function getByPK(array $vals)
{
$classname = get_called_class();
@ -356,7 +363,7 @@ abstract class Managed_DataObject extends Memcached_DataObject
* @return Managed_DataObject of the get_called_class() type
* @throws NoResultException if no object with that primary key
*/
static function getByKeys(array $vals)
public static function getByKeys(array $vals)
{
$classname = get_called_class();
@ -381,7 +388,7 @@ abstract class Managed_DataObject extends Memcached_DataObject
return $object;
}
static function getByID($id)
public static function getByID($id)
{
if (!property_exists(get_called_class(), 'id')) {
throw new ServerException('Trying to get undefined property of dataobject class.');
@ -394,7 +401,7 @@ abstract class Managed_DataObject extends Memcached_DataObject
return static::getByPK(array('id' => $id));
}
static function getByUri($uri)
public static function getByUri($uri)
{
if (!property_exists(get_called_class(), 'uri')) {
throw new ServerException('Trying to get undefined property of dataobject class.');
@ -537,18 +544,20 @@ abstract class Managed_DataObject extends Memcached_DataObject
$pid = $schema['primary key'];
unset($schema);
}
$pidWhere = array();
foreach((array)$pid as $pidCol) {
$pidWhere = [];
foreach ((array) $pid as $pidCol) {
$pidWhere[] = sprintf('%1$s = %2$s', $pidCol, $this->_quote($orig->$pidCol));
}
if (empty($pidWhere)) {
throw new ServerException('No primary ID column(s) set for updateWithKeys');
}
$qry = sprintf('UPDATE %1$s SET %2$s WHERE %3$s',
common_database_tablename($this->tableName()),
implode(', ', $parts),
implode(' AND ', $pidWhere));
$qry = sprintf(
'UPDATE %1$s SET %2$s WHERE %3$s',
$this->escapedTableName(),
implode(', ', $parts),
implode(' AND ', $pidWhere)
);
$result = $this->query($qry);
if ($result === false) {
@ -576,21 +585,23 @@ abstract class Managed_DataObject extends Memcached_DataObject
return $result;
}
static public function beforeSchemaUpdate()
public static function beforeSchemaUpdate()
{
// NOOP
}
static function newUri(Profile $actor, Managed_DataObject $object, $created=null)
public static function newUri(Profile $actor, Managed_DataObject $object, $created = null)
{
if (is_null($created)) {
$created = common_sql_now();
}
return TagURI::mint(strtolower(get_called_class()).':%d:%s:%d:%s',
$actor->getID(),
ActivityUtils::resolveUri($object->getObjectType(), true),
$object->getID(),
common_date_iso8601($created));
return TagURI::mint(
strtolower(get_called_class()) . ':%d:%s:%d:%s',
$actor->getID(),
ActivityUtils::resolveUri($object->getObjectType(), true),
$object->getID(),
common_date_iso8601($created)
);
}
protected function onInsert()

View File

@ -1,23 +1,25 @@
<?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/>.
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* @copyright 2008, 2009 StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('GNUSOCIAL')) { exit(1); }
defined('GNUSOCIAL') || die();
class Memcached_DataObject extends Safe_DataObject
{
@ -30,7 +32,7 @@ class Memcached_DataObject extends Safe_DataObject
* @param mixed $v key field value, or leave out for primary key lookup
* @return mixed Memcached_DataObject subtype or false
*/
static function getClassKV($cls, $k, $v=null)
public static function getClassKV($cls, $k, $v = null)
{
if (is_null($v)) {
$v = $k;
@ -71,7 +73,7 @@ class Memcached_DataObject extends Safe_DataObject
*
* @return array Array of objects, in order
*/
static function multiGetClass($cls, $keyCol, array $keyVals, $skipNulls=true)
public static function multiGetClass($cls, $keyCol, array $keyVals, $skipNulls = true)
{
$obj = new $cls;
@ -100,8 +102,27 @@ class Memcached_DataObject extends Safe_DataObject
$keyVals[$key] = $obj->escape($val);
}
// FIND_IN_SET will make sure we keep the desired order
$obj->orderBy(sprintf("FIND_IN_SET(%s, '%s')", $keyCol, implode(',', $keyVals)));
switch (common_config('db', 'type')) {
case 'pgsql':
// "position" will make sure we keep the desired order
$obj->orderBy(sprintf(
"position(',' || CAST(%s AS text) || ',' IN ',%s,')",
$keyCol,
implode(',', $keyVals)
));
break;
case 'mysql':
// "find_in_set" will make sure we keep the desired order
$obj->orderBy(sprintf(
"find_in_set(%s, '%s')",
$keyCol,
implode(',', $keyVals)
));
break;
default:
throw new ServerException('Unknown DB type selected.');
}
$obj->find();
return $obj;
@ -117,7 +138,7 @@ class Memcached_DataObject extends Safe_DataObject
*
* @return array Array mapping $keyVals to objects, or null if not found
*/
static function pivotGetClass($cls, $keyCol, array $keyVals, array $otherCols = array())
public static function pivotGetClass($cls, $keyCol, array $keyVals, array $otherCols = [])
{
if (is_array($keyCol)) {
foreach ($keyVals as $keyVal) {
@ -130,7 +151,6 @@ class Memcached_DataObject extends Safe_DataObject
$toFetch = array();
foreach ($keyVals as $keyVal) {
if (is_array($keyCol)) {
$kv = array_combine($keyCol, $keyVal);
} else {
@ -147,7 +167,7 @@ class Memcached_DataObject extends Safe_DataObject
} else {
$result[$keyVal] = $i;
}
} else if (!empty($keyVal)) {
} elseif (!empty($keyVal)) {
$toFetch[] = $keyVal;
}
}
@ -207,7 +227,7 @@ class Memcached_DataObject extends Safe_DataObject
return $result;
}
static function _inMultiKey($i, $cols, $values)
public static function _inMultiKey($i, $cols, $values)
{
$types = array();
@ -255,7 +275,7 @@ class Memcached_DataObject extends Safe_DataObject
return $query;
}
static function pkeyColsClass($cls)
public static function pkeyColsClass($cls)
{
$i = new $cls;
$types = $i->keyTypes();
@ -272,7 +292,7 @@ class Memcached_DataObject extends Safe_DataObject
return $pkey;
}
static function listFindClass($cls, $keyCol, array $keyVals)
public static function listFindClass($cls, $keyCol, array $keyVals)
{
$i = new $cls;
$i->whereAddIn($keyCol, $keyVals, $i->columnType($keyCol));
@ -283,7 +303,7 @@ class Memcached_DataObject extends Safe_DataObject
return $i;
}
static function listGetClass($cls, $keyCol, array $keyVals)
public static function listGetClass($cls, $keyCol, array $keyVals)
{
$pkeyMap = array_fill_keys($keyVals, array());
$result = array_fill_keys($keyVals, array());
@ -296,7 +316,7 @@ class Memcached_DataObject extends Safe_DataObject
// We only cache keys -- not objects!
foreach ($keyVals as $keyVal) {
$l = self::cacheGet(sprintf("%s:list-ids:%s:%s", strtolower($cls), $keyCol, $keyVal));
$l = self::cacheGet(sprintf('%s:list-ids:%s:%s', strtolower($cls), $keyCol, $keyVal));
if ($l !== false) {
$pkeyMap[$keyVal] = $l;
foreach ($l as $pkey) {
@ -312,7 +332,7 @@ class Memcached_DataObject extends Safe_DataObject
foreach ($pkeyMap as $keyVal => $pkeyList) {
foreach ($pkeyList as $pkeyVal) {
$i = $keyResults[implode(',',$pkeyVal)];
$i = $keyResults[implode(',', $pkeyVal)];
if (!empty($i)) {
$result[$keyVal][] = $i;
}
@ -338,15 +358,17 @@ class Memcached_DataObject extends Safe_DataObject
// no results found for our keyVals, so we leave them as empty arrays
}
foreach ($toFetch as $keyVal) {
self::cacheSet(sprintf("%s:list-ids:%s:%s", strtolower($cls), $keyCol, $keyVal),
$pkeyMap[$keyVal]);
self::cacheSet(
sprintf("%s:list-ids:%s:%s", strtolower($cls), $keyCol, $keyVal),
$pkeyMap[$keyVal]
);
}
}
return $result;
}
function columnType($columnName)
public function columnType($columnName)
{
$keys = $this->table();
if (!array_key_exists($columnName, $keys)) {
@ -365,7 +387,7 @@ class Memcached_DataObject extends Safe_DataObject
/**
* @todo FIXME: Should this return false on lookup fail to match getKV?
*/
static function pkeyGetClass($cls, array $kv)
public static function pkeyGetClass($cls, array $kv)
{
$i = self::multicache($cls, $kv);
if ($i !== false) { // false == cache miss
@ -395,7 +417,7 @@ class Memcached_DataObject extends Safe_DataObject
}
}
function insert()
public function insert()
{
$result = parent::insert();
if ($result) {
@ -405,7 +427,7 @@ class Memcached_DataObject extends Safe_DataObject
return $result;
}
function update($dataObject=false)
public function update($dataObject = false)
{
if (is_object($dataObject) && $dataObject instanceof Memcached_DataObject) {
$dataObject->decache(); # might be different keys
@ -418,17 +440,19 @@ class Memcached_DataObject extends Safe_DataObject
return $result;
}
function delete($useWhere=false)
public function delete($useWhere = false)
{
$this->decache(); # while we still have the values!
return parent::delete($useWhere);
}
static function memcache() {
public static function memcache()
{
return Cache::instance();
}
static function cacheKey($cls, $k, $v) {
public static function cacheKey($cls, $k, $v)
{
if (is_object($cls) || is_object($k) || (is_object($v) && !($v instanceof DB_DataObject_Cast))) {
$e = new Exception();
common_log(LOG_ERR, __METHOD__ . ' object in param: ' .
@ -438,7 +462,8 @@ class Memcached_DataObject extends Safe_DataObject
return Cache::key(strtolower($cls).':'.$k.':'.$vstr);
}
static function getcached($cls, $k, $v) {
public static function getcached($cls, $k, $v)
{
$c = self::memcache();
if (!$c) {
return false;
@ -456,7 +481,7 @@ class Memcached_DataObject extends Safe_DataObject
}
}
function keyTypes()
public function keyTypes()
{
// ini-based classes return number-indexed arrays. handbuilt
// classes return column => keytype. Make this uniform.
@ -472,18 +497,17 @@ class Memcached_DataObject extends Safe_DataObject
global $_DB_DATAOBJECT;
if (!isset($_DB_DATAOBJECT['INI'][$this->_database][$this->tableName()."__keys"])) {
$this->databaseStructure();
}
return $_DB_DATAOBJECT['INI'][$this->_database][$this->tableName()."__keys"];
}
function encache()
public function encache()
{
$c = self::memcache();
if (!$c) {
return false;
} else if ($this->tableName() == 'user' && is_object($this->id)) {
} elseif ($this->tableName() === 'user' && is_object($this->id)) {
// Special case for User bug
$e = new Exception();
common_log(LOG_ERR, __METHOD__ . ' caching user with User object as ID ' .
@ -498,7 +522,7 @@ class Memcached_DataObject extends Safe_DataObject
}
}
function decache()
public function decache()
{
$c = self::memcache();
@ -513,7 +537,7 @@ class Memcached_DataObject extends Safe_DataObject
}
}
function _allCacheKeys()
public function _allCacheKeys()
{
$ckeys = array();
@ -524,7 +548,6 @@ class Memcached_DataObject extends Safe_DataObject
$pval = array();
foreach ($types as $key => $type) {
assert(!empty($key));
if ($type == 'U') {
@ -532,7 +555,7 @@ class Memcached_DataObject extends Safe_DataObject
continue;
}
$ckeys[] = self::cacheKey($this->tableName(), $key, self::valueString($this->$key));
} else if ($type == 'K' || $type == 'N') {
} elseif (in_array($type, ['K', 'N'])) {
$pkey[] = $key;
$pval[] = self::valueString($this->$key);
} else {
@ -552,7 +575,7 @@ class Memcached_DataObject extends Safe_DataObject
return $ckeys;
}
static function multicache($cls, $kv)
public static function multicache($cls, $kv)
{
ksort($kv);
$c = self::memcache();
@ -563,7 +586,7 @@ class Memcached_DataObject extends Safe_DataObject
}
}
static function multicacheKey($cls, $kv)
public static function multicacheKey($cls, $kv)
{
ksort($kv);
$pkeys = implode(',', array_keys($kv));
@ -571,30 +594,35 @@ class Memcached_DataObject extends Safe_DataObject
return self::cacheKey($cls, $pkeys, $pvals);
}
function getSearchEngine($table)
public function getSearchEngine($table)
{
require_once INSTALLDIR . '/lib/search/search_engines.php';
if (Event::handle('GetSearchEngine', array($this, $table, &$search_engine))) {
if ('mysql' === common_config('db', 'type')) {
$type = common_config('search', 'type');
if ($type == 'like') {
$search_engine = new MySQLLikeSearch($this, $table);
} else if ($type == 'fulltext') {
$search_engine = new MySQLSearch($this, $table);
} else {
// Low level exception. No need for i18n as discussed with Brion.
throw new ServerException('Unknown search type: ' . $type);
if (Event::handle('GetSearchEngine', [$this, $table, &$search_engine])) {
$type = common_config('search', 'type');
if ($type === 'like') {
$search_engine = new SQLLikeSearch($this, $table);
} elseif ($type === 'fulltext') {
switch (common_config('db', 'type')) {
case 'pgsql':
$search_engine = new PostgreSQLSearch($this, $table);
break;
case 'mysql':
$search_engine = new MySQLSearch($this, $table);
break;
default:
throw new ServerException('Unknown DB type selected.');
}
} else {
$search_engine = new PGSearch($this, $table);
// Low level exception. No need for i18n as discussed with Brion.
throw new ServerException('Unknown search type: ' . $type);
}
}
return $search_engine;
}
static function cachedQuery($cls, $qry, $expiry=3600)
public static function cachedQuery($cls, $qry, $expiry = 3600)
{
$c = self::memcache();
if (!$c) {
@ -631,7 +659,7 @@ class Memcached_DataObject extends Safe_DataObject
* @access private
* @return mixed none or PEAR_Error
*/
function _query($string)
public function _query($string)
{
if (common_config('db', 'annotate_queries')) {
$string = $this->annotateQuery($string);
@ -680,7 +708,7 @@ class Memcached_DataObject extends Safe_DataObject
* @param string $string SQL query string
* @return string SQL query string, with a comment in it
*/
function annotateQuery($string)
public function annotateQuery($string)
{
$ignore = array('annotateQuery',
'_query',
@ -707,7 +735,7 @@ class Memcached_DataObject extends Safe_DataObject
}
$here = $frame['class'] . '::' . $func;
break;
} else if (isset($frame['type']) && $frame['type'] == '->') {
} elseif (isset($frame['type']) && $frame['type'] === '->') {
if ($frame['object'] === $this && in_array($func, $ignore)) {
continue;
}
@ -736,7 +764,7 @@ class Memcached_DataObject extends Safe_DataObject
// Sanitize a query for logging
// @fixme don't trim spaces in string literals
function sanitizeQuery($string)
public function sanitizeQuery($string)
{
$string = preg_replace('/\s+/', ' ', $string);
$string = trim($string);
@ -746,7 +774,7 @@ class Memcached_DataObject extends Safe_DataObject
// We overload so that 'SET NAMES "utf8mb4"' is called for
// each connection
function _connect()
public function _connect()
{
global $_DB_DATAOBJECT, $_PEAR;
@ -757,7 +785,7 @@ class Memcached_DataObject extends Safe_DataObject
$exists = true;
} else {
$exists = false;
}
}
// @fixme horrible evil hack!
//
@ -794,7 +822,7 @@ class Memcached_DataObject extends Safe_DataObject
if (!empty($conn)) {
if ($DB instanceof DB_mysqli || $DB instanceof MDB2_Driver_mysqli) {
mysqli_set_charset($conn, 'utf8mb4');
} else if ($DB instanceof DB_mysql || $DB instanceof MDB2_Driver_mysql) {
} elseif ($DB instanceof DB_mysql || $DB instanceof MDB2_Driver_mysql) {
mysql_set_charset('utf8mb4', $conn);
}
}
@ -810,7 +838,7 @@ class Memcached_DataObject extends Safe_DataObject
// XXX: largely cadged from DB_DataObject
function _getDbDsnMD5()
public function _getDbDsnMD5()
{
if ($this->_database_dsn_md5) {
return $this->_database_dsn_md5;
@ -828,7 +856,7 @@ class Memcached_DataObject extends Safe_DataObject
return $sum;
}
function _getDbDsn()
public function _getDbDsn()
{
global $_DB_DATAOBJECT;
@ -843,14 +871,13 @@ class Memcached_DataObject extends Safe_DataObject
$dsn = isset($this->_database_dsn) ? $this->_database_dsn : null;
if (!$dsn) {
if (!$this->_database) {
$this->_database = isset($options["table_{$this->tableName()}"]) ? $options["table_{$this->tableName()}"] : null;
}
if ($this->_database && !empty($options["database_{$this->_database}"])) {
if ($this->_database && !empty($options["database_{$this->_database}"])) {
$dsn = $options["database_{$this->_database}"];
} else if (!empty($options['database'])) {
} elseif (!empty($options['database'])) {
$dsn = $options['database'];
}
}
@ -863,7 +890,7 @@ class Memcached_DataObject extends Safe_DataObject
return $dsn;
}
static function blow()
public static function blow()
{
$c = self::memcache();
@ -882,7 +909,7 @@ class Memcached_DataObject extends Safe_DataObject
return $c->delete($cacheKey);
}
function fixupTimestamps()
public function fixupTimestamps()
{
// Fake up timestamp columns
$columns = $this->table();
@ -893,12 +920,12 @@ class Memcached_DataObject extends Safe_DataObject
}
}
function debugDump()
public function debugDump()
{
common_debug("debugDump: " . common_log_objstring($this));
}
function raiseError($message, $type = null, $behaviour = null)
public function raiseError($message, $type = null, $behavior = null)
{
$id = get_class($this);
if (!empty($this->id)) {
@ -911,7 +938,7 @@ class Memcached_DataObject extends Safe_DataObject
throw new ServerException("[$id] DB_DataObject error [$type]: $message");
}
static function cacheGet($keyPart)
public static function cacheGet($keyPart)
{
$c = self::memcache();
@ -924,7 +951,7 @@ class Memcached_DataObject extends Safe_DataObject
return $c->get($cacheKey);
}
static function cacheSet($keyPart, $value, $flag=null, $expiry=null)
public static function cacheSet($keyPart, $value, $flag = null, $expiry = null)
{
$c = self::memcache();
@ -937,7 +964,7 @@ class Memcached_DataObject extends Safe_DataObject
return $c->set($cacheKey, $value, $flag, $expiry);
}
static function valueString($v)
public static function valueString($v)
{
$vstr = null;
if (is_object($v) && $v instanceof DB_DataObject_Cast) {

File diff suppressed because it is too large Load Diff

View File

@ -1,32 +1,32 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* GNU social
*
* Data class for Notice preferences
*
* 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 GNUsocial
* @author Mikael Nordfeldth <mmn@hethane.se>
* @copyright 2013 Free Software Foundation, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://www.gnu.org/software/social/
* @author Diogo Cordeiro <diogo@fc.up.pt>
* @copyright 2013 Free Software Foundation, Inc http://www.fsf.org
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
defined('GNUSOCIAL') || die();
class Notice_prefs extends Managed_DataObject
{
public $__table = 'notice_prefs'; // table name
@ -58,7 +58,7 @@ class Notice_prefs extends Managed_DataObject
);
}
static function getNamespacePrefs(Notice $notice, $namespace, array $topic=array())
public static function getNamespacePrefs(Notice $notice, $namespace, array $topic = [])
{
if (empty($topic)) {
$prefs = new Notice_prefs();
@ -76,13 +76,13 @@ class Notice_prefs extends Managed_DataObject
return $prefs;
}
static function getNamespace(Notice $notice, $namespace, array $topic=array())
public static function getNamespace(Notice $notice, $namespace, array $topic = [])
{
$prefs = self::getNamespacePrefs($notice, $namespace, $topic);
return $prefs->fetchAll();
}
static function getAll(Notice $notice)
public static function getAll(Notice $notice)
{
try {
$prefs = self::listFind('notice_id', array($notice->getID()));
@ -100,13 +100,17 @@ class Notice_prefs extends Managed_DataObject
return $list;
}
static function getTopic(Notice $notice, $namespace, $topic) {
return self::getByPK(array('notice_id' => $notice->getID(),
'namespace' => $namespace,
'topic' => $topic));
public static function getTopic(Notice $notice, $namespace, $topic)
{
return self::getByPK([
'notice_id' => $notice->getID(),
'namespace' => $namespace,
'topic' => $topic,
]);
}
static function getData(Notice $notice, $namespace, $topic, $def=null) {
public static function getData(Notice $notice, $namespace, $topic, $def = null)
{
try {
$pref = self::getTopic($notice, $namespace, $topic);
} catch (NoResultException $e) {
@ -120,7 +124,8 @@ class Notice_prefs extends Managed_DataObject
return $pref->data;
}
static function getConfigData(Notice $notice, $namespace, $topic) {
public static function getConfigData(Notice $notice, $namespace, $topic)
{
try {
$data = self::getData($notice, $namespace, $topic);
} catch (NoResultException $e) {
@ -140,14 +145,15 @@ class Notice_prefs extends Managed_DataObject
* @return true if changes are made, false if no action taken
* @throws ServerException if preference could not be saved
*/
static function setData(Notice $notice, $namespace, $topic, $data=null) {
public static function setData(Notice $notice, $namespace, $topic, $data = null)
{
try {
$pref = self::getTopic($notice, $namespace, $topic);
if (is_null($data)) {
$pref->delete();
} else {
$orig = clone($pref);
$pref->data = $data;
$pref->data = DB_DataObject_Cast::blob($data);
$pref->update($orig);
}
return true;
@ -161,7 +167,7 @@ class Notice_prefs extends Managed_DataObject
$pref->notice_id = $notice->getID();
$pref->namespace = $namespace;
$pref->topic = $topic;
$pref->data = $data;
$pref->data = DB_DataObject_Cast::blob($data);
$pref->created = common_sql_now();
if ($pref->insert() === false) {

View File

@ -1,9 +1,26 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
defined('GNUSOCIAL') || die();
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
/**
* Table Definition for notice_source
*/
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
class Notice_source extends Managed_DataObject
{
###START_AUTOCODE
@ -26,7 +43,7 @@ class Notice_source extends Managed_DataObject
'code' => array('type' => 'varchar', 'length' => 32, 'not null' => true, 'description' => 'source code'),
'name' => array('type' => 'varchar', 'length' => 191, 'not null' => true, 'description' => 'name of the source'),
'url' => array('type' => 'varchar', 'length' => 191, 'not null' => true, 'description' => 'url to link to'),
'notice_id' => array('type' => 'int', 'not null' => true, 'description' => 'date this record was created'),
'notice_id' => array('type' => 'int', 'not null' => true, 'default' => 0, 'description' => 'date this record was created'),
'created' => array('type' => 'datetime', 'not null' => true, 'default' => '0000-00-00 00:00:00', 'description' => 'date this record was created'),
'modified' => array('type' => 'datetime', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was modified'),
),

View File

@ -1,9 +1,26 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
defined('GNUSOCIAL') || die();
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
/**
* Table Definition for oauth_application_user
*/
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
class Oauth_application_user extends Managed_DataObject
{
###START_AUTOCODE
@ -39,7 +56,7 @@ class Oauth_application_user extends Managed_DataObject
);
}
static function getByUserAndToken($user, $token)
public static function getByUserAndToken($user, $token)
{
if (empty($user) || empty($token)) {
return null;
@ -56,7 +73,7 @@ class Oauth_application_user extends Managed_DataObject
return empty($result) ? null : $oau;
}
function updateKeys(&$orig)
public function updateKeys(&$orig)
{
$this->_connect();
$parts = array();
@ -72,13 +89,11 @@ class Oauth_application_user extends Managed_DataObject
$toupdate = implode(', ', $parts);
$table = $this->tableName();
if(common_config('db','quote_identifiers')) {
$table = '"' . $table . '"';
}
$qry = 'UPDATE ' . $table . ' SET ' . $toupdate .
' WHERE profile_id = ' . $orig->profile_id
. ' AND application_id = ' . $orig->application_id
. " AND token = '$orig->token'";
$tableName = $this->escapedTableName();
$qry = 'UPDATE ' . $tableName . ' SET ' . $toupdate .
' WHERE profile_id = ' . $orig->profile_id .
' AND application_id = ' . $orig->application_id .
" AND token = '" . $orig->token . "'";
$orig->decache();
$result = $this->query($qry);
if ($result) {

View File

@ -1,9 +1,26 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
defined('GNUSOCIAL') || die();
require_once INSTALLDIR . '/classes/Memcached_DataObject.php';
/**
* Table Definition for oauth_association
*/
require_once INSTALLDIR . '/classes/Memcached_DataObject.php';
class Oauth_token_association extends Managed_DataObject
{
###START_AUTOCODE
@ -19,7 +36,7 @@ class Oauth_token_association extends Managed_DataObject
/* the code above is auto generated do not remove the tag below */
###END_AUTOCODE
static function getByUserAndToken($user, $token)
public static function getByUserAndToken($user, $token)
{
if (empty($user) || empty($token)) {
return null;
@ -49,8 +66,8 @@ class Oauth_token_association extends Managed_DataObject
),
'primary key' => array('profile_id', 'application_id', 'token'),
'foreign keys' => array(
'oauth_token_association_profile_fkey' => array('profile_id', array('profile' => 'id')),
'oauth_token_association_application_fkey' => array('application_id', array('application' => 'id')),
'oauth_token_association_profile_fkey' => array('profile', array('profile_id' => 'id')),
'oauth_token_association_application_fkey' => array('oauth_application', array('application_id' => 'id')),
)
);
}

View File

@ -1,48 +1,36 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2011, StatusNet, Inc.
*
* Older-style UI preferences
*
* 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 UI
* @package StatusNet
* @package GNUsocial
* @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/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('STATUSNET')) {
// This check helps protect against security problems;
// your code file can't be executed directly from the web.
exit(1);
}
defined('GNUSOCIAL') || die();
/**
* Separate table for storing UI preferences
*
* @category UI
* @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/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
class Old_school_prefs extends Managed_DataObject
@ -60,17 +48,14 @@ class Old_school_prefs extends Managed_DataObject
return array(
'fields' => array(
'user_id' => array('type' => 'int', 'not null' => true, 'description' => 'user who has the preference'),
'stream_mode_only' => array('type' => 'int',
'size' => 'tiny',
'default' => 1,
'stream_mode_only' => array('type' => 'bool',
'default' => true,
'description' => 'No conversation streams'),
'conversation_tree' => array('type' => 'int',
'size' => 'tiny',
'default' => 1,
'conversation_tree' => array('type' => 'bool',
'default' => true,
'description' => 'Hierarchical tree view for conversations'),
'stream_nicknames' => array('type' => 'int',
'size' => 'tiny',
'default' => 1,
'stream_nicknames' => array('type' => 'bool',
'default' => true,
'description' => 'Show nicknames for authors and addressees in streams'),
'created' => array('type' => 'datetime', 'not null' => true, 'default' => '0000-00-00 00:00:00', 'description' => 'date this record was created'),
'modified' => array('type' => 'datetime', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was modified'),

View File

@ -1,23 +1,25 @@
<?php
/*
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2008-2011, 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/>.
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* @copyright 2008-2011 StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('GNUSOCIAL')) { exit(1); }
defined('GNUSOCIAL') || die();
/**
* Table Definition for profile
@ -81,7 +83,7 @@ class Profile extends Managed_DataObject
throw new NoSuchUserException(array('email'=>$email));
}
return $user->getProfile();
}
}
protected $_user = array();
@ -202,16 +204,16 @@ class Profile extends Managed_DataObject
*
* @return string
*/
function getBestName()
public function getBestName()
{
return ($this->fullname) ? $this->fullname : $this->nickname;
}
/**
* Takes the currently scoped profile into account to give a name
* Takes the currently scoped profile into account to give a name
* to list in notice streams. Preferences may differ between profiles.
*/
function getStreamName()
public function getStreamName()
{
$user = common_current_user();
if ($user instanceof User && $user->streamNicknames()) {
@ -228,7 +230,7 @@ class Profile extends Managed_DataObject
*
* @return string
*/
function getFancyName()
public function getFancyName()
{
$uri = null;
try {
@ -243,7 +245,7 @@ class Profile extends Managed_DataObject
if (mb_strlen($this->getFullname()) > 0) {
// TRANS: The "fancy name": Full name of a profile or group (%1$s) followed by some URI (%2$s) in parentheses.
return sprintf(_m('FANCYNAME','%1$s (%2$s)'), $this->getFullname(), $uri);
return sprintf(_m('FANCYNAME', '%1$s (%2$s)'), $this->getFullname(), $uri);
} else {
return $uri;
}
@ -254,7 +256,7 @@ class Profile extends Managed_DataObject
*
* @return mixed Notice or null
*/
function getCurrentNotice(Profile $scoped=null)
public function getCurrentNotice(Profile $scoped = null)
{
try {
$notice = $this->getNotices(0, 1, 0, 0, $scoped);
@ -271,16 +273,16 @@ class Profile extends Managed_DataObject
// Maybe we should let this through if it's handled well upstream
return null;
}
return null;
}
function getReplies($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0)
public function getReplies($offset = 0, $limit = NOTICES_PER_PAGE, $since_id = 0, $before_id = 0)
{
return Reply::stream($this->getID(), $offset, $limit, $since_id, $before_id);
}
function getTaggedNotices($tag, $offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $max_id=0)
public function getTaggedNotices($tag, $offset = 0, $limit = NOTICES_PER_PAGE, $since_id = 0, $max_id = 0)
{
//FIXME: Get Profile::current() some other way to avoid possible
// confusion between current session profile and background processing.
@ -289,39 +291,39 @@ class Profile extends Managed_DataObject
return $stream->getNotices($offset, $limit, $since_id, $max_id);
}
function getNotices($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $max_id=0, Profile $scoped=null)
public function getNotices($offset = 0, $limit = NOTICES_PER_PAGE, $since_id = 0, $max_id = 0, Profile $scoped = null)
{
$stream = new ProfileNoticeStream($this, $scoped);
return $stream->getNotices($offset, $limit, $since_id, $max_id);
}
function isMember(User_group $group)
public function isMember(User_group $group)
{
$groups = $this->getGroups(0, null);
$groups = $this->getGroups(0, null);
while ($groups instanceof User_group && $groups->fetch()) {
if ($groups->id == $group->id) {
return true;
}
}
return false;
if ($groups->id == $group->id) {
return true;
}
}
return false;
}
function isAdmin(User_group $group)
public function isAdmin(User_group $group)
{
$gm = Group_member::pkeyGet(array('profile_id' => $this->id,
'group_id' => $group->id));
return (!empty($gm) && $gm->is_admin);
}
function isPendingMember($group)
public function isPendingMember($group)
{
$request = Group_join_queue::pkeyGet(array('profile_id' => $this->id,
'group_id' => $group->id));
return !empty($request);
}
function getGroups($offset=0, $limit=PROFILES_PER_PAGE)
public function getGroups($offset = 0, $limit = PROFILES_PER_PAGE)
{
$ids = array();
@ -356,14 +358,15 @@ class Profile extends Managed_DataObject
}
}
function getGroupCount() {
public function getGroupCount()
{
$groups = $this->getGroups(0, null);
return $groups instanceof User_group
? $groups->N
: 0;
}
function isTagged($peopletag)
public function isTagged($peopletag)
{
$tag = Profile_tag::pkeyGet(array('tagger' => $peopletag->tagger,
'tagged' => $this->id,
@ -371,7 +374,7 @@ class Profile extends Managed_DataObject
return !empty($tag);
}
function canTag($tagged)
public function canTag($tagged)
{
if (empty($tagged)) {
return false;
@ -395,16 +398,16 @@ class Profile extends Managed_DataObject
if ($local) {
return true;
}
} else if ($subs) {
} elseif ($subs) {
return (Subscription::exists($this, $tagged) ||
Subscription::exists($tagged, $this));
} else if ($remote) {
} elseif ($remote) {
return true;
}
return false;
}
function getLists(Profile $scoped=null, $offset=0, $limit=null, $since_id=0, $max_id=0)
public function getLists(Profile $scoped = null, $offset = 0, $limit = null, $since_id = 0, $max_id = 0)
{
$ids = array();
@ -421,15 +424,15 @@ class Profile extends Managed_DataObject
$list->tagger = $this->id;
$list->selectAdd('id as "cursor"');
if ($since_id>0) {
$list->whereAdd('id > '.$since_id);
if ($since_id > 0) {
$list->whereAdd('id > ' . $since_id);
}
if ($max_id>0) {
$list->whereAdd('id <= '.$max_id);
if ($max_id > 0) {
$list->whereAdd('id <= ' . $max_id);
}
if($offset>=0 && !is_null($limit)) {
if ($offset >= 0 && !is_null($limit)) {
$list->limit($offset, $limit);
}
@ -452,7 +455,6 @@ class Profile extends Managed_DataObject
$list = Profile_list::getKV('id', $id);
if (!empty($list) &&
($showPrivate || !$list->private)) {
if (!isset($list->cursor)) {
$list->cursor = $list->id;
}
@ -476,33 +478,47 @@ class Profile extends Managed_DataObject
* @return Profile_list resulting lists
*/
function getOtherTags(Profile $scoped=null, $offset=0, $limit=null, $since_id=0, $max_id=0)
public function getOtherTags(Profile $scoped = null, int $offset = 0, ?int $limit = null, int $since = 0, int $upto = 0)
{
$list = new Profile_list();
$qry = sprintf('select profile_list.*, unix_timestamp(profile_tag.modified) as "cursor" ' .
'from profile_tag join profile_list '.
'on (profile_tag.tagger = profile_list.tagger ' .
' and profile_tag.tag = profile_list.tag) ' .
'where profile_tag.tagged = %d ',
$this->id);
if (common_config('db', 'type') !== 'mysql') {
$cursor = sprintf(
'((EXTRACT(DAY %1$s) * 24 + EXTRACT(HOUR %1$s)) * 60 + ' .
'EXTRACT(MINUTE %1$s)) * 60 + FLOOR(EXTRACT(SECOND %1$s)) AS "cursor"',
"FROM (profile_tag.modified - TIMESTAMP '1970-01-01 00:00:00')"
);
} else {
// The SQL/Foundation conforming implementation above doesn't work on MariaDB/MySQL
$cursor = "timestampdiff(SECOND, '1970-01-01', profile_tag.modified) AS `cursor`";
}
$qry = sprintf(
'SELECT profile_list.*, ' . $cursor . ' ' .
'FROM profile_tag INNER JOIN profile_list ' .
'ON (profile_tag.tagger = profile_list.tagger ' .
' AND profile_tag.tag = profile_list.tag) ' .
'WHERE profile_tag.tagged = %d ',
$this->id
);
if (!is_null($scoped)) {
$qry .= sprintf('AND ( ( profile_list.private = false ) ' .
'OR ( profile_list.tagger = %d AND ' .
'profile_list.private = true ) )',
$scoped->getID());
$qry .= sprintf(
'AND ( profile_list.private = false ' .
'OR ( profile_list.tagger = %d AND ' .
'profile_list.private = TRUE ) )',
$scoped->getID()
);
} else {
$qry .= 'AND profile_list.private = 0 ';
$qry .= 'AND profile_list.private = FALSE ';
}
if ($since_id > 0) {
$qry .= sprintf('AND (cursor > %d) ', $since_id);
if ($since > 0) {
$qry .= 'AND cursor > ' . $since . ' ';
}
if ($max_id > 0) {
$qry .= sprintf('AND (cursor < %d) ', $max_id);
if ($upto > 0) {
$qry .= 'AND cursor < ' . $upto . ' ';
}
$qry .= 'ORDER BY profile_tag.modified DESC ';
@ -515,21 +531,21 @@ class Profile extends Managed_DataObject
return $list;
}
function getPrivateTags($offset=0, $limit=null, $since_id=0, $max_id=0)
public function getPrivateTags($offset = 0, $limit = null, $since_id = 0, $max_id = 0)
{
$tags = new Profile_list();
$tags->private = true;
$tags->tagger = $this->id;
if ($since_id>0) {
$tags->whereAdd('id > '.$since_id);
if ($since_id > 0) {
$tags->whereAdd('id > ' . $since_id);
}
if ($max_id>0) {
$tags->whereAdd('id <= '.$max_id);
if ($max_id > 0) {
$tags->whereAdd('id <= ' . $max_id);
}
if($offset>=0 && !is_null($limit)) {
if ($offset >= 0 && !is_null($limit)) {
$tags->limit($offset, $limit);
}
@ -539,13 +555,13 @@ class Profile extends Managed_DataObject
return $tags;
}
function hasLocalTags()
public function hasLocalTags()
{
$tags = new Profile_tag();
$tags->joinAdd(array('tagger', 'user:id'));
$tags->whereAdd('tagged = '.$this->id);
$tags->whereAdd('tagger != '.$this->id);
$tags->whereAdd('tagged = ' . $this->id);
$tags->whereAdd('tagger <> ' . $this->id);
$tags->limit(0, 1);
$tags->fetch();
@ -553,31 +569,38 @@ class Profile extends Managed_DataObject
return ($tags->N == 0) ? false : true;
}
function getTagSubscriptions($offset=0, $limit=null, $since_id=0, $max_id=0)
public function getTagSubscriptions(int $offset = 0, ?int $limit = null, int $since = 0, int $upto = 0)
{
$lists = new Profile_list();
$subs = new Profile_tag_subscription();
$lists->joinAdd(array('id', 'profile_tag_subscription:profile_tag_id'));
$lists->joinAdd(['id', 'profile_tag_subscription:profile_tag_id']);
#@fixme: postgres (round(date_part('epoch', my_date)))
$lists->selectAdd('unix_timestamp(profile_tag_subscription.created) as "cursor"');
if (common_config('db', 'type') !== 'mysql') {
$lists->selectAdd(sprintf(
'((EXTRACT(DAY %1$s) * 24 + EXTRACT(HOUR %1$s)) * 60 + ' .
'EXTRACT(MINUTE %1$s)) * 60 + FLOOR(EXTRACT(SECOND %1$s)) AS "cursor"',
"FROM (profile_tag_subscription.created - TIMESTAMP '1970-01-01 00:00:00')"
));
} else {
$lists->selectAdd("timestampdiff(SECOND, '1970-01-01', profile_tag_subscription.created) AS `cursor`");
}
$lists->whereAdd('profile_tag_subscription.profile_id = '.$this->id);
if ($since_id>0) {
$lists->whereAdd('cursor > '.$since_id);
if ($since > 0) {
$lists->whereAdd('cursor > ' . $since);
}
if ($max_id>0) {
$lists->whereAdd('cursor <= '.$max_id);
if ($upto > 0) {
$lists->whereAdd('cursor <= ' . $upto);
}
if($offset>=0 && !is_null($limit)) {
if ($offset >= 0 && !is_null($limit)) {
$lists->limit($offset, $limit);
}
$lists->orderBy('"cursor" DESC');
$lists->orderBy('profile_tag_subscription.created DESC');
$lists->find();
return $lists;
@ -590,7 +613,7 @@ class Profile extends Managed_DataObject
* @param User_group $group
* @return mixed: Group_member on success, Group_join_queue if pending approval, null on some cancels?
*/
function joinGroup(User_group $group)
public function joinGroup(User_group $group)
{
$join = null;
if ($group->join_policy == User_group::JOIN_POLICY_MODERATE) {
@ -616,7 +639,7 @@ class Profile extends Managed_DataObject
*
* @param User_group $group
*/
function leaveGroup(User_group $group)
public function leaveGroup(User_group $group)
{
if (Event::handle('StartLeaveGroup', array($group, $this))) {
Group_member::leave($group->id, $this->id);
@ -627,12 +650,12 @@ class Profile extends Managed_DataObject
}
}
function avatarUrl($size=AVATAR_PROFILE_SIZE)
public function avatarUrl($size = AVATAR_PROFILE_SIZE)
{
return Avatar::urlByProfile($this, $size);
}
function getSubscribed($offset=0, $limit=null)
public function getSubscribed($offset = 0, $limit = null)
{
$subs = Subscription::getSubscribedIDs($this->id, $offset, $limit);
try {
@ -643,7 +666,7 @@ class Profile extends Managed_DataObject
return $profiles;
}
function getSubscribers($offset=0, $limit=null)
public function getSubscribers($offset = 0, $limit = null)
{
$subs = Subscription::getSubscriberIDs($this->id, $offset, $limit);
try {
@ -654,7 +677,7 @@ class Profile extends Managed_DataObject
return $profiles;
}
function getTaggedSubscribers($tag, $offset=0, $limit=null)
public function getTaggedSubscribers($tag, $offset = 0, $limit = null)
{
$qry =
'SELECT profile.* ' .
@ -664,7 +687,7 @@ class Profile extends Managed_DataObject
'AND profile_tag.tagger = subscription.subscribed) ' .
'WHERE subscription.subscribed = %d ' .
"AND profile_tag.tag = '%s' " .
'AND subscription.subscribed != subscription.subscriber ' .
'AND subscription.subscribed <> subscription.subscriber ' .
'ORDER BY subscription.created DESC ';
if ($offset) {
@ -678,7 +701,7 @@ class Profile extends Managed_DataObject
return $profile;
}
function getTaggedSubscriptions($tag, $offset=0, $limit=null)
public function getTaggedSubscriptions($tag, $offset = 0, $limit = null)
{
$qry =
'SELECT profile.* ' .
@ -688,7 +711,7 @@ class Profile extends Managed_DataObject
'AND profile_tag.tagger = subscription.subscriber) ' .
'WHERE subscription.subscriber = %d ' .
"AND profile_tag.tag = '%s' " .
'AND subscription.subscribed != subscription.subscriber ' .
'AND subscription.subscribed <> subscription.subscriber ' .
'ORDER BY subscription.created DESC ';
$qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
@ -707,7 +730,7 @@ class Profile extends Managed_DataObject
* @param int $limit
* @return Profile
*/
function getRequests($offset=0, $limit=null)
public function getRequests($offset = 0, $limit = null)
{
// FIXME: mysql only
$subqueue = new Profile();
@ -721,7 +744,7 @@ class Profile extends Managed_DataObject
return $subqueue;
}
function subscriptionCount()
public function subscriptionCount()
{
$c = Cache::instance();
@ -749,7 +772,7 @@ class Profile extends Managed_DataObject
return $cnt;
}
function subscriberCount()
public function subscriberCount()
{
$c = Cache::instance();
if (!empty($c)) {
@ -761,8 +784,8 @@ class Profile extends Managed_DataObject
$sub = new Subscription();
$sub->subscribed = $this->id;
$sub->whereAdd('subscriber != subscribed');
$cnt = (int) $sub->count('distinct subscriber');
$sub->whereAdd('subscriber <> subscribed');
$cnt = (int) $sub->count('DISTINCT subscriber');
if (!empty($c)) {
$c->set(Cache::key('profile:subscriber_count:'.$this->id), $cnt);
@ -777,12 +800,12 @@ class Profile extends Managed_DataObject
* @param Profile $other
* @return boolean
*/
function isSubscribed(Profile $other)
public function isSubscribed(Profile $other)
{
return Subscription::exists($this, $other);
}
function readableBy(Profile $other=null)
public function readableBy(Profile $other = null)
{
// If it's not a private stream, it's readable by anyone
if (!$this->isPrivateStream()) {
@ -793,7 +816,7 @@ class Profile extends Managed_DataObject
return is_null($other) ? false : $other->isSubscribed($this);
}
function requiresSubscriptionApproval(Profile $other=null): bool
public function requiresSubscriptionApproval(Profile $other = null): bool
{
if (!$this->isLocal()) {
// We don't know for remote users, and we'll always be able to send
@ -818,7 +841,7 @@ class Profile extends Managed_DataObject
* @param Profile $other
* @return boolean
*/
function hasPendingSubscription(Profile $other)
public function hasPendingSubscription(Profile $other)
{
return Subscription_queue::exists($this, $other);
}
@ -829,13 +852,13 @@ class Profile extends Managed_DataObject
* @param Profile $other
* @return boolean
*/
function mutuallySubscribed(Profile $other)
public function mutuallySubscribed(Profile $other)
{
return $this->isSubscribed($other) &&
$other->isSubscribed($this);
}
function noticeCount()
public function noticeCount()
{
$c = Cache::instance();
@ -858,7 +881,7 @@ class Profile extends Managed_DataObject
return $cnt;
}
function blowSubscriberCount()
public function blowSubscriberCount()
{
$c = Cache::instance();
if (!empty($c)) {
@ -866,7 +889,7 @@ class Profile extends Managed_DataObject
}
}
function blowSubscriptionCount()
public function blowSubscriptionCount()
{
$c = Cache::instance();
if (!empty($c)) {
@ -874,7 +897,7 @@ class Profile extends Managed_DataObject
}
}
function blowNoticeCount()
public function blowNoticeCount()
{
$c = Cache::instance();
if (!empty($c)) {
@ -882,7 +905,7 @@ class Profile extends Managed_DataObject
}
}
static function maxBio()
public static function maxBio()
{
$biolimit = common_config('profile', 'biolimit');
// null => use global limit (distinct from 0!)
@ -892,13 +915,13 @@ class Profile extends Managed_DataObject
return $biolimit;
}
static function bioTooLong($bio)
public static function bioTooLong($bio)
{
$biolimit = self::maxBio();
return ($biolimit > 0 && !empty($bio) && (mb_strlen($bio) > $biolimit));
}
function update($dataObject=false)
public function update($dataObject = false)
{
if (is_object($dataObject) && $this->nickname != $dataObject->nickname) {
try {
@ -946,7 +969,7 @@ class Profile extends Managed_DataObject
return $relMes;
}
function delete($useWhere=false)
public function delete($useWhere = false)
{
$this->_deleteNotices();
$this->_deleteSubscriptions();
@ -957,10 +980,11 @@ class Profile extends Managed_DataObject
// Warning: delete() will run on the batch objects,
// not on individual objects.
$related = array('Reply',
'Group_member',
'Profile_role'
);
$related = [
'Reply',
'Group_member',
'Profile_role',
];
Event::handle('ProfileDeleteRelated', array($this, &$related));
foreach ($related as $cls) {
@ -968,7 +992,7 @@ class Profile extends Managed_DataObject
$inst->profile_id = $this->id;
$inst->delete();
}
$this->grantRole(Profile_role::DELETED);
$localuser = User::getKV('id', $this->id);
@ -979,7 +1003,7 @@ class Profile extends Managed_DataObject
return parent::delete($useWhere);
}
function _deleteNotices()
public function _deleteNotices()
{
$notice = new Notice();
$notice->profile_id = $this->id;
@ -992,7 +1016,7 @@ class Profile extends Managed_DataObject
}
}
function _deleteSubscriptions()
public function _deleteSubscriptions()
{
$sub = new Subscription();
$sub->subscriber = $this->getID();
@ -1040,14 +1064,14 @@ class Profile extends Managed_DataObject
$self->delete();
}
function _deleteTags()
public function _deleteTags()
{
$tag = new Profile_tag();
$tag->tagged = $this->id;
$tag->delete();
}
function _deleteBlocks()
public function _deleteBlocks()
{
$block = new Profile_block();
$block->blocked = $this->id;
@ -1058,7 +1082,7 @@ class Profile extends Managed_DataObject
$block->delete();
}
function _deleteAttentions()
public function _deleteAttentions()
{
$att = new Attention();
$att->profile_id = $this->getID();
@ -1103,7 +1127,7 @@ class Profile extends Managed_DataObject
if ($cfg == 'always') {
return true;
} else if ($cfg == 'never') {
} elseif ($cfg == 'never') {
return false;
} else { // user
$share = common_config('location', 'sharedefault');
@ -1120,7 +1144,7 @@ class Profile extends Managed_DataObject
}
}
function hasRole($name)
public function hasRole($name)
{
$has_role = false;
if (Event::handle('StartHasRole', array($this, $name, &$has_role))) {
@ -1132,10 +1156,9 @@ class Profile extends Managed_DataObject
return $has_role;
}
function grantRole($name)
public function grantRole($name)
{
if (Event::handle('StartGrantRole', array($this, $name))) {
$role = new Profile_role();
$role->profile_id = $this->id;
@ -1158,17 +1181,20 @@ class Profile extends Managed_DataObject
return $result;
}
function revokeRole($name)
public function revokeRole($name)
{
if (Event::handle('StartRevokeRole', array($this, $name))) {
$role = Profile_role::pkeyGet(array('profile_id' => $this->id,
'role' => $name));
if (empty($role)) {
// TRANS: Exception thrown when trying to revoke an existing role for a user that does not exist.
// TRANS: %1$s is the role name, %2$s is the user ID (number).
throw new Exception(sprintf(_('Cannot revoke role "%1$s" for user #%2$d; does not exist.'),$name, $this->id));
throw new Exception(sprintf(
_('Cannot revoke role "%1$s" for user #%2$d; does not exist.'),
$name,
$this->id
));
}
$result = $role->delete();
@ -1177,7 +1203,11 @@ class Profile extends Managed_DataObject
common_log_db_error($role, 'DELETE', __FILE__);
// TRANS: Exception thrown when trying to revoke a role for a user with a failing database query.
// TRANS: %1$s is the role name, %2$s is the user ID (number).
throw new Exception(sprintf(_('Cannot revoke role "%1$s" for user #%2$d; database error.'),$name, $this->id));
throw new Exception(sprintf(
_('Cannot revoke role "%1$s" for user #%2$d; database error.'),
$name,
$this->id
));
}
if ($name == 'owner') {
@ -1190,27 +1220,27 @@ class Profile extends Managed_DataObject
}
}
function isSandboxed()
public function isSandboxed()
{
return $this->hasRole(Profile_role::SANDBOXED);
}
function isSilenced()
public function isSilenced()
{
return $this->hasRole(Profile_role::SILENCED);
}
function sandbox()
public function sandbox()
{
$this->grantRole(Profile_role::SANDBOXED);
}
function unsandbox()
public function unsandbox()
{
$this->revokeRole(Profile_role::SANDBOXED);
}
function silence()
public function silence()
{
$this->grantRole(Profile_role::SILENCED);
if (common_config('notice', 'hidespam')) {
@ -1218,7 +1248,7 @@ class Profile extends Managed_DataObject
}
}
function silenceAs(Profile $actor)
public function silenceAs(Profile $actor)
{
if (!$actor->hasRight(Right::SILENCEUSER)) {
throw new AuthorizationException(_('You cannot silence users on this site.'));
@ -1234,7 +1264,7 @@ class Profile extends Managed_DataObject
return $this->silence();
}
function unsilence()
public function unsilence()
{
$this->revokeRole(Profile_role::SILENCED);
if (common_config('notice', 'hidespam')) {
@ -1242,7 +1272,7 @@ class Profile extends Managed_DataObject
}
}
function unsilenceAs(Profile $actor)
public function unsilenceAs(Profile $actor)
{
if (!$actor->hasRight(Right::SILENCEUSER)) {
// TRANS: Client error displayed trying to unsilence a user when the user does not have the right.
@ -1255,7 +1285,7 @@ class Profile extends Managed_DataObject
return $this->unsilence();
}
function flushVisibility()
public function flushVisibility()
{
// Get all notices
$stream = new ProfileNoticeStream($this, $this);
@ -1301,8 +1331,7 @@ class Profile extends Managed_DataObject
}
if (Event::handle('UserRightsCheck', array($this, $right, &$result))) {
switch ($right)
{
switch ($right) {
case Right::DELETEOTHERSNOTICE:
case Right::MAKEGROUPADMIN:
case Right::SANDBOXUSER:
@ -1380,7 +1409,7 @@ class Profile extends Managed_DataObject
*
* @return string
*/
function asAtomAuthor($cur = null)
public function asAtomAuthor($cur = null)
{
$xs = new XMLStringer(true);
@ -1388,7 +1417,7 @@ class Profile extends Managed_DataObject
$xs->element('name', null, $this->nickname);
$xs->element('uri', null, $this->getUri());
if ($cur != null) {
$attrs = Array();
$attrs = [];
$attrs['following'] = $cur->isSubscribed($this) ? 'true' : 'false';
$attrs['blocking'] = $cur->hasBlocked($this) ? 'true' : 'false';
$xs->element('statusnet:profile_info', $attrs, null);
@ -1409,7 +1438,7 @@ class Profile extends Managed_DataObject
* @return array representation of <statusnet:profile_info> element or null
*/
function profileInfo(Profile $scoped=null)
public function profileInfo(Profile $scoped = null)
{
$profileInfoAttr = array('local_id' => $this->id);
@ -1431,7 +1460,7 @@ class Profile extends Managed_DataObject
*
* @return string
*/
function asActivityActor()
public function asActivityActor()
{
return $this->asActivityNoun('actor');
}
@ -1447,7 +1476,7 @@ class Profile extends Managed_DataObject
*
* @return string
*/
function asActivityNoun($element)
public function asActivityNoun($element)
{
$noun = $this->asActivityObject();
return $noun->asString('activity:' . $element);
@ -1619,7 +1648,7 @@ class Profile extends Managed_DataObject
return $scheme ? $acct : mb_substr($acct, 5);
}
function hasBlocked(Profile $other)
public function hasBlocked(Profile $other)
{
$block = Profile_block::exists($this, $other);
return !empty($block);
@ -1652,7 +1681,7 @@ class Profile extends Managed_DataObject
*
* @param string $uri A unique identifier for a resource (profile/group/whatever)
*/
static function fromUri($uri)
public static function fromUri($uri)
{
$profile = null;
@ -1677,7 +1706,7 @@ class Profile extends Managed_DataObject
return $profile;
}
function canRead(Notice $notice)
public function canRead(Notice $notice)
{
if ($notice->scope & Notice::SITE_SCOPE) {
$user = $this->getUser();
@ -1717,7 +1746,7 @@ class Profile extends Managed_DataObject
return true;
}
static function current()
public static function current()
{
$user = common_current_user();
if (empty($user)) {
@ -1728,7 +1757,7 @@ class Profile extends Managed_DataObject
return $profile;
}
static function ensureCurrent()
public static function ensureCurrent()
{
$profile = self::current();
if (!$profile instanceof Profile) {
@ -1747,7 +1776,7 @@ class Profile extends Managed_DataObject
* @return array of variable names to include in serialization.
*/
function __sleep()
public function __sleep()
{
$vars = parent::__sleep();
$skip = array('_user', '_group');
@ -1802,11 +1831,13 @@ class Profile extends Managed_DataObject
return !is_null($private_stream) && $private_stream;
}
public function delPref($namespace, $topic) {
public function delPref($namespace, $topic)
{
return Profile_prefs::setData($this, $namespace, $topic, null);
}
public function getPref($namespace, $topic, $default=null) {
public function getPref($namespace, $topic, $default = null)
{
// If you want an exception to be thrown, call Profile_prefs::getData directly
try {
return Profile_prefs::getData($this, $namespace, $topic, $default);
@ -1821,7 +1852,8 @@ class Profile extends Managed_DataObject
return Profile_prefs::getConfigData($this, $namespace, $topic);
}
public function setPref($namespace, $topic, $data) {
public function setPref($namespace, $topic, $data)
{
return Profile_prefs::setData($this, $namespace, $topic, $data);
}

View File

@ -1,27 +1,28 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* StatusNet - the distributed open-source microblogging tool
*
* 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 Notices
* @package StatusNet
* @author Shashi Gowda <connect2shashi@gmail.com>
* @license GNU Affero General Public License http://www.gnu.org/licenses/
* @category Notices
* @package GNUsocial
* @author Shashi Gowda <connect2shashi@gmail.com>
* @copyright 2019 Free Software Foundation, Inc http://www.fsf.org
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('GNUSOCIAL')) { exit(1); }
defined('GNUSOCIAL') || die();
class Profile_list extends Managed_DataObject
{
@ -30,7 +31,7 @@ class Profile_list extends Managed_DataObject
public $tagger; // int(4)
public $tag; // varchar(64)
public $description; // text
public $private; // tinyint(1)
public $private; // bool default_false
public $created; // datetime() not_null default_0000-00-00%2000%3A00%3A00
public $modified; // datetime() not_null default_CURRENT_TIMESTAMP
public $uri; // varchar(191) unique_key not 255 because utf8mb4 takes more space
@ -46,7 +47,7 @@ class Profile_list extends Managed_DataObject
'tagger' => array('type' => 'int', 'not null' => true, 'description' => 'user making the tag'),
'tag' => array('type' => 'varchar', 'length' => 64, 'not null' => true, 'description' => 'people tag'),
'description' => array('type' => 'text', 'description' => 'description of the people tag'),
'private' => array('type' => 'int', 'size' => 'tiny', 'default' => 0, 'description' => 'is this tag private'),
'private' => array('type' => 'bool', 'default' => false, 'description' => 'is this tag private'),
'created' => array('type' => 'datetime', 'not null' => true, 'default' => '0000-00-00 00:00:00', 'description' => 'date the tag was added'),
'modified' => array('type' => 'datetime', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date the tag was modified'),
@ -58,7 +59,8 @@ class Profile_list extends Managed_DataObject
),
'primary key' => array('tagger', 'tag'),
'unique keys' => array(
'profile_list_id_key' => array('id')
'profile_list_id_key' => array('id'),
'profile_list_tag_key' => array('tag'),
),
'foreign keys' => array(
'profile_list_tagger_fkey' => array('profile', array('tagger' => 'id')),
@ -79,7 +81,7 @@ class Profile_list extends Managed_DataObject
* @return Profile the tagger
*/
function getTagger()
public function getTagger()
{
return Profile::getByID($this->tagger);
}
@ -91,7 +93,7 @@ class Profile_list extends Managed_DataObject
* @return String
*/
function getBestName()
public function getBestName()
{
return $this->tag;
}
@ -102,15 +104,17 @@ class Profile_list extends Managed_DataObject
* @return String uri
*/
function getUri()
public function getUri()
{
$uri = null;
if (Event::handle('StartProfiletagGetUri', array($this, &$uri))) {
if (!empty($this->uri)) {
$uri = $this->uri;
} else {
$uri = common_local_url('profiletagbyid',
array('id' => $this->id, 'tagger_id' => $this->tagger));
$uri = common_local_url(
'profiletagbyid',
['id' => $this->id, 'tagger_id' => $this->tagger]
);
}
}
Event::handle('EndProfiletagGetUri', array($this, &$uri));
@ -123,7 +127,7 @@ class Profile_list extends Managed_DataObject
* @return String home url
*/
function homeUrl()
public function homeUrl()
{
$url = null;
if (Event::handle('StartUserPeopletagHomeUrl', array($this, &$url))) {
@ -131,9 +135,13 @@ class Profile_list extends Managed_DataObject
if (!empty($this->mainpage)) {
$url = $this->mainpage;
} else {
$url = common_local_url('showprofiletag',
array('nickname' => $this->getTagger()->nickname,
'tag' => $this->tag));
$url = common_local_url(
'showprofiletag',
[
'nickname' => $this->getTagger()->nickname,
'tag' => $this->tag,
]
);
}
}
Event::handle('EndUserPeopletagHomeUrl', array($this, &$url));
@ -146,12 +154,14 @@ class Profile_list extends Managed_DataObject
* @return String permalink
*/
function permalink()
public function permalink()
{
$url = null;
if (Event::handle('StartProfiletagPermalink', array($this, &$url))) {
$url = common_local_url('profiletagbyid',
array('id' => $this->id));
$url = common_local_url(
'profiletagbyid',
['id' => $this->id]
);
}
Event::handle('EndProfiletagPermalink', array($this, &$url));
return $url;
@ -169,7 +179,7 @@ class Profile_list extends Managed_DataObject
* @return Notice the query
*/
function getNotices($offset, $limit, $since_id=null, $max_id=null)
public function getNotices($offset, $limit, $since_id = null, $max_id = null)
{
// FIXME: Use something else than Profile::current() to avoid
// possible confusion between session user and queue processing.
@ -190,7 +200,7 @@ class Profile_list extends Managed_DataObject
* @return Profile results
*/
function getSubscribers($offset=0, $limit=null, $since=0, $upto=0)
public function getSubscribers(int $offset = 0, ?int $limit = null, int $since = 0, int $upto = 0)
{
$subs = new Profile();
@ -199,8 +209,15 @@ class Profile_list extends Managed_DataObject
);
$subs->whereAdd('profile_tag_subscription.profile_tag_id = ' . $this->id);
$subs->selectAdd('unix_timestamp(profile_tag_subscription.' .
'created) as "cursor"');
if (common_config('db', 'type') !== 'mysql') {
$subs->selectAdd(sprintf(
'((EXTRACT(DAY %1$s) * 24 + EXTRACT(HOUR %1$s)) * 60 + ' .
'EXTRACT(MINUTE %1$s)) * 60 + FLOOR(EXTRACT(SECOND %1$s)) AS "cursor"',
"FROM (profile_tag_subscription.created - TIMESTAMP '1970-01-01 00:00:00')"
));
} else {
$subs->selectAdd("timestampdiff(SECOND, '1970-01-01', profile_tag_subscription.created) AS `cursor`");
}
if ($since != 0) {
$subs->whereAdd('cursor > ' . $since);
@ -227,24 +244,22 @@ class Profile_list extends Managed_DataObject
* @return array ids of users
*/
function getUserSubscribers()
public function getUserSubscribers()
{
// XXX: cache this
$user = new User();
if(common_config('db','quote_identifiers'))
$user_table = '"user"';
else $user_table = 'user';
$qry =
'SELECT id ' .
'FROM '. $user_table .' JOIN profile_tag_subscription '.
'ON '. $user_table .'.id = profile_tag_subscription.profile_id ' .
'WHERE profile_tag_subscription.profile_tag_id = %d ';
$user->query(sprintf(
'SELECT id ' .
'FROM %1$s INNER JOIN profile_tag_subscription ' .
'ON %1$s.id = profile_tag_subscription.profile_id ' .
'WHERE profile_tag_subscription.profile_tag_id = %2$d ',
$user->escapedTableName(),
$this->id
));
$user->query(sprintf($qry, $this->id));
$ids = array();
$ids = [];
while ($user->fetch()) {
$ids[] = $user->id;
@ -264,7 +279,7 @@ class Profile_list extends Managed_DataObject
* @return boolean subscription status
*/
function hasSubscriber($id)
public function hasSubscriber($id)
{
if (!is_numeric($id)) {
$id = $id->id;
@ -288,13 +303,21 @@ class Profile_list extends Managed_DataObject
* @return Profile results
*/
function getTagged($offset=0, $limit=null, $since=0, $upto=0)
public function getTagged(int $offset = 0, ?int $limit = null, int $since = 0, int $upto = 0)
{
$tagged = new Profile();
$tagged->joinAdd(array('id', 'profile_tag:tagged'));
$tagged->joinAdd(['id', 'profile_tag:tagged']);
if (common_config('db', 'type') !== 'mysql') {
$tagged->selectAdd(sprintf(
'((EXTRACT(DAY %1$s) * 24 + EXTRACT(HOUR %1$s)) * 60 + ' .
'EXTRACT(MINUTE %1$s)) * 60 + FLOOR(EXTRACT(SECOND %1$s)) AS "cursor"',
"FROM (profile_tag.modified - TIMESTAMP '1970-01-01 00:00:00')"
));
} else {
$tagged->selectAdd("timestampdiff(SECOND, '1970-01-01', profile_tag.modified) AS `cursor`");
}
#@fixme: postgres
$tagged->selectAdd('unix_timestamp(profile_tag.modified) as "cursor"');
$tagged->whereAdd('profile_tag.tagger = '.$this->tagger);
$tagged->whereAdd("profile_tag.tag = '{$this->tag}'");
@ -323,7 +346,7 @@ class Profile_list extends Managed_DataObject
* @return boolean success
*/
function delete($useWhere=false)
public function delete($useWhere = false)
{
// force delete one item at a time.
if (empty($this->id)) {
@ -350,7 +373,7 @@ class Profile_list extends Managed_DataObject
* @return boolean success
*/
function update($dataObject=false)
public function update($dataObject = false)
{
if (!is_object($dataObject) && !$dataObject instanceof Profile_list) {
return parent::update($dataObject);
@ -361,9 +384,9 @@ class Profile_list extends Managed_DataObject
// if original tag was different
// check to see if the new tag already exists
// if not, rename the tag correctly
if($dataObject->tag != $this->tag || $dataObject->tagger != $this->tagger) {
if ($dataObject->tag != $this->tag || $dataObject->tagger != $this->tagger) {
$existing = Profile_list::getByTaggerAndTag($this->tagger, $this->tag);
if(!empty($existing)) {
if (!empty($existing)) {
// TRANS: Server exception.
throw new ServerException(_('The tag you are trying to rename ' .
'to already exists.'));
@ -382,7 +405,7 @@ class Profile_list extends Managed_DataObject
* @return string atom author element
*/
function asAtomAuthor()
public function asAtomAuthor()
{
$xs = new XMLStringer(true);
@ -404,7 +427,7 @@ class Profile_list extends Managed_DataObject
* @return string activitystreams noun
*/
function asActivityNoun($element)
public function asActivityNoun($element)
{
$noun = ActivityObject::fromPeopletag($this);
return $noun->asString('activity:' . $element);
@ -419,11 +442,13 @@ class Profile_list extends Managed_DataObject
* @return integer count
*/
function taggedCount($recount=false)
public function taggedCount($recount = false)
{
$keypart = sprintf('profile_list:tagged_count:%d:%s',
$this->tagger,
$this->tag);
$keypart = sprintf(
'profile_list:tagged_count:%d:%s',
$this->tagger,
$this->tag
);
$count = self::cacheGet($keypart);
@ -450,15 +475,16 @@ class Profile_list extends Managed_DataObject
* @return integer count
*/
function subscriberCount($recount=false)
public function subscriberCount($recount = false)
{
$keypart = sprintf('profile_list:subscriber_count:%d',
$this->id);
$keypart = sprintf(
'profile_list:subscriber_count:%d',
$this->id
);
$count = self::cacheGet($keypart);
if ($count === false) {
$sub = new Profile_tag_subscription();
$sub->profile_tag_id = $this->id;
$count = (int) $sub->count('distinct profile_id');
@ -478,7 +504,7 @@ class Profile_list extends Managed_DataObject
* @return integer count
*/
function blowNoticeStreamCache($all=false)
public function blowNoticeStreamCache($all = false)
{
self::blow('profile_list:notice_ids:%d', $this->id);
if ($all) {
@ -496,7 +522,7 @@ class Profile_list extends Managed_DataObject
* @return integer count
*/
static function getByTaggerAndTag($tagger, $tag)
public static function getByTaggerAndTag($tagger, $tag)
{
$ptag = Profile_list::pkeyGet(array('tagger' => $tagger, 'tag' => $tag));
return $ptag;
@ -514,11 +540,11 @@ class Profile_list extends Managed_DataObject
* @return Profile_list the people tag object
*/
static function ensureTag($tagger, $tag, $description=null, $private=false)
public static function ensureTag($tagger, $tag, $description = null, $private = false)
{
$ptag = Profile_list::getByTaggerAndTag($tagger, $tag);
if(empty($ptag->id)) {
if (empty($ptag->id)) {
$args = array(
'tag' => $tag,
'tagger' => $tagger,
@ -544,7 +570,7 @@ class Profile_list extends Managed_DataObject
* @return integer maximum number of characters
*/
static function maxDescription()
public static function maxDescription()
{
$desclimit = common_config('peopletag', 'desclimit');
// null => use global limit (distinct from 0!)
@ -563,7 +589,7 @@ class Profile_list extends Managed_DataObject
* @return boolean is the descripition too long?
*/
static function descriptionTooLong($desc)
public static function descriptionTooLong($desc)
{
$desclimit = self::maxDescription();
return ($desclimit > 0 && !empty($desc) && (mb_strlen($desc) > $desclimit));
@ -578,7 +604,8 @@ class Profile_list extends Managed_DataObject
*
* @return mixed Profile_list on success, false on fail
*/
static function saveNew(array $fields) {
public static function saveNew(array $fields)
{
extract($fields);
$ptag = new Profile_list();
@ -639,7 +666,7 @@ class Profile_list extends Managed_DataObject
$result = $ptag->update($orig);
if (!$result) {
common_log_db_error($ptag, 'UPDATE', __FILE__);
// TRANS: Server exception saving new tag.
// TRANS: Server exception saving new tag.
throw new ServerException(_('Could not set profile tag URI.'));
}
}
@ -647,7 +674,7 @@ class Profile_list extends Managed_DataObject
if (!isset($mainpage) || empty($mainpage)) {
$orig = clone($ptag);
$user = User::getKV('id', $ptag->tagger);
if(!empty($user)) {
if (!empty($user)) {
$ptag->mainpage = common_local_url('showprofiletag', array('tag' => $ptag->tag, 'nickname' => $user->getNickname()));
} else {
$ptag->mainpage = $uri; // assume this is a remote peopletag and the uri works
@ -687,9 +714,9 @@ class Profile_list extends Managed_DataObject
* @returns array (array (mixed items), int next_cursor, int previous_cursor)
*/
// XXX: This should be in Memcached_DataObject... eventually.
// XXX: This should be in Memcached_DataObject... eventually
static function getAtCursor($fn, array $args, $cursor, $count=20)
public static function getAtCursor($fn, array $args, $cursor, $count = 20)
{
$items = array();
@ -698,12 +725,12 @@ class Profile_list extends Managed_DataObject
$next_cursor = 0;
$prev_cursor = 0;
if($cursor > 0) {
if ($cursor > 0) {
// if cursor is +ve fetch $count+2 items before cursor starting at cursor
$max_id = $cursor;
$fn_args = array_merge($args, array(0, $count+2, 0, $max_id));
$list = call_user_func_array($fn, $fn_args);
while($list->fetch()) {
while ($list->fetch()) {
$items[] = clone($list);
}
@ -734,15 +761,14 @@ class Profile_list extends Managed_DataObject
$next_cursor = isset($next->cursor) ?
$items[$count-1]->cursor : $items[$count-1]->id;
}
} else if($cursor < -1) {
} elseif ($cursor < -1) {
// if cursor is -ve fetch $count+2 items created after -$cursor-1
$cursor = abs($cursor);
$since_id = $cursor-1;
$fn_args = array_merge($args, array(0, $count+2, $since_id));
$list = call_user_func_array($fn, $fn_args);
while($list->fetch()) {
while ($list->fetch()) {
$items[] = clone($list);
}
@ -755,7 +781,10 @@ class Profile_list extends Managed_DataObject
} else {
$next_cursor = isset($items[$end]->cursor) ?
$items[$end]->cursor : $items[$end]->id;
if ($end > $count) array_pop($items); // excess item.
if ($end > $count) {
// excess item
array_pop($items);
}
// check if there are more items for next page
$fn_args = array_merge($args, array(0, 1, 0, $cursor));
@ -771,23 +800,22 @@ class Profile_list extends Managed_DataObject
$prev_cursor = isset($prev->cursor) ?
-$items[0]->cursor : -$items[0]->id;
}
} else if($cursor == -1) {
} elseif ($cursor == -1) {
$fn_args = array_merge($args, array(0, $count+1));
$list = call_user_func_array($fn, $fn_args);
while($list->fetch()) {
while ($list->fetch()) {
$items[] = clone($list);
}
if (count($items)==$count+1) {
$next = array_pop($items);
if(isset($next->cursor)) {
if (isset($next->cursor)) {
$next_cursor = $items[$count-1]->cursor;
} else {
$next_cursor = $items[$count-1]->id;
}
}
}
return array($items, $next_cursor, $prev_cursor);
}
@ -803,7 +831,8 @@ class Profile_list extends Managed_DataObject
* @return boolean success
*/
static function setCache($ckey, &$tag, $offset=0, $limit=null) {
public static function setCache($ckey, &$tag, $offset = 0, $limit = null)
{
$cache = Cache::instance();
if (empty($cache)) {
return false;
@ -834,8 +863,8 @@ class Profile_list extends Managed_DataObject
* @return Profile_list results
*/
static function getCached($ckey, $offset=0, $limit=null) {
public static function getCached($ckey, $offset = 0, $limit = null)
{
$keys_str = self::cacheGet($ckey);
if ($keys_str === false) {
return false;
@ -862,7 +891,8 @@ class Profile_list extends Managed_DataObject
* @return Profile_list results
*/
static function getByKeys(array $keys) {
public static function getByKeys(array $keys)
{
$cache = Cache::instance();
if (!empty($cache)) {
@ -910,7 +940,7 @@ class Profile_list extends Managed_DataObject
}
}
function insert()
public function insert()
{
$result = parent::insert();
if ($result) {

View File

@ -1,32 +1,31 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* StatusNet, the distributed open-source microblogging tool
*
* Data class for Profile preferences
*
* 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 GNUsocial
* @author Mikael Nordfeldth <mmn@hethane.se>
* @copyright 2013 Free Software Foundation, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://www.gnu.org/software/social/
* @copyright 2013 Free Software Foundation, Inc http://www.fsf.org
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
defined('GNUSOCIAL') || die();
class Profile_prefs extends Managed_DataObject
{
public $__table = 'profile_prefs'; // table name
@ -58,7 +57,7 @@ class Profile_prefs extends Managed_DataObject
);
}
static function getNamespacePrefs(Profile $profile, $namespace, array $topic=array())
public static function getNamespacePrefs(Profile $profile, $namespace, array $topic = [])
{
if (empty($topic)) {
$prefs = new Profile_prefs();
@ -76,13 +75,13 @@ class Profile_prefs extends Managed_DataObject
return $prefs;
}
static function getNamespace(Profile $profile, $namespace, array $topic=array())
public static function getNamespace(Profile $profile, $namespace, array $topic = [])
{
$prefs = self::getNamespacePrefs($profile, $namespace, $topic);
return $prefs->fetchAll();
}
static function getAll(Profile $profile)
public static function getAll(Profile $profile)
{
try {
$prefs = self::listFind('profile_id', array($profile->getID()));
@ -100,13 +99,15 @@ class Profile_prefs extends Managed_DataObject
return $list;
}
static function getTopic(Profile $profile, $namespace, $topic) {
public static function getTopic(Profile $profile, $namespace, $topic)
{
return Profile_prefs::getByPK(array('profile_id' => $profile->getID(),
'namespace' => $namespace,
'topic' => $topic));
}
static function getData(Profile $profile, $namespace, $topic, $def=null) {
public static function getData(Profile $profile, $namespace, $topic, $def = null)
{
try {
$pref = self::getTopic($profile, $namespace, $topic);
} catch (NoResultException $e) {
@ -120,7 +121,8 @@ class Profile_prefs extends Managed_DataObject
return $pref->data;
}
static function getConfigData(Profile $profile, $namespace, $topic) {
public static function getConfigData(Profile $profile, $namespace, $topic)
{
try {
$data = self::getData($profile, $namespace, $topic);
} catch (NoResultException $e) {
@ -140,14 +142,15 @@ class Profile_prefs extends Managed_DataObject
* @return true if changes are made, false if no action taken
* @throws ServerException if preference could not be saved
*/
static function setData(Profile $profile, $namespace, $topic, $data=null) {
public static function setData(Profile $profile, $namespace, $topic, $data = null)
{
try {
$pref = self::getTopic($profile, $namespace, $topic);
if (is_null($data)) {
$pref->delete();
} else {
$orig = clone($pref);
$pref->data = $data;
$pref->data = DB_DataObject_Cast::blob($data);
$pref->update($orig);
}
return true;
@ -161,7 +164,7 @@ class Profile_prefs extends Managed_DataObject
$pref->profile_id = $profile->getID();
$pref->namespace = $namespace;
$pref->topic = $topic;
$pref->data = $data;
$pref->data = DB_DataObject_Cast::blob($data);
$pref->created = common_sql_now();
if ($pref->insert() === false) {

View File

@ -1,8 +1,24 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
defined('GNUSOCIAL') || die();
/**
* Table Definition for profile_tag
*/
class Profile_tag extends Managed_DataObject
{
public $__table = 'profile_tag'; // table name
@ -35,35 +51,34 @@ class Profile_tag extends Managed_DataObject
);
}
function links()
public function links()
{
return array('tagger,tag' => 'profile_list:tagger,tag');
}
function getMeta()
public function getMeta()
{
return Profile_list::pkeyGet(array('tagger' => $this->tagger, 'tag' => $this->tag));
}
static function getSelfTagsArray(Profile $target)
public static function getSelfTagsArray(Profile $target)
{
return self::getTagsArray($target->getID(), $target->getID(), $target);
}
static function setSelfTags(Profile $target, array $newtags, array $privacy=array())
public static function setSelfTags(Profile $target, array $newtags, array $privacy = [])
{
return self::setTags($target->getID(), $target->getID(), $newtags, $privacy);
}
static function getTags($tagger, $tagged, $auth_user=null) {
public static function getTags($tagger, $tagged, $auth_user = null)
{
$profile_list = new Profile_list();
$include_priv = 1;
if (!($auth_user instanceof User ||
$auth_user instanceof Profile) ||
($auth_user->id !== $tagger)) {
$profile_list->private = false;
$include_priv = 0;
}
@ -81,7 +96,7 @@ class Profile_tag extends Managed_DataObject
$qry = sprintf($qry, $tagger, $tagged);
if (!$include_priv) {
$qry .= ' and profile_list.private = 0';
$qry .= ' AND profile_list.private = FALSE';
}
$profile_list->query($qry);
@ -91,20 +106,23 @@ class Profile_tag extends Managed_DataObject
return $profile_list;
}
static function getTagsArray($tagger, $tagged, Profile $scoped=null)
public static function getTagsArray($tagger, $tagged, Profile $scoped = null)
{
$ptag = new Profile_tag();
$qry = sprintf('select profile_tag.tag '.
'from profile_tag join profile_list '.
' on (profile_tag.tagger = profile_list.tagger ' .
' and profile_tag.tag = profile_list.tag) ' .
'where profile_tag.tagger = %d ' .
'and profile_tag.tagged = %d ',
$tagger, $tagged);
$qry = sprintf(
'SELECT profile_tag.tag '.
'FROM profile_tag INNER JOIN profile_list '.
' ON (profile_tag.tagger = profile_list.tagger ' .
' and profile_tag.tag = profile_list.tag) ' .
'WHERE profile_tag.tagger = %d ' .
'AND profile_tag.tagged = %d ',
$tagger,
$tagged
);
if (!$scoped instanceof Profile || $scoped->getID() !== $tagger) {
$qry .= 'and profile_list.private = 0';
$qry .= 'AND profile_list.private = FALSE';
}
$tags = array();
@ -118,8 +136,8 @@ class Profile_tag extends Managed_DataObject
return $tags;
}
static function setTags($tagger, $tagged, array $newtags, array $privacy=array()) {
public static function setTags($tagger, $tagged, array $newtags, array $privacy = [])
{
$newtags = array_unique($newtags);
$oldtags = self::getTagsArray($tagger, $tagged, Profile::getByID($tagger));
@ -145,8 +163,8 @@ class Profile_tag extends Managed_DataObject
}
# set a single tag
static function setTag($tagger, $tagged, $tag, $desc=null, $private=false) {
public static function setTag($tagger, $tagged, $tag, $desc=null, $private = false)
{
$ptag = Profile_tag::pkeyGet(array('tagger' => $tagger,
'tagged' => $tagged,
'tag' => $tag));
@ -160,7 +178,6 @@ class Profile_tag extends Managed_DataObject
$tagged_profile = Profile::getByID($tagged);
if (Event::handle('StartTagProfile', array($tagger_profile, $tagged_profile, $tag))) {
if (!$tagger_profile->canTag($tagged_profile)) {
// TRANS: Client exception thrown trying to set a tag for a user that cannot be tagged.
throw new ClientException(_('You cannot tag this user.'));
@ -172,10 +189,12 @@ class Profile_tag extends Managed_DataObject
if ($count >= common_config('peopletag', 'maxtags')) {
// TRANS: Client exception thrown trying to set more tags than allowed.
throw new ClientException(sprintf(_('You already have created %d or more tags ' .
'which is the maximum allowed number of tags. ' .
'Try using or deleting some existing tags.'),
common_config('peopletag', 'maxtags')));
throw new ClientException(sprintf(
_('You already have created %d or more tags ' .
'which is the maximum allowed number of tags. ' .
'Try using or deleting some existing tags.'),
common_config('peopletag', 'maxtags')
));
}
$plist = new Profile_list();
@ -185,10 +204,13 @@ class Profile_tag extends Managed_DataObject
if ($profile_list->taggedCount() >= common_config('peopletag', 'maxpeople')) {
// TRANS: Client exception thrown when trying to add more people than allowed to a list.
throw new ClientException(sprintf(_('You already have %1$d or more people in list %2$s, ' .
'which is the maximum allowed number. ' .
'Try unlisting others first.'),
common_config('peopletag', 'maxpeople'), $tag));
throw new ClientException(sprintf(
_('You already have %1$d or more people in list %2$s, ' .
'which is the maximum allowed number. ' .
'Try unlisting others first.'),
common_config('peopletag', 'maxpeople'),
$tag
));
}
$newtag = new Profile_tag();
@ -221,7 +243,8 @@ class Profile_tag extends Managed_DataObject
return $newtag;
}
static function unTag($tagger, $tagged, $tag) {
public static function unTag($tagger, $tagged, $tag)
{
$ptag = Profile_tag::pkeyGet(array('tagger' => $tagger,
'tagged' => $tagged,
'tag' => $tag));
@ -247,13 +270,14 @@ class Profile_tag extends Managed_DataObject
}
// @fixme: move this to Profile_list?
static function cleanup($profile_list) {
public static function cleanup($profile_list)
{
$ptag = new Profile_tag();
$ptag->tagger = $profile_list->tagger;
$ptag->tag = $profile_list->tag;
$ptag->find();
while($ptag->fetch()) {
while ($ptag->fetch()) {
if (Event::handle('StartUntagProfile', array($ptag))) {
$orig = clone($ptag);
$result = $ptag->delete();
@ -266,17 +290,18 @@ class Profile_tag extends Managed_DataObject
}
// move a tag!
static function moveTag($orig, $new) {
public static function moveTag($orig, $new)
{
$tags = new Profile_tag();
$qry = 'UPDATE profile_tag SET ' .
'tag = "%s", tagger = "%s" ' .
'WHERE tag = "%s" ' .
'AND tagger = "%s"';
$result = $tags->query(sprintf($qry,
$tags->escape($new->tag),
$tags->escape($new->tagger),
$tags->escape($orig->tag),
$tags->escape($orig->tagger)));
$qry = "UPDATE profile_tag SET tag = '%s', tagger = '%s' " .
"WHERE tag = '%s' AND tagger = '%s'";
$result = $tags->query(sprintf(
$qry,
$tags->escape($new->tag),
$tags->escape($new->tagger),
$tags->escape($orig->tag),
$tags->escape($orig->tagger)
));
if ($result === false) {
common_log_db_error($tags, 'UPDATE', __FILE__);
@ -285,7 +310,8 @@ class Profile_tag extends Managed_DataObject
return $result;
}
static function blowCaches($tagger, $tagged) {
public static function blowCaches($tagger, $tagged)
{
foreach (array(0, 1) as $perm) {
self::blow(sprintf('profile_tag:tagger_tagged_privacy:%d-%d-%d', $tagger, $tagged, $perm));
}
@ -293,38 +319,43 @@ class Profile_tag extends Managed_DataObject
}
// Return profiles with a given tag
static function getTagged($tagger, $tag) {
public static function getTagged($tagger, $tag)
{
$profile = new Profile();
$profile->query('SELECT profile.* ' .
'FROM profile JOIN profile_tag ' .
'ON profile.id = profile_tag.tagged ' .
'WHERE profile_tag.tagger = ' . $profile->escape($tagger) . ' ' .
'AND profile_tag.tag = "' . $profile->escape($tag) . '" ');
$tagged = array();
"AND profile_tag.tag = '" . $profile->escape($tag) . "' ");
$tagged = [];
while ($profile->fetch()) {
$tagged[] = clone($profile);
}
return true;
}
function insert()
public function insert()
{
$result = parent::insert();
if ($result) {
self::blow('profile_list:tagged_count:%d:%s',
$this->tagger,
$this->tag);
self::blow(
'profile_list:tagged_count:%d:%s',
$this->tagger,
$this->tag
);
}
return $result;
}
function delete($useWhere=false)
public function delete($useWhere = false)
{
$result = parent::delete($useWhere);
if ($result !== false) {
self::blow('profile_list:tagged_count:%d:%s',
$this->tagger,
$this->tag);
self::blow(
'profile_list:tagged_count:%d:%s',
$this->tagger,
$this->tag
);
}
return $result;
}

View File

@ -1,23 +1,25 @@
<?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/>.
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* @copyright 2008, 2009, StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('GNUSOCIAL')) { exit(1); }
defined('GNUSOCIAL') || die();
/**
* Table Definition for subscription
@ -30,8 +32,8 @@ class Subscription extends Managed_DataObject
public $__table = 'subscription'; // table name
public $subscriber; // int(4) primary_key not_null
public $subscribed; // int(4) primary_key not_null
public $jabber; // tinyint(1) default_1
public $sms; // tinyint(1) default_1
public $jabber; // bool default_true
public $sms; // bool default_true
public $token; // varchar(191) not 255 because utf8mb4 takes more space
public $secret; // varchar(191) not 255 because utf8mb4 takes more space
public $uri; // varchar(191) not 255 because utf8mb4 takes more space
@ -44,8 +46,8 @@ class Subscription extends Managed_DataObject
'fields' => array(
'subscriber' => array('type' => 'int', 'not null' => true, 'description' => 'profile listening'),
'subscribed' => array('type' => 'int', 'not null' => true, 'description' => 'profile being listened to'),
'jabber' => array('type' => 'int', 'size' => 'tiny', 'default' => 1, 'description' => 'deliver jabber messages'),
'sms' => array('type' => 'int', 'size' => 'tiny', 'default' => 1, 'description' => 'deliver sms messages'),
'jabber' => array('type' => 'bool', 'default' => true, 'description' => 'deliver jabber messages'),
'sms' => array('type' => 'bool', 'default' => true, 'description' => 'deliver sms messages'),
'token' => array('type' => 'varchar', 'length' => 191, 'description' => 'authorization token'),
'secret' => array('type' => 'varchar', 'length' => 191, 'description' => 'token secret'),
'uri' => array('type' => 'varchar', 'length' => 191, 'description' => 'universally unique identifier'),
@ -74,7 +76,7 @@ class Subscription extends Managed_DataObject
* @return mixed Subscription or Subscription_queue: new subscription info
*/
static function start(Profile $subscriber, Profile $other, $force=false)
public static function start(Profile $subscriber, Profile $other, $force = false)
{
if (!$subscriber->hasRight(Right::SUBSCRIBE)) {
// TRANS: Exception thrown when trying to subscribe while being banned from subscribing.
@ -117,7 +119,6 @@ class Subscription extends Managed_DataObject
$otherUser->autosubscribe &&
!self::exists($other, $subscriber) &&
!$subscriber->hasBlocked($other)) {
try {
self::start($other, $subscriber);
} catch (AlreadyFulfilledException $e) {
@ -137,7 +138,7 @@ class Subscription extends Managed_DataObject
return $sub;
}
static function ensureStart(Profile $subscriber, Profile $other, $force=false)
public static function ensureStart(Profile $subscriber, Profile $other, $force = false)
{
try {
$sub = self::start($subscriber, $other, $force);
@ -157,12 +158,14 @@ class Subscription extends Managed_DataObject
$sub->subscriber = $subscriber->getID();
$sub->subscribed = $other->getID();
$sub->jabber = 1;
$sub->sms = 1;
$sub->jabber = true;
$sub->sms = true;
$sub->created = common_sql_now();
$sub->uri = self::newUri($subscriber,
$other,
$sub->created);
$sub->uri = self::newUri(
$subscriber,
$other,
$sub->created
);
$result = $sub->insert();
@ -175,7 +178,7 @@ class Subscription extends Managed_DataObject
return $sub;
}
function notify()
public function notify()
{
// XXX: add other notifications (Jabber, SMS) here
// XXX: queue this and handle it offline
@ -184,12 +187,11 @@ class Subscription extends Managed_DataObject
$this->notifyEmail();
}
function notifyEmail()
public function notifyEmail()
{
$subscribedUser = User::getKV('id', $this->subscribed);
if ($subscribedUser instanceof User) {
$subscriber = Profile::getKV('id', $this->subscriber);
mail_subscribe_notify_profile($subscribedUser, $subscriber);
@ -200,7 +202,7 @@ class Subscription extends Managed_DataObject
* Cancel a subscription
*
*/
static function cancel(Profile $subscriber, Profile $other)
public static function cancel(Profile $subscriber, Profile $other)
{
if (!self::exists($subscriber, $other)) {
// TRANS: Exception thrown when trying to unsibscribe without a subscription.
@ -215,7 +217,6 @@ class Subscription extends Managed_DataObject
}
if (Event::handle('StartUnsubscribe', array($subscriber, $other))) {
$sub = Subscription::pkeyGet(array('subscriber' => $subscriber->id,
'subscribed' => $other->id));
@ -245,7 +246,7 @@ class Subscription extends Managed_DataObject
return;
}
static function exists(Profile $subscriber, Profile $other)
public static function exists(Profile $subscriber, Profile $other)
{
try {
$sub = self::getSubscription($subscriber, $other);
@ -256,7 +257,7 @@ class Subscription extends Managed_DataObject
return true;
}
static function getSubscription(Profile $subscriber, Profile $other)
public static function getSubscription(Profile $subscriber, Profile $other)
{
// This is essentially a pkeyGet but we have an object to return in NoResultException
$sub = new Subscription();
@ -278,7 +279,7 @@ class Subscription extends Managed_DataObject
return Profile::getByID($this->subscribed);
}
function asActivity()
public function asActivity()
{
$subscriber = $this->getSubscriber();
$subscribed = $this->getSubscribed();
@ -293,19 +294,25 @@ class Subscription extends Managed_DataObject
$act->time = strtotime($this->created);
// TRANS: Activity title when subscribing to another person.
$act->title = _m('TITLE','Follow');
$act->title = _m('TITLE', 'Follow');
// TRANS: Notification given when one person starts following another.
// TRANS: %1$s is the subscriber, %2$s is the subscribed.
$act->content = sprintf(_('%1$s is now following %2$s.'),
$subscriber->getBestName(),
$subscribed->getBestName());
$act->content = sprintf(
_('%1$s is now following %2$s.'),
$subscriber->getBestName(),
$subscribed->getBestName()
);
$act->actor = $subscriber->asActivityObject();
$act->objects[] = $subscribed->asActivityObject();
$url = common_local_url('AtomPubShowSubscription',
array('subscriber' => $subscriber->id,
'subscribed' => $subscribed->id));
$url = common_local_url(
'AtomPubShowSubscription',
[
'subscriber' => $subscriber->id,
'subscribed' => $subscribed->id,
]
);
$act->selfLink = $url;
$act->editLink = $url;
@ -356,11 +363,13 @@ class Subscription extends Managed_DataObject
// The following are helper functions to the subscription lists,
// notably the public ones get used in places such as Profile
public static function getSubscribedIDs($profile_id, $offset, $limit) {
public static function getSubscribedIDs($profile_id, $offset, $limit)
{
return self::getSubscriptionIDs('subscribed', $profile_id, $offset, $limit);
}
public static function getSubscriberIDs($profile_id, $offset, $limit) {
public static function getSubscriberIDs($profile_id, $offset, $limit)
{
return self::getSubscriptionIDs('subscriber', $profile_id, $offset, $limit);
}
@ -397,7 +406,7 @@ class Subscription extends Managed_DataObject
$sub = new Subscription();
$sub->$by_type = $profile_id;
$sub->selectAdd($get_type);
$sub->whereAdd("{$get_type} != {$profile_id}");
$sub->whereAdd($get_type . ' <> ' . $profile_id);
$sub->orderBy('created DESC');
$sub->limit($queryoffset, $querylimit);
@ -426,7 +435,7 @@ class Subscription extends Managed_DataObject
*
* @return boolean success flag.
*/
function update($dataObject=false)
public function update($dataObject = false)
{
self::blow('subscription:by-subscriber:'.$this->subscriber);
self::blow('subscription:by-subscribed:'.$this->subscribed);

View File

@ -1,23 +1,20 @@
<?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/>.
*/
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
if (!defined('GNUSOCIAL')) { exit(1); }
defined('GNUSOCIAL') || die();
/**
* Table Definition for user
@ -37,24 +34,24 @@ class User extends Managed_DataObject
public $password; // varchar(191) not 255 because utf8mb4 takes more space
public $email; // varchar(191) unique_key not 255 because utf8mb4 takes more space
public $incomingemail; // varchar(191) unique_key not 255 because utf8mb4 takes more space
public $emailnotifysub; // tinyint(1) default_1
public $emailnotifyfav; // tinyint(1) default_1
public $emailnotifynudge; // tinyint(1) default_1
public $emailnotifymsg; // tinyint(1) default_1
public $emailnotifyattn; // tinyint(1) default_1
public $emailnotifysub; // bool default_true
public $emailnotifyfav; // tinyint(1) default_null
public $emailnotifynudge; // bool default_true
public $emailnotifymsg; // bool default_true
public $emailnotifyattn; // bool default_true
public $language; // varchar(50)
public $timezone; // varchar(50)
public $emailpost; // tinyint(1) default_1
public $emailpost; // bool default_true
public $sms; // varchar(64) unique_key
public $carrier; // int(4)
public $smsnotify; // tinyint(1)
public $smsreplies; // tinyint(1)
public $smsnotify; // bool default_false
public $smsreplies; // bool default_false
public $smsemail; // varchar(191) not 255 because utf8mb4 takes more space
public $uri; // varchar(191) unique_key not 255 because utf8mb4 takes more space
public $autosubscribe; // tinyint(1)
public $autosubscribe; // bool default_false
public $subscribe_policy; // tinyint(1)
public $urlshorteningservice; // varchar(50) default_ur1.ca
public $private_stream; // tinyint(1) default_0
public $private_stream; // bool default_false
public $created; // datetime() not_null default_0000-00-00%2000%3A00%3A00
public $modified; // datetime() not_null default_CURRENT_TIMESTAMP
@ -71,24 +68,24 @@ class User extends Managed_DataObject
'password' => array('type' => 'varchar', 'length' => 191, 'description' => 'salted password, can be null for OpenID users'),
'email' => array('type' => 'varchar', 'length' => 191, 'description' => 'email address for password recovery etc.'),
'incomingemail' => array('type' => 'varchar', 'length' => 191, 'description' => 'email address for post-by-email'),
'emailnotifysub' => array('type' => 'int', 'size' => 'tiny', 'default' => 1, 'description' => 'Notify by email of subscriptions'),
'emailnotifysub' => array('type' => 'bool', 'default' => true, 'description' => 'Notify by email of subscriptions'),
'emailnotifyfav' => array('type' => 'int', 'size' => 'tiny', 'default' => null, 'description' => 'Notify by email of favorites'),
'emailnotifynudge' => array('type' => 'int', 'size' => 'tiny', 'default' => 1, 'description' => 'Notify by email of nudges'),
'emailnotifymsg' => array('type' => 'int', 'size' => 'tiny', 'default' => 1, 'description' => 'Notify by email of direct messages'),
'emailnotifyattn' => array('type' => 'int', 'size' => 'tiny', 'default' => 1, 'description' => 'Notify by email of @-replies'),
'emailnotifynudge' => array('type' => 'bool', 'default' => true, 'description' => 'Notify by email of nudges'),
'emailnotifymsg' => array('type' => 'bool', 'default' => true, 'description' => 'Notify by email of direct messages'),
'emailnotifyattn' => array('type' => 'bool', 'default' => true, 'description' => 'Notify by email of @-replies'),
'language' => array('type' => 'varchar', 'length' => 50, 'description' => 'preferred language'),
'timezone' => array('type' => 'varchar', 'length' => 50, 'description' => 'timezone'),
'emailpost' => array('type' => 'int', 'size' => 'tiny', 'default' => 1, 'description' => 'Post by email'),
'emailpost' => array('type' => 'bool', 'default' => true, 'description' => 'Post by email'),
'sms' => array('type' => 'varchar', 'length' => 64, 'description' => 'sms phone number'),
'carrier' => array('type' => 'int', 'description' => 'foreign key to sms_carrier'),
'smsnotify' => array('type' => 'int', 'size' => 'tiny', 'default' => 0, 'description' => 'whether to send notices to SMS'),
'smsreplies' => array('type' => 'int', 'size' => 'tiny', 'default' => 0, 'description' => 'whether to send notices to SMS on replies'),
'smsnotify' => array('type' => 'bool', 'default' => false, 'description' => 'whether to send notices to SMS'),
'smsreplies' => array('type' => 'bool', 'default' => false, 'description' => 'whether to send notices to SMS on replies'),
'smsemail' => array('type' => 'varchar', 'length' => 191, 'description' => 'built from sms and carrier'),
'uri' => array('type' => 'varchar', 'length' => 191, 'description' => 'universally unique identifier, usually a tag URI'),
'autosubscribe' => array('type' => 'int', 'size' => 'tiny', 'default' => 0, 'description' => 'automatically subscribe to users who subscribe to us'),
'autosubscribe' => array('type' => 'bool', 'default' => false, 'description' => 'automatically subscribe to users who subscribe to us'),
'subscribe_policy' => array('type' => 'int', 'size' => 'tiny', 'default' => 0, 'description' => '0 = anybody can subscribe; 1 = require approval'),
'urlshorteningservice' => array('type' => 'varchar', 'length' => 50, 'default' => 'internal', 'description' => 'service to use for auto-shortening URLs'),
'private_stream' => array('type' => 'int', 'size' => 'tiny', 'default' => 0, 'description' => 'whether to limit all notices to followers only'),
'private_stream' => array('type' => 'bool', 'default' => false, 'description' => 'whether to limit all notices to followers only'),
'created' => array('type' => 'datetime', 'not null' => true, 'default' => '0000-00-00 00:00:00', 'description' => 'date this record was created'),
'modified' => array('type' => 'datetime', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was modified'),
),
@ -144,7 +141,7 @@ class User extends Managed_DataObject
return $this->getProfile()->getNickname();
}
static function getByNickname($nickname)
public static function getByNickname($nickname)
{
$user = User::getKV('nickname', $nickname);
if (!$user instanceof User) {
@ -154,12 +151,12 @@ class User extends Managed_DataObject
return $user;
}
function isSubscribed(Profile $other)
public function isSubscribed(Profile $other)
{
return $this->getProfile()->isSubscribed($other);
}
function hasPendingSubscription(Profile $other)
public function hasPendingSubscription(Profile $other)
{
return $this->getProfile()->hasPendingSubscription($other);
}
@ -169,17 +166,17 @@ class User extends Managed_DataObject
*
* @return mixed Notice or null
*/
function getCurrentNotice()
public function getCurrentNotice()
{
return $this->getProfile()->getCurrentNotice();
}
function getCarrier()
public function getCarrier()
{
return Sms_carrier::getKV('id', $this->carrier);
}
function hasBlocked(Profile $other)
public function hasBlocked(Profile $other)
{
return $this->getProfile()->hasBlocked($other);
}
@ -206,10 +203,9 @@ class User extends Managed_DataObject
* @return User object
* @throws Exception on failure
*/
static function register(array $fields, $accept_email_fail=false) {
public static function register(array $fields, $accept_email_fail = false)
{
// MAGICALLY put fields into current scope
extract($fields);
$profile = new Profile();
@ -262,23 +258,22 @@ class User extends Managed_DataObject
}
}
if(isset($email_confirmed) && $email_confirmed) {
if (isset($email_confirmed) && $email_confirmed) {
$user->email = $email;
}
// Set default-on options here, otherwise they'll be disabled
// initially for sites using caching, since the initial encache
// doesn't know about the defaults in the database.
$user->emailnotifysub = 1;
$user->emailnotifynudge = 1;
$user->emailnotifymsg = 1;
$user->emailnotifyattn = 1;
$user->emailpost = 1;
$user->emailnotifysub = true;
$user->emailnotifynudge = true;
$user->emailnotifymsg = true;
$user->emailnotifyattn = true;
$user->emailpost = true;
$user->created = common_sql_now();
if (Event::handle('StartUserRegister', array($profile))) {
$profile->query('BEGIN');
$id = $profile->insert();
@ -291,7 +286,7 @@ class User extends Managed_DataObject
// Necessary because id has been known to be reissued.
if ($profile->hasRole(Profile_role::DELETED)) {
$profile->revokeRole(Profile_role::DELETED);
$profile->revokeRole(Profile_role::DELETED);
}
$user->id = $id;
@ -367,8 +362,11 @@ class User extends Managed_DataObject
if (!empty($defnick)) {
$defuser = User::getKV('nickname', $defnick);
if (empty($defuser)) {
common_log(LOG_WARNING, sprintf("Default user %s does not exist.", $defnick),
__FILE__);
common_log(
LOG_WARNING,
sprintf('Default user %s does not exist.', $defnick),
__FILE__
);
} else {
Subscription::ensureStart($profile, $defuser->getProfile());
}
@ -394,16 +392,23 @@ class User extends Managed_DataObject
if (!empty($welcome)) {
$welcomeuser = User::getKV('nickname', $welcome);
if (empty($welcomeuser)) {
common_log(LOG_WARNING, sprintf("Welcome user %s does not exist.", $defnick),
__FILE__);
common_log(
LOG_WARNING,
sprintf('Welcome user %s does not exist.', $defnick),
__FILE__
);
} else {
$notice = Notice::saveNew($welcomeuser->id,
// TRANS: Notice given on user registration.
// TRANS: %1$s is the sitename, $2$s is the registering user's nickname.
sprintf(_('Welcome to %1$s, @%2$s!'),
common_config('site', 'name'),
$profile->getNickname()),
'system');
$notice = Notice::saveNew(
$welcomeuser->id,
// TRANS: Notice given on user registration.
// TRANS: %1$s is the sitename, $2$s is the registering user's nickname.
sprintf(
_('Welcome to %1$s, @%2$s!'),
common_config('site', 'name'),
$profile->getNickname()
),
'system'
);
}
}
@ -418,9 +423,8 @@ class User extends Managed_DataObject
}
// Things we do when the email changes
function emailChanged()
public function emailChanged()
{
$invites = new Invitation();
$invites->address = $this->email;
$invites->address_type = 'email';
@ -441,48 +445,53 @@ class User extends Managed_DataObject
}
}
function mutuallySubscribed(Profile $other)
public function mutuallySubscribed(Profile $other)
{
return $this->getProfile()->mutuallySubscribed($other);
}
function mutuallySubscribedUsers()
public function mutuallySubscribedUsers()
{
// 3-way join; probably should get cached
$UT = common_config('db','type')=='pgsql'?'"user"':'user';
$qry = "SELECT $UT.* " .
"FROM subscription sub1 JOIN $UT ON sub1.subscribed = $UT.id " .
"JOIN subscription sub2 ON $UT.id = sub2.subscriber " .
'WHERE sub1.subscriber = %d and sub2.subscribed = %d ' .
"ORDER BY $UT.nickname";
$user = new User();
$user->query(sprintf($qry, $this->id, $this->id));
// 3-way join; probably should get cached
$user->query(sprintf(
'SELECT %1$s.* ' .
'FROM subscription AS sub1 INNER JOIN %1$s ON sub1.subscribed = %1$s.id ' .
'INNER JOIN subscription AS sub2 ON %1$s.id = sub2.subscriber ' .
'WHERE sub1.subscriber = %2$d AND sub2.subscribed = %2$d ' .
'ORDER BY %1$s.nickname',
$user->escapedTableName(),
$this->id
));
return $user;
}
function getReplies($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0)
public function getReplies($offset = 0, $limit = NOTICES_PER_PAGE, $since_id = 0, $before_id = 0)
{
return $this->getProfile()->getReplies($offset, $limit, $since_id, $before_id);
}
function getTaggedNotices($tag, $offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0) {
public function getTaggedNotices($tag, $offset = 0, $limit = NOTICES_PER_PAGE, $since_id = 0, $before_id = 0)
{
return $this->getProfile()->getTaggedNotices($tag, $offset, $limit, $since_id, $before_id);
}
function getNotices($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0)
public function getNotices($offset = 0, $limit = NOTICES_PER_PAGE, $since_id = 0, $before_id = 0)
{
return $this->getProfile()->getNotices($offset, $limit, $since_id, $before_id);
}
function block(Profile $other)
public function block(Profile $other)
{
// Add a new block record
// no blocking (and thus unsubbing from) yourself
if ($this->id == $other->id) {
common_log(LOG_WARNING,
common_log(
LOG_WARNING,
sprintf(
"Profile ID %d (%s) tried to block themself.",
$this->id,
@ -521,7 +530,7 @@ class User extends Managed_DataObject
return true;
}
function unblock(Profile $other)
public function unblock(Profile $other)
{
// Get the block record
@ -541,17 +550,17 @@ class User extends Managed_DataObject
return true;
}
function isMember(User_group $group)
public function isMember(User_group $group)
{
return $this->getProfile()->isMember($group);
}
function isAdmin(User_group $group)
public function isAdmin(User_group $group)
{
return $this->getProfile()->isAdmin($group);
}
function getGroups($offset=0, $limit=null)
public function getGroups($offset = 0, $limit = null)
{
return $this->getProfile()->getGroups($offset, $limit);
}
@ -563,7 +572,7 @@ class User extends Managed_DataObject
* @param User_group $group
* @return Group_member
*/
function joinGroup(User_group $group)
public function joinGroup(User_group $group)
{
return $this->getProfile()->joinGroup($group);
}
@ -573,37 +582,37 @@ class User extends Managed_DataObject
*
* @param User_group $group
*/
function leaveGroup(User_group $group)
public function leaveGroup(User_group $group)
{
return $this->getProfile()->leaveGroup($group);
}
function getSubscribed($offset=0, $limit=null)
public function getSubscribed($offset = 0, $limit = null)
{
return $this->getProfile()->getSubscribed($offset, $limit);
}
function getSubscribers($offset=0, $limit=null)
public function getSubscribers($offset = 0, $limit = null)
{
return $this->getProfile()->getSubscribers($offset, $limit);
}
function getTaggedSubscribers($tag, $offset=0, $limit=null)
public function getTaggedSubscribers($tag, $offset = 0, $limit = null)
{
return $this->getProfile()->getTaggedSubscribers($tag, $offset, $limit);
}
function getTaggedSubscriptions($tag, $offset=0, $limit=null)
public function getTaggedSubscriptions($tag, $offset = 0, $limit = null)
{
return $this->getProfile()->getTaggedSubscriptions($tag, $offset, $limit);
}
function hasRight($right)
public function hasRight($right)
{
return $this->getProfile()->hasRight($right);
}
function delete($useWhere=false)
public function delete($useWhere = false)
{
if (empty($this->id)) {
common_log(LOG_WARNING, "Ambiguous User->delete(); skipping related tables.");
@ -640,14 +649,14 @@ class User extends Managed_DataObject
return parent::delete($useWhere);
}
function _deleteTags()
public function _deleteTags()
{
$tag = new Profile_tag();
$tag->tagger = $this->id;
$tag->delete();
}
function _deleteBlocks()
public function _deleteBlocks()
{
$block = new Profile_block();
$block->blocker = $this->id;
@ -655,32 +664,32 @@ class User extends Managed_DataObject
// XXX delete group block? Reset blocker?
}
function hasRole($name)
public function hasRole($name)
{
return $this->getProfile()->hasRole($name);
}
function grantRole($name)
public function grantRole($name)
{
return $this->getProfile()->grantRole($name);
}
function revokeRole($name)
public function revokeRole($name)
{
return $this->getProfile()->revokeRole($name);
}
function isSandboxed()
public function isSandboxed()
{
return $this->getProfile()->isSandboxed();
}
function isSilenced()
public function isSilenced()
{
return $this->getProfile()->isSilenced();
}
function receivesEmailNotifications()
public function receivesEmailNotifications()
{
// We could do this in one large if statement, but that's not as easy to read
// Don't send notifications if we don't know the user's email address or it is
@ -695,7 +704,7 @@ class User extends Managed_DataObject
return true;
}
function repeatedByMe($offset=0, $limit=20, $since_id=null, $max_id=null)
public function repeatedByMe($offset = 0, $limit = 20, $since_id = null, $max_id = null)
{
// FIXME: Use another way to get Profile::current() since we
// want to avoid confusion between session user and queue processing.
@ -704,7 +713,7 @@ class User extends Managed_DataObject
}
function repeatsOfMe($offset=0, $limit=20, $since_id=null, $max_id=null)
public function repeatsOfMe($offset = 0, $limit = 20, $since_id = null, $max_id = null)
{
// FIXME: Use another way to get Profile::current() since we
// want to avoid confusion between session user and queue processing.
@ -712,7 +721,7 @@ class User extends Managed_DataObject
return $stream->getNotices($offset, $limit, $since_id, $max_id);
}
public function repeatedToMe($offset=0, $limit=20, $since_id=null, $max_id=null)
public function repeatedToMe($offset = 0, $limit = 20, $since_id = null, $max_id = null)
{
return $this->getProfile()->repeatedToMe($offset, $limit, $since_id, $max_id);
}
@ -791,7 +800,7 @@ class User extends Managed_DataObject
* @throws ServerException if no valid single user account is present
* @throws ServerException if called when not in single-user mode
*/
static function singleUserNickname()
public static function singleUserNickname()
{
try {
$user = User::singleUser();
@ -828,7 +837,7 @@ class User extends Managed_DataObject
* Get a list of OAuth client applications that have access to this
* user's account.
*/
function getConnectedApps($offset = 0, $limit = null)
public function getConnectedApps($offset = 0, $limit = null)
{
$qry =
'SELECT u.* ' .
@ -839,11 +848,7 @@ class User extends Managed_DataObject
'ORDER BY u.created DESC ';
if ($offset > 0) {
if (common_config('db','type') == 'pgsql') {
$qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
} else {
$qry .= ' LIMIT ' . $offset . ', ' . $limit;
}
$qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
}
$apps = new Oauth_application_user();
@ -863,14 +868,14 @@ class User extends Managed_DataObject
* @return array of variable names to include in serialization.
*/
function __sleep()
public function __sleep()
{
$vars = parent::__sleep();
$skip = array('_profile');
return array_diff($vars, $skip);
}
static function recoverPassword($nore)
public static function recoverPassword($nore)
{
require_once INSTALLDIR . '/lib/util/mail.php';
@ -943,7 +948,7 @@ class User extends Managed_DataObject
throw new ServerException(_('Error saving address confirmation.'));
}
// @todo FIXME: needs i18n.
// @todo FIXME: needs i18n.
$body = "Hey, $user->nickname.";
$body .= "\n\n";
$body .= 'Someone just asked for a new password ' .
@ -951,8 +956,10 @@ class User extends Managed_DataObject
$body .= "\n\n";
$body .= 'If it was you, and you want to confirm, use the URL below:';
$body .= "\n\n";
$body .= "\t".common_local_url('recoverpassword',
array('code' => $confirm->code));
$body .= "\t" . common_local_url(
'recoverpassword',
['code' => $confirm->code]
);
$body .= "\n\n";
$body .= 'If not, just ignore this message.';
$body .= "\n\n";
@ -966,7 +973,7 @@ class User extends Managed_DataObject
mail_to_user($user, _('Password recovery requested'), $body, $headers, $confirm->address);
}
function streamModeOnly()
public function streamModeOnly()
{
if (common_config('oldschool', 'enabled')) {
$osp = Old_school_prefs::getKV('user_id', $this->id);
@ -978,7 +985,7 @@ class User extends Managed_DataObject
return false;
}
function streamNicknames()
public function streamNicknames()
{
if (common_config('oldschool', 'enabled')) {
$osp = Old_school_prefs::getKV('user_id', $this->id);
@ -989,7 +996,7 @@ class User extends Managed_DataObject
return false;
}
function registrationActivity()
public function registrationActivity()
{
$profile = $this->getProfile();
@ -1007,16 +1014,20 @@ class User extends Managed_DataObject
$act->objects[] = $service;
$act->id = TagURI::mint('user:register:%d',
$this->id);
$act->id = TagURI::mint(
'user:register:%d',
$this->id
);
$act->time = strtotime($this->created);
$act->title = _("Register");
$act->content = sprintf(_('%1$s joined %2$s.'),
$profile->getBestName(),
$service->title);
$act->content = sprintf(
_('%1$s joined %2$s.'),
$profile->getBestName(),
$service->title
);
return $act;
}

View File

@ -1,8 +1,24 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
defined('GNUSOCIAL') || die();
/**
* Table Definition for user_group
*/
class User_group extends Managed_DataObject
{
const JOIN_POLICY_OPEN = 0;
@ -63,7 +79,7 @@ class User_group extends Managed_DataObject
'uri' => array('type' => 'varchar', 'length' => 191, 'description' => 'universal identifier'),
'mainpage' => array('type' => 'varchar', 'length' => 191, 'description' => 'page for group info to link to'),
'join_policy' => array('type' => 'int', 'size' => 'tiny', 'description' => '0=open; 1=requires admin approval'),
'join_policy' => array('type' => 'int', 'size' => 'tiny', 'description' => '0=open; 1=requires admin approval'),
'force_scope' => array('type' => 'int', 'size' => 'tiny', 'description' => '0=never,1=sometimes,-1=always'),
),
'primary key' => array('id'),
@ -118,40 +134,38 @@ class User_group extends Managed_DataObject
return Theme::path('default-avatar-'.$sizenames[$size].'.png');
}
function homeUrl()
public function homeUrl()
{
return $this->getProfile()->getUrl();
}
function getUri()
public function getUri()
{
$uri = null;
if (Event::handle('StartUserGroupGetUri', array($this, &$uri))) {
if (!empty($this->uri)) {
$uri = $this->uri;
} elseif ($this->isLocal()) {
$uri = common_local_url('groupbyid',
array('id' => $this->id));
$uri = common_local_url('groupbyid', ['id' => $this->id]);
}
}
Event::handle('EndUserGroupGetUri', array($this, &$uri));
return $uri;
}
function permalink()
public function permalink()
{
$url = null;
if (Event::handle('StartUserGroupPermalink', array($this, &$url))) {
if ($this->isLocal()) {
$url = common_local_url('groupbyid',
array('id' => $this->id));
$url = common_local_url('groupbyid', ['id' => $this->id]);
}
}
Event::handle('EndUserGroupPermalink', array($this, &$url));
return $url;
}
function getNotices($offset, $limit, $since_id=null, $max_id=null)
public function getNotices($offset, $limit, $since_id = null, $max_id = null)
{
// FIXME: Get the Profile::current() some other way, to avoid
// possible confusion between current session and queue process.
@ -160,29 +174,26 @@ class User_group extends Managed_DataObject
return $stream->getNotices($offset, $limit, $since_id, $max_id);
}
function getMembers($offset=0, $limit=null) {
public function getMembers($offset = 0, $limit = null)
{
$ids = null;
if (is_null($limit) || $offset + $limit > User_group::CACHE_WINDOW) {
$ids = $this->getMemberIDs($offset,
$limit);
$ids = $this->getMemberIDs($offset, $limit);
} else {
$key = sprintf('group:member_ids:%d', $this->id);
$window = self::cacheGet($key);
if ($window === false) {
$window = $this->getMemberIDs(0,
User_group::CACHE_WINDOW);
$window = $this->getMemberIDs(0, User_group::CACHE_WINDOW);
self::cacheSet($key, $window);
}
$ids = array_slice($window,
$offset,
$limit);
$ids = array_slice($window, $offset, $limit);
}
return Profile::multiGet('id', $ids);
}
function getMemberIDs($offset=0, $limit=null)
public function getMemberIDs($offset = 0, $limit = null)
{
$gm = new Group_member();
@ -215,7 +226,7 @@ class User_group extends Managed_DataObject
* @param int $limit
* @return Profile
*/
function getRequests($offset=0, $limit=null)
public function getRequests($offset = 0, $limit = null)
{
$rq = new Group_join_queue();
$rq->group_id = $this->id;
@ -237,7 +248,7 @@ class User_group extends Managed_DataObject
{
$block = new Group_member();
$block->group_id = $this->id;
$block->is_admin = 1;
$block->is_admin = true;
return $block->count();
}
@ -264,7 +275,7 @@ class User_group extends Managed_DataObject
return $cnt;
}
function getBlockedCount()
public function getBlockedCount()
{
// XXX: WORM cache this
@ -274,7 +285,7 @@ class User_group extends Managed_DataObject
return $block->count();
}
function getQueueCount()
public function getQueueCount()
{
// XXX: WORM cache this
@ -284,11 +295,12 @@ class User_group extends Managed_DataObject
return $queue->count();
}
function getAdmins($offset=null, $limit=null) // offset is null because DataObject wants it, 0 would mean no results
// offset is null because DataObject wants it, 0 would mean no results
public function getAdmins($offset = null, $limit = null)
{
$admins = new Profile();
$admins->joinAdd(array('id', 'group_member:profile_id'));
$admins->whereAdd(sprintf('group_member.group_id = %u AND group_member.is_admin = 1', $this->id));
$admins->whereAdd('group_member.group_id = ' . $this->id . ' AND group_member.is_admin = true');
$admins->orderBy('group_member.modified ASC');
$admins->limit($offset, $limit);
$admins->find();
@ -296,7 +308,8 @@ class User_group extends Managed_DataObject
return $admins;
}
function getBlocked($offset=null, $limit=null) // offset is null because DataObject wants it, 0 would mean no results
// offset is null because DataObject wants it, 0 would mean no results
public function getBlocked($offset = null, $limit = null)
{
$blocked = new Profile();
$blocked->joinAdd(array('id', 'group_block:blocked'));
@ -308,7 +321,7 @@ class User_group extends Managed_DataObject
return $blocked;
}
function setOriginal($filename)
public function setOriginal($filename)
{
// This should be handled by the Profile->setOriginal function so user and group avatars are handled the same
$imagefile = new ImageFile(null, Avatar::path($filename));
@ -320,8 +333,12 @@ class User_group extends Managed_DataObject
$orig = clone($this);
$this->original_logo = Avatar::url($filename);
foreach ($sizes as $name=>$size) {
$filename = Avatar::filename($this->profile_id, image_type_to_extension($imagefile->preferredType()),
$size, common_timestamp());
$filename = Avatar::filename(
$this->profile_id,
image_type_to_extension($imagefile->preferredType()),
$size,
common_timestamp()
);
$imagefile->resizeTo(Avatar::path($filename), array('width'=>$size, 'height'=>$size));
$this->$name = Avatar::url($filename);
}
@ -329,7 +346,7 @@ class User_group extends Managed_DataObject
return $this->update($orig);
}
function getBestName()
public function getBestName()
{
return ($this->fullname) ? $this->fullname : $this->nickname;
}
@ -340,17 +357,17 @@ class User_group extends Managed_DataObject
*
* @return string
*/
function getFancyName()
public function getFancyName()
{
if ($this->fullname) {
// TRANS: Full name of a profile or group followed by nickname in parens
return sprintf(_m('FANCYNAME','%1$s (%2$s)'), $this->fullname, $this->nickname);
return sprintf(_m('FANCYNAME', '%1$s (%2$s)'), $this->fullname, $this->nickname);
} else {
return $this->nickname;
}
}
function getAliases()
public function getAliases()
{
$aliases = array();
@ -371,8 +388,8 @@ class User_group extends Managed_DataObject
return $aliases;
}
function setAliases($newaliases) {
public function setAliases($newaliases)
{
$newaliases = array_unique($newaliases);
$oldaliases = $this->getAliases();
@ -413,7 +430,7 @@ class User_group extends Managed_DataObject
return true;
}
static function getForNickname($nickname, Profile $profile=null)
public static function getForNickname($nickname, Profile $profile = null)
{
$nickname = Nickname::normalize($nickname);
@ -440,24 +457,21 @@ class User_group extends Managed_DataObject
return null;
}
function getUserMembers()
public function getUserMembers()
{
// XXX: cache this
$user = new User();
if(common_config('db','quote_identifiers'))
$user_table = '"user"';
else $user_table = 'user';
$qry =
'SELECT id ' .
'FROM '. $user_table .' JOIN group_member '.
'ON '. $user_table .'.id = group_member.profile_id ' .
'WHERE group_member.group_id = %d ';
$user->query(sprintf(
'SELECT id FROM %1$s INNER JOIN group_member ' .
'ON %1$s.id = group_member.profile_id ' .
'WHERE group_member.group_id = %2$d ',
$user->escapedTableName(),
$this->id
));
$user->query(sprintf($qry, $this->id));
$ids = array();
$ids = [];
while ($user->fetch()) {
$ids[] = $user->id;
@ -468,7 +482,7 @@ class User_group extends Managed_DataObject
return $ids;
}
static function maxDescription()
public static function maxDescription()
{
$desclimit = common_config('group', 'desclimit');
// null => use global limit (distinct from 0!)
@ -478,13 +492,13 @@ class User_group extends Managed_DataObject
return $desclimit;
}
static function descriptionTooLong($desc)
public static function descriptionTooLong($desc)
{
$desclimit = self::maxDescription();
return ($desclimit > 0 && !empty($desc) && (mb_strlen($desc) > $desclimit));
}
function asAtomEntry($namespace=false, $source=false)
public function asAtomEntry($namespace = false, $source = false)
{
$xs = new XMLStringer(true);
@ -528,7 +542,7 @@ class User_group extends Managed_DataObject
return $xs->getString();
}
function asAtomAuthor()
public function asAtomAuthor()
{
$xs = new XMLStringer(true);
@ -551,20 +565,21 @@ class User_group extends Managed_DataObject
*
* @return string
*/
function asActivityNoun($element)
public function asActivityNoun($element)
{
$noun = ActivityObject::fromGroup($this);
return $noun->asString('activity:' . $element);
}
function getAvatar()
public function getAvatar()
{
return empty($this->homepage_logo)
? User_group::defaultLogo(AVATAR_PROFILE_SIZE)
: $this->homepage_logo;
}
static function register($fields) {
public static function register($fields)
{
if (!empty($fields['userid'])) {
$profile = Profile::getKV('id', $fields['userid']);
if ($profile && !$profile->hasRight(Right::CREATEGROUP)) {
@ -580,18 +595,20 @@ class User_group extends Managed_DataObject
// MAGICALLY put fields into current scope
// @fixme kill extract(); it makes debugging absurdly hard
$defaults = array('nickname' => null,
'fullname' => null,
'homepage' => null,
'description' => null,
'location' => null,
'uri' => null,
'mainpage' => null,
'aliases' => array(),
'userid' => null);
$fields = array_merge($defaults, $fields);
$defaults = [
'nickname' => null,
'fullname' => null,
'homepage' => null,
'description' => null,
'location' => null,
'uri' => null,
'mainpage' => null,
'aliases' => [],
'userid' => null,
];
$fields = array_merge($defaults, $fields);
extract($fields);
$group = new User_group();
@ -645,7 +662,6 @@ class User_group extends Managed_DataObject
}
if (Event::handle('StartGroupSave', array(&$group))) {
$result = $group->insert();
if ($result === false) {
@ -676,7 +692,7 @@ class User_group extends Managed_DataObject
$member->group_id = $group->id;
$member->profile_id = $userid;
$member->is_admin = 1;
$member->is_admin = true;
$member->created = $group->created;
$result = $member->insert();
@ -721,7 +737,7 @@ class User_group extends Managed_DataObject
* are not de-cached in the UI, including the sidebar lists on
* GroupsAction
*/
function delete($useWhere=false)
public function delete($useWhere = false)
{
if (empty($this->id)) {
common_log(LOG_WARNING, "Ambiguous User_group->delete(); skipping related tables.");
@ -813,7 +829,7 @@ class User_group extends Managed_DataObject
return parent::update($dataObject);
}
function isPrivate()
public function isPrivate()
{
return ($this->join_policy == self::JOIN_POLICY_MODERATE &&
intval($this->force_scope) === 1);
@ -825,14 +841,16 @@ class User_group extends Managed_DataObject
return ($local instanceof Local_group);
}
static function groupsFromText($text, Profile $profile)
public static function groupsFromText($text, Profile $profile)
{
$groups = array();
/* extract all !group */
$count = preg_match_all('/(?:^|\s)!(' . Nickname::DISPLAY_FMT . ')/',
strtolower($text),
$match);
$count = preg_match_all(
'/(?:^|\s)!(' . Nickname::DISPLAY_FMT . ')/',
strtolower($text),
$match
);
if (!$count) {
return $groups;
@ -848,7 +866,7 @@ class User_group extends Managed_DataObject
return $groups;
}
static function idsFromText($text, Profile $profile)
public static function idsFromText($text, Profile $profile)
{
$ids = array();
$groups = self::groupsFromText($text, $profile);

View File

@ -1,32 +1,31 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* StatusNet, the distributed open-source microblogging tool
*
* Data class for user IM preferences
*
* 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
* @package GNUsocial
* @author Craig Andrews <candrews@integralblue.com>
* @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/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
defined('GNUSOCIAL') || die();
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
class User_im_prefs extends Managed_DataObject
@ -38,9 +37,9 @@ class User_im_prefs extends Managed_DataObject
public $user_id; // int(4) primary_key not_null
public $screenname; // varchar(191) not_null not 255 because utf8mb4 takes more space
public $transport; // varchar(191) not_null not 255 because utf8mb4 takes more space
public $notify; // tinyint(1)
public $replies; // tinyint(1)
public $updatefrompresence; // tinyint(1)
public $notify; // bool not_null default_false
public $replies; // bool not_null default_false
public $updatefrompresence; // bool not_null default_false
public $created; // datetime() not_null default_0000-00-00%2000%3A00%3A00
public $modified; // datetime() not_null default_CURRENT_TIMESTAMP
@ -54,9 +53,9 @@ class User_im_prefs extends Managed_DataObject
'user_id' => array('type' => 'int', 'not null' => true, 'description' => 'user'),
'screenname' => array('type' => 'varchar', 'length' => 191, 'not null' => true, 'description' => 'screenname on this service'),
'transport' => array('type' => 'varchar', 'length' => 191, 'not null' => true, 'description' => 'transport (ex xmpp, aim)'),
'notify' => array('type' => 'int', 'size' => 'tiny', 'not null' => true, 'default' => 0, 'description' => 'Notify when a new notice is sent'),
'replies' => array('type' => 'int', 'size' => 'tiny', 'not null' => true, 'default' => 0, 'description' => 'Send replies from people not subscribed to'),
'updatefrompresence' => array('type' => 'int', 'size' => 'tiny', 'not null' => true, 'default' => 0, 'description' => 'Send replies from people not subscribed to.'),
'notify' => array('type' => 'bool', 'not null' => true, 'default' => false, 'description' => 'Notify when a new notice is sent'),
'replies' => array('type' => 'bool', 'not null' => true, 'default' => false, 'description' => 'Send replies from people not subscribed to'),
'updatefrompresence' => array('type' => 'bool', 'not null' => true, 'default' => false, 'description' => 'Update from presence.'),
'created' => array('type' => 'datetime', 'not null' => true, 'default' => '0000-00-00 00:00:00', 'description' => 'date this record was created'),
'modified' => array('type' => 'datetime', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was modified'),
),
@ -69,5 +68,4 @@ class User_im_prefs extends Managed_DataObject
),
);
}
}

View File

@ -1,30 +1,27 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* StatusNet, the distributed open-source microblogging tool
*
* Data class for user location preferences
*
* 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
* @package GNUsocial
* @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/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
@ -36,7 +33,7 @@ class User_location_prefs extends Managed_DataObject
public $__table = 'user_location_prefs'; // table name
public $user_id; // int(4) primary_key not_null
public $share_location; // tinyint(1) default_1
public $share_location; // bool default_true
public $created; // datetime() not_null default_0000-00-00%2000%3A00%3A00
public $modified; // datetime() not_null default_CURRENT_TIMESTAMP
@ -48,7 +45,7 @@ class User_location_prefs extends Managed_DataObject
return array(
'fields' => array(
'user_id' => array('type' => 'int', 'not null' => true, 'description' => 'user who has the preference'),
'share_location' => array('type' => 'int', 'size' => 'tiny', 'default' => 1, 'description' => 'Whether to share location data'),
'share_location' => array('type' => 'bool', 'default' => true, 'description' => 'Whether to share location data'),
'created' => array('type' => 'datetime', 'not null' => true, 'default' => '0000-00-00 00:00:00', 'description' => 'date this record was created'),
'modified' => array('type' => 'datetime', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was modified'),
),

View File

@ -1,9 +1,26 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
defined('GNUSOCIAL') || die();
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
/**
* Table Definition for user_username
*/
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
class User_username extends Managed_DataObject
{
###START_AUTOCODE
@ -23,8 +40,8 @@ class User_username extends Managed_DataObject
{
return array(
'fields' => array(
'provider_name' => array('type' => 'varchar', 'length' => 191, 'description' => 'provider name'),
'username' => array('type' => 'varchar', 'length' => 191, 'description' => 'username'),
'provider_name' => array('type' => 'varchar', 'not null' => true, 'length' => 191, 'description' => 'provider name'),
'username' => array('type' => 'varchar', 'not null' => true, 'length' => 191, 'description' => 'username'),
'user_id' => array('type' => 'int', 'not null' => true, 'description' => 'notice id this title relates to'),
'created' => array('type' => 'datetime', 'not null' => true, 'default' => '0000-00-00 00:00:00', 'description' => 'date this record was created'),
'modified' => array('type' => 'datetime', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was modified'),
@ -46,7 +63,7 @@ class User_username extends Managed_DataObject
* @param provider_name string name of the provider
* @return mixed User_username instance if the registration succeeded, false if it did not
*/
static function register($user, $username, $provider_name)
public static function register($user, $username, $provider_name)
{
$user_username = new User_username();
$user_username->user_id = $user->id;
@ -54,9 +71,9 @@ class User_username extends Managed_DataObject
$user_username->username = $username;
$user_username->created = common_sql_now();
if($user_username->insert()){
if ($user_username->insert()) {
return $user_username;
}else{
} else {
return false;
}
}

View File

@ -1,13 +1,23 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
*
* Some notes...
*
* Drupal docs don't list a bool type, but it might be nice to use rather than 'tinyint'
* Note however that we use bitfields and things as well in tinyints, and PG's
* "bool" type isn't 100% compatible with 0/1 checks. Just keeping tinyints. :)
*
* decimal <-> numeric
*
* MySQL 'timestamp' columns were formerly used for 'modified' files for their
@ -29,64 +39,67 @@
* double-check what we've been doing on postgres?
*/
$classes = array('Schema_version',
'Profile',
'Avatar',
'Sms_carrier',
'User',
'Subscription',
'Group_join_queue',
'Subscription_queue',
'Oauth_token_association',
'Notice',
'Notice_location',
'Notice_source',
'Notice_prefs',
'Reply',
'Consumer',
'Token',
'Nonce',
'Oauth_application',
'Oauth_application_user',
'Confirm_address',
'Remember_me',
'Queue_item',
'Notice_tag',
'Foreign_service',
'Foreign_user',
'Foreign_link',
'Foreign_subscription',
'Invitation',
'Profile_prefs',
'Profile_tag',
'Profile_list',
'Profile_tag_subscription',
'Profile_block',
'User_group',
'Related_group',
'Group_inbox',
'Group_member',
'File',
'File_redirection',
'File_thumbnail',
'File_to_post',
'Group_block',
'Group_alias',
'Session',
'Config',
'Profile_role',
'Location_namespace',
'Login_token',
'User_location_prefs',
'User_im_prefs',
'Conversation',
'Local_group',
'User_urlshortener_prefs',
'Old_school_prefs',
'User_username',
'Attention',
);
defined('GNUSOCIAL') || die();
$classes = [
'Schema_version',
'Profile',
'Avatar',
'Sms_carrier',
'User',
'User_group',
'Subscription',
'Group_join_queue',
'Subscription_queue',
'Consumer',
'Oauth_application',
'Oauth_token_association',
'Conversation',
'Notice',
'Notice_location',
'Notice_source',
'Notice_prefs',
'Reply',
'Token',
'Nonce',
'Oauth_application_user',
'Confirm_address',
'Remember_me',
'Queue_item',
'Notice_tag',
'Foreign_service',
'Foreign_user',
'Foreign_link',
'Foreign_subscription',
'Invitation',
'Profile_prefs',
'Profile_list',
'Profile_tag',
'Profile_tag_subscription',
'Profile_block',
'Related_group',
'Group_inbox',
'Group_member',
'File',
'File_redirection',
'File_thumbnail',
'File_to_post',
'Group_block',
'Group_alias',
'Session',
'Config',
'Profile_role',
'Location_namespace',
'Login_token',
'User_location_prefs',
'User_im_prefs',
'Local_group',
'User_urlshortener_prefs',
'Old_school_prefs',
'User_username',
'Attention'
];
foreach ($classes as $cls) {
$schema[strtolower($cls)] = call_user_func(array($cls, 'schemaDef'));
$schema[strtolower($cls)] = call_user_func([$cls, 'schemaDef']);
}

View File

@ -36,7 +36,7 @@ VALUES
(100088, 'Orange (Poland)', '%s@orange.pl', now()),
(100089, 'Personal (Argentina)', '%s@personal-net.com.ar', now()),
(100090, 'Plus GSM (Poland)', '%s@text.plusgsm.pl', now()),
(100091, 'President\'s Choice (Canada)', '%s@txt.bell.ca', now()),
(100091, 'President''s Choice (Canada)', '%s@txt.bell.ca', now()),
(100092, 'Qwest', '%s@qwestmp.com', now()),
(100093, 'Rogers (Canada)', '%s@pcs.rogers.com', now()),
(100094, 'Sasktel (Canada)', '%s@sms.sasktel.com', now()),

View File

@ -1787,12 +1787,34 @@ class DB_DataObject extends DB_DataObject_Overload
// note: we dont declare this to keep the print_r size down.
$_DB_DATAOBJECT['RESULTFIELDS'][$this->_DB_resultid] = array_flip(array_keys($array));
}
$dbtype = $_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5]->dsn['phptype'];
if ($dbtype === 'pgsql') {
if (($_DB_DATAOBJECT['CONFIG']['db_driver'] ?? 'DB') === 'DB') {
$tableInfo = $result->tableInfo();
} elseif ($result->db->supports('result_introspection')) { // MDB2
$result->db->loadModule('Reverse', null, true);
$tableInfo = $result->db->reverse->tableInfo($result);
}
}
$replace = array('.', ' ');
foreach ($array as $k => $v) {
foreach (array_keys($array) as $i => $k) {
// use strpos as str_replace is slow.
$kk = (strpos($k, '.') === false && strpos($k, ' ') === false) ?
$k : str_replace($replace, '_', $k);
if ($dbtype === 'pgsql') {
switch ($tableInfo[$i]['type']) {
case 'bool':
$array[$k] = str_replace(['t', 'f'], ['1', '0'], $array[$k]);
break;
case 'bytea':
$array[$k] = pg_unescape_bytea($array[$k]);
break;
}
}
if (!empty($_DB_DATAOBJECT['CONFIG']['debug'])) {
$this->debug("$kk = " . $array[$k], "fetchrow LINE", 3);
}
@ -2418,7 +2440,7 @@ class DB_DataObject extends DB_DataObject_Overload
case 'pgsql':
if (!$seq) {
$seq = $DB->getSequenceName(strtolower($this->tableName()));
$seq = $DB->getSequenceName(strtolower($this->tableName() . '_' . $key));
}
$db_driver = empty($options['db_driver']) ? 'DB' : $options['db_driver'];
$method = ($db_driver == 'DB') ? 'getOne' : 'queryOne';
@ -2949,12 +2971,34 @@ class DB_DataObject extends DB_DataObject_Overload
$this->raiseError("fetchrow: No results available", DB_DATAOBJECT_ERROR_NODATA);
return false;
}
$dbtype = $_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5]->dsn['phptype'];
if ($dbtype === 'pgsql') {
if (($_DB_DATAOBJECT['CONFIG']['db_driver'] ?? 'DB') === 'DB') {
$tableInfo = $result->tableInfo();
} elseif ($result->db->supports('result_introspection')) { // MDB2
$result->db->loadModule('Reverse', null, true);
$tableInfo = $result->db->reverse->tableInfo($result);
}
}
$replace = array('.', ' ');
foreach ($array as $k => $v) {
foreach (array_keys($array) as $i => $k) {
// use strpos as str_replace is slow.
$kk = (strpos($k, '.') === false && strpos($k, ' ') === false) ?
$k : str_replace($replace, '_', $k);
if ($dbtype === 'pgsql') {
switch ($tableInfo[$i]['type']) {
case 'bool':
$array[$k] = str_replace(['t', 'f'], ['1', '0'], $array[$k]);
break;
case 'bytea':
$array[$k] = pg_unescape_bytea($array[$k]);
break;
}
}
if (!empty($_DB_DATAOBJECT['CONFIG']['debug'])) {
$this->debug("$kk = " . $array[$k], "fetchrow LINE", 3);
}

View File

@ -1,36 +1,31 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* 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
* @package GNUsocial
* @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/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('GNUSOCIAL')) {
exit(1);
}
defined('GNUSOCIAL') || die();
/**
* Base class for all actions
@ -41,14 +36,11 @@ if (!defined('GNUSOCIAL')) {
* 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/
* @category Output
* @copyright 2008 StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*
* @see HTMLOutputter
* @see HTMLOutputter
*/
class Action extends HTMLOutputter // lawsuit
{
@ -1566,19 +1558,6 @@ class Action extends HTMLOutputter // lawsuit
// needs to be defined by the class
}
/**
* This is a cheap hack to avoid a bug in DB_DataObject
* where '' is non-type-aware compared to 0, which means it
* will always be true for values like false and 0 too...
*
* Upstream bug is::
* https://pear.php.net/bugs/bug.php?id=20291
*/
public function booleanintstring($key, $def = false)
{
return $this->boolean($key, $def) ? '1' : '0';
}
/**
* Integer value of an argument
*

View File

@ -17,9 +17,9 @@
/**
* Database schema for MariaDB
*
* @category Database
* @package GNUsocial
* @author Evan Prodromou <evan@status.net>
* @category Database
* @package GNUsocial
* @author Evan Prodromou <evan@status.net>
* @copyright 2019 Free Software Foundation, Inc http://www.fsf.org
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
@ -38,21 +38,20 @@ defined('GNUSOCIAL') || die();
*/
class MysqlSchema extends Schema
{
static $_single = null;
protected $conn = null;
public static $_single = null;
/**
* Main public entry point. Use this to get
* the singleton object.
*
* @param null $conn
* @param object|null $conn
* @param string|null dummy param
* @return Schema the (single) Schema object
*/
static function get($conn = null)
public static function get($conn = null, $_ = 'mysql')
{
if (empty(self::$_single)) {
self::$_single = new Schema($conn);
self::$_single = new Schema($conn, 'mysql');
}
return self::$_single;
}
@ -69,7 +68,6 @@ class MysqlSchema extends Schema
* @throws PEAR_Exception
* @throws SchemaTableMissingException
*/
public function getTableDef($table)
{
$def = [];
@ -82,7 +80,6 @@ class MysqlSchema extends Schema
}
foreach ($columns as $row) {
$name = $row['COLUMN_NAME'];
$field = [];
@ -109,14 +106,16 @@ class MysqlSchema extends Schema
$field['not null'] = true;
}
if ($row['COLUMN_DEFAULT'] !== null) {
// Hack for timestamp cols
if ($type == 'timestamp' && $row['COLUMN_DEFAULT'] == 'CURRENT_TIMESTAMP') {
// skip because timestamp is numerical, but it accepts datetime strings as well
// Hack for timestamp columns
if ($row['COLUMN_DEFAULT'] === 'current_timestamp()') {
// skip timestamp columns as they get a CURRENT_TIMESTAMP default implicitly
if ($type !== 'timestamp') {
$field['default'] = 'CURRENT_TIMESTAMP';
}
} elseif ($this->isNumericType($type)) {
$field['default'] = intval($row['COLUMN_DEFAULT']);
} else {
$field['default'] = $row['COLUMN_DEFAULT'];
if ($this->isNumericType($type)) {
$field['default'] = intval($field['default']);
}
}
}
if ($row['COLUMN_KEY'] !== null) {
@ -166,9 +165,9 @@ class MysqlSchema extends Schema
if ($name == 'PRIMARY') {
$type = 'primary key';
} else if ($row['Non_unique'] == 0) {
} elseif ($row['Non_unique'] == 0) {
$type = 'unique keys';
} else if ($row['Index_type'] == 'FULLTEXT') {
} elseif ($row['Index_type'] === 'FULLTEXT') {
$type = 'fulltext indexes';
} else {
$type = 'indexes';
@ -198,8 +197,7 @@ class MysqlSchema extends Schema
* @throws PEAR_Exception
* @throws SchemaTableMissingException
*/
function getTableProperties($table, $props)
public function getTableProperties($table, $props)
{
$data = $this->fetchMetaInfo($table, 'TABLES');
if ($data) {
@ -218,7 +216,7 @@ class MysqlSchema extends Schema
* @return array of arrays
* @throws PEAR_Exception
*/
function fetchMetaInfo($table, $infoTable, $orderBy = null)
public function fetchMetaInfo($table, $infoTable, $orderBy = null)
{
$query = "SELECT * FROM INFORMATION_SCHEMA.%s " .
"WHERE TABLE_SCHEMA='%s' AND TABLE_NAME='%s'";
@ -237,7 +235,7 @@ class MysqlSchema extends Schema
* @return array of arrays
* @throws PEAR_Exception
*/
function fetchIndexInfo($table)
public function fetchIndexInfo($table)
{
$query = "SHOW INDEX FROM `%s`";
$sql = sprintf($query, $table);
@ -253,7 +251,7 @@ class MysqlSchema extends Schema
* @param string $name
* @param array $def
*/
function appendCreateFulltextIndex(array &$statements, $table, $name, array $def)
public function appendCreateFulltextIndex(array &$statements, $table, $name, array $def)
{
$statements[] = "CREATE FULLTEXT INDEX $name ON $table " . $this->buildIndexList($def);
}
@ -266,13 +264,13 @@ class MysqlSchema extends Schema
* @return string;
*
*/
function endCreateTable($name, array $def)
public function endCreateTable($name, array $def)
{
$engine = $this->preferredEngine($def);
return ") ENGINE=$engine CHARACTER SET utf8mb4 COLLATE utf8mb4_bin";
}
function preferredEngine($def)
public function preferredEngine($def)
{
/* MyISAM is no longer required for fulltext indexes, fortunately
if (!empty($def['fulltext indexes'])) {
@ -288,7 +286,7 @@ class MysqlSchema extends Schema
* @param $columnName
* @return string
*/
function _uniqueKey($tableName, $columnName)
public function _uniqueKey($tableName, $columnName)
{
return $this->_key($tableName, $columnName);
}
@ -299,7 +297,7 @@ class MysqlSchema extends Schema
* @param $columnName
* @return string
*/
function _key($tableName, $columnName)
public function _key($tableName, $columnName)
{
return "{$tableName}_{$columnName}_idx";
}
@ -310,7 +308,7 @@ class MysqlSchema extends Schema
*
* @param array $phrase
*/
function appendAlterDropPrimary(array &$phrase)
public function appendAlterDropPrimary(array &$phrase, string $tableName)
{
$phrase[] = 'DROP PRIMARY KEY';
}
@ -322,7 +320,7 @@ class MysqlSchema extends Schema
* @param array $phrase
* @param string $keyName MySQL
*/
function appendAlterDropUnique(array &$phrase, $keyName)
public function appendAlterDropUnique(array &$phrase, $keyName)
{
$phrase[] = 'DROP INDEX ' . $keyName;
}
@ -335,7 +333,7 @@ class MysqlSchema extends Schema
* @param array $def
* @throws Exception
*/
function appendAlterExtras(array &$phrase, $tableName, array $def)
public function appendAlterExtras(array &$phrase, $tableName, array $def)
{
// Check for table properties: make sure we're using a sane
// engine type and charset/collation.
@ -370,15 +368,15 @@ class MysqlSchema extends Schema
* Appropriate for use in CREATE TABLE or
* ALTER TABLE statements.
*
* @param string $name column name to create
* @param array $cd column to create
*
* @return string correct SQL for that column
*/
function columnSql(array $cd)
public function columnSql(string $name, array $cd)
{
$line = [];
$line[] = parent::columnSql($cd);
$line[] = parent::columnSql($name, $cd);
// This'll have been added from our transform of 'serial' type
if (!empty($cd['auto_increment'])) {
@ -393,12 +391,12 @@ class MysqlSchema extends Schema
return implode(' ', $line);
}
function mapType($column)
public function mapType($column)
{
$map = [
'serial' => 'int',
'integer' => 'int',
'numeric' => 'decimal'
'bool' => 'tinyint',
'numeric' => 'decimal',
];
$type = $column['type'];
@ -411,7 +409,9 @@ class MysqlSchema extends Schema
if ($type == 'int' &&
in_array($size, ['tiny', 'small', 'medium', 'big'])) {
$type = $size . $type;
} else if (in_array($type, ['blob', 'text']) &&
} elseif ($type == 'float' && $size == 'big') {
$type = 'double';
} elseif (in_array($type, ['blob', 'text']) &&
in_array($size, ['tiny', 'medium', 'long'])) {
$type = $size . $type;
}
@ -420,13 +420,15 @@ class MysqlSchema extends Schema
return $type;
}
function typeAndSize($column)
public function typeAndSize(string $name, array $column)
{
if ($column['type'] == 'enum') {
$vals = array_map([$this, 'quote'], $column['enum']);
if ($column['type'] === 'enum') {
foreach ($column['enum'] as &$val) {
$vals[] = "'" . $val . "'";
}
return 'enum(' . implode(',', $vals) . ')';
} else if ($this->_isString($column)) {
$col = parent::typeAndSize($column);
} elseif ($this->_isString($column)) {
$col = parent::typeAndSize($name, $column);
if (!empty($column['charset'])) {
$col .= ' CHARSET ' . $column['charset'];
}
@ -435,7 +437,7 @@ class MysqlSchema extends Schema
}
return $col;
} else {
return parent::typeAndSize($column);
return parent::typeAndSize($name, $column);
}
}
@ -449,7 +451,7 @@ class MysqlSchema extends Schema
* @param array $tableDef
* @return array
*/
function filterDef(array $tableDef)
public function filterDef(array $tableDef)
{
$version = $this->conn->getVersion();
foreach ($tableDef['fields'] as $name => &$col) {

View File

@ -17,11 +17,11 @@
/**
* Database schema for PostgreSQL
*
* @category Database
* @package GNUsocial
* @author Evan Prodromou <evan@status.net>
* @author Brenda Wallace <shiny@cpan.org>
* @author Brion Vibber <brion@status.net>
* @category Database
* @package GNUsocial
* @author Evan Prodromou <evan@status.net>
* @author Brenda Wallace <shiny@cpan.org>
* @author Brion Vibber <brion@status.net>
* @copyright 2019 Free Software Foundation, Inc http://www.fsf.org
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
@ -40,6 +40,23 @@ defined('GNUSOCIAL') || die();
*/
class PgsqlSchema extends Schema
{
public static $_single = null;
/**
* Main public entry point. Use this to get
* the singleton object.
*
* @param object|null $conn
* @param string|null dummy param
* @return Schema the (single) Schema object
*/
public static function get($conn = null, $_ = 'pgsql')
{
if (empty(self::$_single)) {
self::$_single = new Schema($conn, 'pgsql');
}
return self::$_single;
}
/**
* Returns a table definition array for the table
@ -52,7 +69,6 @@ class PgsqlSchema extends Schema
* @return array tabledef for that table.
* @throws SchemaTableMissingException
*/
public function getTableDef($table)
{
$def = [];
@ -68,14 +84,13 @@ class PgsqlSchema extends Schema
$orderedFields = [];
foreach ($columns as $row) {
$name = $row['column_name'];
$orderedFields[$row['ordinal_position']] = $name;
$field = [];
$field['type'] = $type = $row['udt_name'];
if ($type == 'char' || $type == 'varchar') {
if (in_array($type, ['char', 'bpchar', 'varchar'])) {
if ($row['character_maximum_length'] !== null) {
$field['length'] = intval($row['character_maximum_length']);
}
@ -106,7 +121,8 @@ class PgsqlSchema extends Schema
// 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);
$indexInfo = $this->fetchIndexInfo($table);
foreach ($indexInfo as $row) {
$keyName = $row['key_name'];
@ -146,8 +162,8 @@ class PgsqlSchema extends Schema
// 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);
} elseif (preg_match("/^{$table}_(.*)_fkey$/", $keyName, $matches)) {
$fkey = $this->fetchForeignKeyInfo($table, $keyName);
$colMap = array_combine($cols, $fkey['col_names']);
$def['foreign keys'][$keyName] = [$fkey['table_name'], $colMap];
} else {
@ -166,7 +182,7 @@ class PgsqlSchema extends Schema
* @return array of arrays
* @throws PEAR_Exception
*/
function fetchMetaInfo($table, $infoTable, $orderBy = null)
public function fetchMetaInfo($table, $infoTable, $orderBy = null)
{
$query = "SELECT * FROM information_schema.%s " .
"WHERE table_name='%s'";
@ -183,47 +199,42 @@ class PgsqlSchema extends Schema
* @return array of arrays
* @throws PEAR_Exception
*/
function getIndexInfo($table)
public function fetchIndexInfo(string $table): array
{
$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\' ' .
$query = 'SELECT indexname AS key_name, indexdef AS key_def, pg_index.* ' .
'FROM pg_index INNER JOIN pg_indexes ON pg_index.indexrelid = CAST(pg_indexes.indexname AS regclass) ' .
'WHERE tablename = \'%s\' AND indisprimary = FALSE AND indisunique = FALSE ' .
'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 string $table
* @param $constraint_name
* @return array array of rows with keys: fkey_name, table_name, table_id, col_names (array of strings)
* @param string $constraint_name
* @return array array of rows with keys: table_name, col_names (array of strings)
* @throws PEAR_Exception
*/
function getForeignKeyInfo($table, $constraint_name)
public function fetchForeignKeyInfo(string $table, string $constraint_name): array
{
// 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, ' .
'(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 ' .
'(SELECT indkey FROM pg_index WHERE indexrelid = conindid) AS col_indices ' .
'FROM pg_constraint ' .
'WHERE conrelid=(SELECT oid FROM pg_class WHERE relname=\'%s\') ' .
'AND conname=\'%s\' ' .
'AND contype=\'f\'';
'WHERE conrelid = CAST(\'%s\' AS regclass) 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);
throw new Exception('Could not find foreign key ' . $constraint_name . ' on table ' . $table);
}
$row = $data[0];
return [
'table_name' => $row['table_name'],
'col_names' => $this->getTableColumnNames($row['table_id'], $row['col_indexes'])
'col_names' => $this->getTableColumnNames($row['table_id'], $row['col_indices'])
];
}
@ -234,7 +245,7 @@ class PgsqlSchema extends Schema
* @return array of strings
* @throws PEAR_Exception
*/
function getTableColumnNames($table_id, $col_indexes)
public function getTableColumnNames($table_id, $col_indexes)
{
$indexes = array_map('intval', explode(' ', $col_indexes));
$query = 'SELECT attnum AS col_index, attname AS col_name ' .
@ -255,23 +266,6 @@ class PgsqlSchema extends Schema
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 = [
'datetime' => 'timestamp',
];
if (!empty($map[$type])) {
return $map[$type];
}
return $type;
}
/**
* Return the proper SQL for creating or
* altering a column.
@ -279,15 +273,15 @@ class PgsqlSchema extends Schema
* Appropriate for use in CREATE TABLE or
* ALTER TABLE statements.
*
* @param string $name column name to create
* @param array $cd column to create
*
* @return string correct SQL for that column
*/
function columnSql(array $cd)
public function columnSql(string $name, array $cd)
{
$line = [];
$line[] = parent::columnSql($cd);
$line[] = parent::columnSql($name, $cd);
/*
if ($table['foreign keys'][$name]) {
@ -299,6 +293,16 @@ class PgsqlSchema extends Schema
}
*/
// This'll have been added from our transform of 'serial' type
if (!empty($cd['auto_increment'])) {
$line[] = 'GENERATED BY DEFAULT AS IDENTITY';
} elseif (!empty($cd['enum'])) {
foreach ($cd['enum'] as &$val) {
$vals[] = "'" . $val . "'";
}
$line[] = 'CHECK (' . $name . ' IN (' . implode(',', $vals) . '))';
}
return implode(' ', $line);
}
@ -311,29 +315,35 @@ class PgsqlSchema extends Schema
* @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)
public function appendAlterModifyColumn(array &$phrase, $columnName, array $old, array $cd)
{
$prefix = 'ALTER COLUMN ' . $this->quoteIdentifier($columnName) . ' ';
$oldType = $this->mapType($old);
$newType = $this->mapType($cd);
$oldType = $this->typeAndSize($columnName, $old);
$newType = $this->typeAndSize($columnName, $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'])) {
} elseif (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'])) {
} elseif (!isset($old['default']) && isset($cd['default'])) {
$phrase[] = $prefix . 'SET DEFAULT ' . $this->quoteDefaultValue($cd);
}
}
public function appendAlterDropPrimary(array &$phrase, string $tableName)
{
// name hack -- is this reliable?
$phrase[] = 'DROP CONSTRAINT ' . $this->quoteIdentifier($tableName . '_pkey');
}
/**
* Append an SQL statement to drop an index from a table.
* Note that in PostgreSQL, index names are DB-unique.
@ -342,29 +352,19 @@ class PgsqlSchema extends Schema
* @param string $table
* @param string $name
*/
function appendDropIndex(array &$statements, $table, $name)
public 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)
public function mapType($column)
{
$map = [
'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',
'integer' => 'int',
'char' => 'bpchar',
'datetime' => 'timestamp',
'blob' => 'bytea'
'blob' => 'bytea',
'enum' => 'text',
];
$type = $column['type'];
@ -372,32 +372,22 @@ class PgsqlSchema extends Schema
$type = $map[$type];
}
if ($type == 'int') {
if (!empty($column['size'])) {
$size = $column['size'];
if ($size == 'small') {
return 'int2';
} else if ($size == 'big') {
return 'int8';
}
$size = $column['size'] ?? null;
if ($type === 'int') {
if (in_array($size, ['tiny', 'small'])) {
$type = 'int2';
} elseif ($size === 'big') {
$type = 'int8';
} else {
$type = 'int4';
}
return 'int4';
} elseif ($type === 'float') {
$type = ($size !== 'big') ? 'float4' : 'float8';
}
return $type;
}
// @fixme need name... :P
function typeAndSize($column)
{
if ($column['type'] == 'enum') {
$vals = array_map([$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.
@ -408,23 +398,39 @@ class PgsqlSchema extends Schema
* @param array $tableDef
* @return array
*/
function filterDef(array $tableDef)
public 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']);
}
switch ($col['type']) {
case 'serial':
$col['type'] = 'int';
$col['auto_increment'] = true;
break;
case 'datetime':
// Replace archaic MySQL-specific zero-dates with NULL
if (($col['default'] ?? null) === '0000-00-00 00:00:00') {
$col['default'] = null;
$col['not null'] = false;
}
break;
case 'timestamp':
// In MariaDB: If the column does not permit NULL values,
// assigning NULL (or not referencing the column at all
// when inserting) will set the column to CURRENT_TIMESTAMP
// FIXME: ON UPDATE CURRENT_TIMESTAMP
if ($col['not null'] && !isset($col['default'])) {
$col['default'] = 'CURRENT_TIMESTAMP';
}
break;
}
*/
$col['type'] = $this->mapType($col);
unset($col['size']);
}
if (!empty($tableDef['primary key'])) {
$tableDef['primary key'] = $this->filterKeyDef($tableDef['primary key']);
}
@ -443,7 +449,7 @@ class PgsqlSchema extends Schema
* @param array $def
* @return array
*/
function filterKeyDef(array $def)
public function filterKeyDef(array $def)
{
// PostgreSQL doesn't like prefix lengths specified on keys...?
foreach ($def as $i => $item) {

View File

@ -17,10 +17,10 @@
/**
* Database schema
*
* @category Database
* @package GNUsocial
* @author Evan Prodromou <evan@status.net>
* @author Brion Vibber <brion@status.net>
* @category Database
* @package GNUsocial
* @author Evan Prodromou <evan@status.net>
* @author Brion Vibber <brion@status.net>
* @copyright 2019 Free Software Foundation, Inc http://www.fsf.org
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
@ -39,14 +39,13 @@ defined('GNUSOCIAL') || die();
*/
class Schema
{
static $_static = null;
public static $_static = null;
protected $conn = null;
/**
* Constructor. Only run once for singleton object.
* @param null $conn
*/
protected function __construct($conn = null)
{
if (is_null($conn)) {
@ -64,11 +63,11 @@ class Schema
* Main public entry point. Use this to get
* the schema object.
*
* @param null $conn
* @param object|null $conn
* @param string|null Force a database type (necessary for installation purposes in which we don't have a config.php)
* @return Schema the Schema object for the connection
*/
static function get($conn = null)
public static function get($conn = null, $dbtype = null)
{
if (is_null($conn)) {
$key = 'default';
@ -76,9 +75,11 @@ class Schema
$key = md5(serialize($conn->dsn));
}
$type = common_config('db', 'type');
if (is_null($dbtype)) {
$dbtype = common_config('db', 'type');
}
if (empty(self::$_static[$key])) {
$schemaClass = ucfirst($type) . 'Schema';
$schemaClass = ucfirst($dbtype) . 'Schema';
self::$_static[$key] = new $schemaClass($conn);
}
return self::$_static[$key];
@ -95,7 +96,6 @@ class Schema
* @return ColumnDef definition of the column or null
* if not found.
*/
public function getColumnDef($table, $column)
{
$td = $this->getTableDef($table);
@ -120,7 +120,6 @@ class Schema
* @return bool success flag
* @throws PEAR_Exception
*/
public function createTable($tableName, $def)
{
$statements = $this->buildCreateTable($tableName, $def);
@ -194,7 +193,7 @@ class Schema
* @param array $def table definition
* @return string
*/
function startCreateTable($name, array $def)
public function startCreateTable($name, array $def)
{
return 'CREATE TABLE ' . $this->quoteIdentifier($name) . ' (';
}
@ -206,7 +205,7 @@ class Schema
* @param array $def table definition
* @return string
*/
function endCreateTable($name, array $def)
public function endCreateTable($name, array $def)
{
return ')';
}
@ -218,9 +217,9 @@ class Schema
* @param string $name
* @param array $def
*/
function appendColumnDef(array &$sql, $name, array $def)
public function appendColumnDef(array &$sql, string $name, array $def)
{
$sql[] = "$name " . $this->columnSql($def);
$sql[] = $name . ' ' . $this->columnSql($name, $def);
}
/**
@ -230,7 +229,7 @@ class Schema
* @param array $sql
* @param array $def
*/
function appendPrimaryKeyDef(array &$sql, array $def)
public function appendPrimaryKeyDef(array &$sql, array $def)
{
$sql[] = "PRIMARY KEY " . $this->buildIndexList($def);
}
@ -243,7 +242,7 @@ class Schema
* @param string $name
* @param array $def
*/
function appendUniqueKeyDef(array &$sql, $name, array $def)
public function appendUniqueKeyDef(array &$sql, $name, array $def)
{
$sql[] = "CONSTRAINT $name UNIQUE " . $this->buildIndexList($def);
}
@ -257,7 +256,7 @@ class Schema
* @param array $def
* @throws Exception
*/
function appendForeignKeyDef(array &$sql, $name, array $def)
public function appendForeignKeyDef(array &$sql, $name, array $def)
{
if (count($def) != 2) {
throw new Exception("Invalid foreign key def for $name: " . var_export($def, true));
@ -265,11 +264,11 @@ class Schema
list($refTable, $map) = $def;
$srcCols = array_keys($map);
$refCols = array_values($map);
$sql[] = "CONSTRAINT $name FOREIGN KEY " .
$sql[] = 'CONSTRAINT ' . $this->quoteIdentifier($name) . ' FOREIGN KEY ' .
$this->buildIndexList($srcCols) .
" REFERENCES " .
' REFERENCES ' .
$this->quoteIdentifier($refTable) .
" " .
' ' .
$this->buildIndexList($refCols);
}
@ -282,9 +281,10 @@ class Schema
* @param string $name
* @param array $def
*/
function appendCreateIndex(array &$statements, $table, $name, array $def)
public function appendCreateIndex(array &$statements, $table, $name, array $def)
{
$statements[] = "CREATE INDEX $name ON $table " . $this->buildIndexList($def);
$statements[] = 'CREATE INDEX ' . $name . ' ON ' .
$this->quoteIdentifier($table) . ' ' . $this->buildIndexList($def);
}
/**
@ -297,7 +297,7 @@ class Schema
* @param array $def
* @throws Exception
*/
function appendCreateFulltextIndex(array &$statements, $table, $name, array $def)
public function appendCreateFulltextIndex(array &$statements, $table, $name, array $def)
{
throw new Exception("Fulltext index not supported in this database");
}
@ -309,18 +309,18 @@ class Schema
* @param string $table
* @param string $name
*/
function appendDropIndex(array &$statements, $table, $name)
public function appendDropIndex(array &$statements, $table, $name)
{
$statements[] = "DROP INDEX $name ON " . $this->quoteIdentifier($table);
}
function buildIndexList(array $def)
public function buildIndexList(array $def)
{
// @fixme
return '(' . implode(',', array_map([$this, 'buildIndexItem'], $def)) . ')';
}
function buildIndexItem($def)
public function buildIndexItem($def)
{
if (is_array($def)) {
list($name, $size) = $def;
@ -339,12 +339,11 @@ class Schema
* @return bool success flag
* @throws PEAR_Exception
*/
public function dropTable($name)
{
global $_PEAR;
$res = $this->conn->query("DROP TABLE $name");
$res = $this->conn->query('DROP TABLE ' . $this->quoteIdentifier($name));
if ($_PEAR->isError($res)) {
PEAR_ErrorToPEAR_Exception($res);
@ -369,11 +368,12 @@ class Schema
* @return bool success flag
* @throws PEAR_Exception
*/
public function createIndex($table, $columnNames, $name = null)
{
global $_PEAR;
$qry = [];
if (!is_array($columnNames)) {
$columnNames = [$columnNames];
}
@ -382,9 +382,9 @@ class Schema
$name = "{$table}_" . implode("_", $columnNames) . "_idx";
}
$res = $this->conn->query("ALTER TABLE $table " .
"ADD INDEX $name (" .
implode(",", $columnNames) . ")");
$this->appendCreateIndex($qry, $table, $name, $columnNames);
$res = $this->conn->query(implode('; ', $qry));
if ($_PEAR->isError($res)) {
PEAR_ErrorToPEAR_Exception($res);
@ -402,12 +402,14 @@ class Schema
* @return bool success flag
* @throws PEAR_Exception
*/
public function dropIndex($table, $name)
{
global $_PEAR;
$res = $this->conn->query("ALTER TABLE $table DROP INDEX $name");
$res = $this->conn->query(
'ALTER TABLE ' . $this->quoteIdentifier($table) .
' DROP INDEX ' . $name
);
if ($_PEAR->isError($res)) {
PEAR_ErrorToPEAR_Exception($res);
@ -426,12 +428,12 @@ class Schema
* @return bool success flag
* @throws PEAR_Exception
*/
public function addColumn($table, $columndef)
{
global $_PEAR;
$sql = "ALTER TABLE $table ADD COLUMN " . $this->_columnSql($columndef);
$sql = 'ALTER TABLE ' . $this->quoteIdentifier($table) .
' ADD COLUMN ' . $this->columnSql($name, $columndef);
$res = $this->conn->query($sql);
@ -453,13 +455,12 @@ class Schema
* @return bool success flag
* @throws PEAR_Exception
*/
public function modifyColumn($table, $columndef)
{
global $_PEAR;
$sql = "ALTER TABLE $table MODIFY COLUMN " .
$this->_columnSql($columndef);
$sql = 'ALTER TABLE ' . $this->quoteIdentifier($table) .
' MODIFY COLUMN ' . $this->columnSql($name, $columndef);
$res = $this->conn->query($sql);
@ -481,12 +482,12 @@ class Schema
* @return bool success flag
* @throws PEAR_Exception
*/
public function dropColumn($table, $columnName)
{
global $_PEAR;
$sql = "ALTER TABLE $table DROP COLUMN $columnName";
$sql = 'ALTER TABLE ' . $this->quoteIdentifier($table) .
' DROP COLUMN ' . $columnName;
$res = $this->conn->query($sql);
@ -511,7 +512,6 @@ class Schema
* @return bool success flag
* @throws PEAR_Exception
*/
public function ensureTable($tableName, $def)
{
$statements = $this->buildEnsureTable($tableName, $def);
@ -527,7 +527,7 @@ class Schema
* @return bool success flag
* @throws PEAR_Exception
*/
function runSqlSet(array $statements)
public function runSqlSet(array $statements)
{
global $_PEAR;
@ -561,8 +561,7 @@ class Schema
* @return array of SQL statements
* @throws Exception
*/
function buildEnsureTable($tableName, array $def)
public function buildEnsureTable($tableName, array $def)
{
try {
$old = $this->getTableDef($tableName);
@ -606,18 +605,24 @@ class Schema
}
if (isset($old['primary key']) && (!isset($def['primary key']) || $def['primary key'] != $old['primary key'])) {
$this->appendAlterDropPrimary($phrase);
$this->appendAlterDropPrimary($phrase, $tableName);
}
foreach ($fields['add'] as $columnName) {
$this->appendAlterAddColumn($phrase, $columnName,
$def['fields'][$columnName]);
$this->appendAlterAddColumn(
$phrase,
$columnName,
$def['fields'][$columnName]
);
}
foreach ($fields['mod'] as $columnName) {
$this->appendAlterModifyColumn($phrase, $columnName,
$this->appendAlterModifyColumn(
$phrase,
$columnName,
$old['fields'][$columnName],
$def['fields'][$columnName]);
$def['fields'][$columnName]
);
}
foreach ($fields['del'] as $columnName) {
@ -639,7 +644,8 @@ class Schema
$this->appendAlterExtras($phrase, $tableName, $def);
if (count($phrase) > 0) {
$sql = 'ALTER TABLE ' . $tableName . ' ' . implode(",\n", $phrase);
$sql = 'ALTER TABLE ' . $this->quoteIdentifier($tableName) .
' ' . implode(",\n", $phrase);
$statements[] = $sql;
}
@ -656,7 +662,7 @@ class Schema
return $statements;
}
function diffArrays($oldDef, $newDef, $section, $compareCallback = null)
public function diffArrays($oldDef, $newDef, $section, $compareCallback = null)
{
$old = isset($oldDef[$section]) ? $oldDef[$section] : [];
$new = isset($newDef[$section]) ? $newDef[$section] : [];
@ -701,12 +707,12 @@ class Schema
* @param string $columnName
* @param array $cd
*/
function appendAlterAddColumn(array &$phrase, $columnName, array $cd)
public function appendAlterAddColumn(array &$phrase, string $columnName, array $cd)
{
$phrase[] = 'ADD COLUMN ' .
$this->quoteIdentifier($columnName) .
' ' .
$this->columnSql($cd);
$this->columnSql($columnName, $cd);
}
/**
@ -718,12 +724,12 @@ class Schema
* @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)
public function appendAlterModifyColumn(array &$phrase, string $columnName, array $old, array $cd)
{
$phrase[] = 'MODIFY COLUMN ' .
$this->quoteIdentifier($columnName) .
' ' .
$this->columnSql($cd);
$this->columnSql($columnName, $cd);
}
/**
@ -733,12 +739,12 @@ class Schema
* @param array $phrase
* @param string $columnName
*/
function appendAlterDropColumn(array &$phrase, $columnName)
public function appendAlterDropColumn(array &$phrase, $columnName)
{
$phrase[] = 'DROP COLUMN ' . $this->quoteIdentifier($columnName);
}
function appendAlterAddUnique(array &$phrase, $keyName, array $def)
public function appendAlterAddUnique(array &$phrase, $keyName, array $def)
{
$sql = [];
$sql[] = 'ADD';
@ -746,7 +752,7 @@ class Schema
$phrase[] = implode(' ', $sql);
}
function appendAlterAddForeign(array &$phrase, $keyName, array $def)
public function appendAlterAddForeign(array &$phrase, $keyName, array $def)
{
$sql = [];
$sql[] = 'ADD';
@ -754,7 +760,7 @@ class Schema
$phrase[] = implode(' ', $sql);
}
function appendAlterAddPrimary(array &$phrase, array $def)
public function appendAlterAddPrimary(array &$phrase, array $def)
{
$sql = [];
$sql[] = 'ADD';
@ -762,22 +768,22 @@ class Schema
$phrase[] = implode(' ', $sql);
}
function appendAlterDropPrimary(array &$phrase)
public function appendAlterDropPrimary(array &$phrase, string $tableName)
{
$phrase[] = 'DROP CONSTRAINT PRIMARY KEY';
}
function appendAlterDropUnique(array &$phrase, $keyName)
public function appendAlterDropUnique(array &$phrase, $keyName)
{
$phrase[] = 'DROP CONSTRAINT ' . $keyName;
}
function appendAlterDropForeign(array &$phrase, $keyName)
public function appendAlterDropForeign(array &$phrase, $keyName)
{
$phrase[] = 'DROP FOREIGN KEY ' . $keyName;
}
function appendAlterExtras(array &$phrase, $tableName, array $def)
public function appendAlterExtras(array &$phrase, $tableName, array $def)
{
// no-op
}
@ -788,21 +794,21 @@ class Schema
* @param string $name
* @return string
*/
function quoteIdentifier($name)
public function quoteIdentifier($name)
{
return $name;
return $this->conn->quoteIdentifier($name);
}
function quoteDefaultValue($cd)
public function quoteDefaultValue($cd)
{
if (($cd['type'] == 'datetime' || $cd['type'] == 'timestamp') && $cd['default'] == 'CURRENT_TIMESTAMP') {
if (in_array($cd['type'], ['datetime', 'timestamp']) && $cd['default'] === 'CURRENT_TIMESTAMP') {
return $cd['default'];
} else {
return $this->quoteValue($cd['default']);
}
}
function quoteValue($val)
public function quoteValue($val)
{
return $this->conn->quoteSmart($val);
}
@ -816,7 +822,7 @@ class Schema
* @param array $b
* @return bool
*/
function columnsEqual(array $a, array $b)
public function columnsEqual(array $a, array $b)
{
return !array_diff_assoc($a, $b) && !array_diff_assoc($b, $a);
}
@ -829,7 +835,6 @@ class Schema
*
* @return array strings for name values
*/
protected function _names($cds)
{
$names = [];
@ -850,7 +855,6 @@ class Schema
*
* @return ColumnDef matching item or null if no match.
*/
protected function _byName($cds, $name)
{
foreach ($cds as $cd) {
@ -869,20 +873,20 @@ class Schema
* Appropriate for use in CREATE TABLE or
* ALTER TABLE statements.
*
* @param string $name column name to create
* @param array $cd column to create
*
* @return string correct SQL for that column
*/
function columnSql(array $cd)
public function columnSql(string $name, array $cd)
{
$line = [];
$line[] = $this->typeAndSize($cd);
$line[] = $this->typeAndSize($name, $cd);
if (isset($cd['default'])) {
$line[] = 'default';
$line[] = $this->quoteDefaultValue($cd);
} else if (!empty($cd['not null'])) {
} elseif (!empty($cd['not null'])) {
// Can't have both not null AND default!
$line[] = 'not null';
}
@ -895,14 +899,14 @@ class Schema
* @param string $column canonical type name in defs
* @return string native DB type name
*/
function mapType($column)
public function mapType($column)
{
return $column;
}
function typeAndSize($column)
public function typeAndSize(string $name, array $column)
{
//$type = $this->mapType($column);
//$type = $this->mapType($column)['type'];
$type = $column['type'];
if (isset($column['size'])) {
$type = $column['size'] . $type;
@ -914,7 +918,7 @@ class Schema
if (isset($column['scale'])) {
$lengths[] = $column['scale'];
}
} else if (isset($column['length'])) {
} elseif (isset($column['length'])) {
$lengths[] = $column['length'];
}
@ -977,12 +981,12 @@ class Schema
$table['primary key'] = [];
}
$table['primary key'][] = $cd->name;
} else if ($cd->key == 'MUL') {
} elseif ($cd->key === 'MUL') {
// Individual multiple-value indexes are only per-column
// using the old ColumnDef syntax.
$idx = "{$tableName}_{$cd->name}_idx";
$table['indexes'][$idx] = [$cd->name];
} else if ($cd->key == 'UNI') {
} elseif ($cd->key === 'UNI') {
// Individual unique-value indexes are only per-column
// using the old ColumnDef syntax.
$idx = "{$tableName}_{$cd->name}_idx";
@ -1003,7 +1007,7 @@ class Schema
* @param array $tableDef
* @return array
*/
function filterDef(array $tableDef)
public function filterDef(array $tableDef)
{
return $tableDef;
}
@ -1019,7 +1023,7 @@ class Schema
*
* @throws Exception on wildly invalid input
*/
function validateDef($tableName, array $def)
public function validateDef($tableName, array $def)
{
if (isset($def[0]) && $def[0] instanceof ColumnDef) {
$def = $this->oldToNew($tableName, $def);
@ -1033,7 +1037,7 @@ class Schema
return $def;
}
function isNumericType($type)
public function isNumericType($type)
{
$type = strtolower($type);
$known = ['int', 'serial', 'numeric'];
@ -1074,20 +1078,21 @@ class Schema
$this->getTableDef($new_name);
// New table exists, can't work
throw new ServerException("Both table {$old_name} and {$new_name} exist. You're on your own.");
} catch(SchemaTableMissingException $e) {
} catch (SchemaTableMissingException $e) {
// New table doesn't exist, carry on
}
} catch(SchemaTableMissingException $e) {
} catch (SchemaTableMissingException $e) {
// Already renamed, or no previous table, so we're done
return true;
}
return $this->runSqlSet(["ALTER TABLE {$old_name} RENAME TO {$new_name};"]);
return $this->runSqlSet([
'ALTER TABLE ' . $this->quoteIdentifier($old_name) .
' RENAME TO ' . $this->quoteIdentifier($new_name) . ';',
]);
}
}
class SchemaTableMissingException extends Exception
{
// no-op
}

View File

@ -1,77 +1,60 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* StatusNet, the distributed open-source microblogging tool
*
* Groups with the most members 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
* @package GNUsocial
* @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/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
defined('GNUSOCIAL') || die();
/**
* Groups with the most members 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/
* @copyright 2019 Free Software Foundation, Inc http://www.fsf.org
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
class GroupsByMembersSection extends GroupSection
{
function getGroups()
public function getGroups()
{
$qry = 'SELECT user_group.*, count(*) as value ' .
'FROM user_group JOIN group_member '.
'ON user_group.id = group_member.group_id ' .
'GROUP BY user_group.id,user_group.nickname,user_group.fullname,user_group.homepage,user_group.description,user_group.location,user_group.original_logo,user_group.homepage_logo,user_group.stream_logo,user_group.mini_logo,user_group.created,user_group.modified ' .
'ORDER BY value DESC ';
$limit = GROUPS_PER_SECTION;
$offset = 0;
if (common_config('db','type') == 'pgsql') {
$qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
} else {
$qry .= ' LIMIT ' . $offset . ', ' . $limit;
}
$qry = 'SELECT user_group.*, COUNT(*) AS value ' .
'FROM user_group INNER JOIN group_member '.
'ON user_group.id = group_member.group_id ' .
'GROUP BY user_group.id, user_group.nickname, user_group.fullname, user_group.homepage, user_group.description, user_group.location, user_group.original_logo, user_group.homepage_logo, user_group.stream_logo, user_group.mini_logo, user_group.created, user_group.modified ' .
'ORDER BY value DESC LIMIT ' . $limit;
$group = Memcached_DataObject::cachedQuery('User_group',
$qry,
3600);
$group = Memcached_DataObject::cachedQuery('User_group', $qry, 3600);
return $group;
}
function title()
public function title()
{
// TRANS: Title for groups with the most members section.
return _('Popular groups');
}
function divId()
public function divId()
{
return 'top_groups_by_member';
}

View File

@ -44,20 +44,13 @@ class GroupsByPostsSection extends GroupSection
{
function getGroups()
{
$limit = GROUPS_PER_SECTION;
$qry = 'SELECT user_group.*, count(*) as value ' .
'FROM user_group JOIN group_inbox '.
'ON user_group.id = group_inbox.group_id ' .
'GROUP BY user_group.id,user_group.nickname,user_group.fullname,user_group.homepage,user_group.description,user_group.location,user_group.original_logo,user_group.homepage_logo,user_group.stream_logo,user_group.mini_logo,user_group.created,user_group.modified ' .
'ORDER BY value DESC ';
$limit = GROUPS_PER_SECTION;
$offset = 0;
if (common_config('db','type') == 'pgsql') {
$qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
} else {
$qry .= ' LIMIT ' . $offset . ', ' . $limit;
}
'ORDER BY value DESC LIMIT ' . $limit;
$group = Memcached_DataObject::cachedQuery('User_group',
$qry,

View File

@ -1,51 +1,40 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2011, StatusNet, Inc.
*
* Stream of notices for a profile's "all" feed
*
* 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 NoticeStream
* @package StatusNet
* @package GNUsocial
* @author Evan Prodromou <evan@status.net>
* @author Mikael Nordfeldth <mmn@hethane.se>
* @author Alexei Sorokin <sor.alexei@meowr.ru>
* @author Stephane Berube <chimo@chromic.org>
* @copyright 2011 StatusNet, Inc.
* @copyright 2014 Free Software Foundation, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
* @copyright 2014 Free Software Foundation, Inc http://www.fsf.org
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('GNUSOCIAL')) {
exit(1);
}
defined('GNUSOCIAL') || die();
/**
* Stream of notices for a profile's "all" feed
*
* @category General
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @author Mikael Nordfeldth <mmn@hethane.se>
* @author Alexei Sorokin <sor.alexei@meowr.ru>
* @author chimo <chimo@chromic.org>
* @copyright 2011 StatusNet, Inc.
* @copyright 2014 Free Software Foundation, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
* @copyright 2014 Free Software Foundation, Inc http://www.fsf.org
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
class InboxNoticeStream extends ScopingNoticeStream
{
@ -65,13 +54,9 @@ class InboxNoticeStream extends ScopingNoticeStream
* Raw stream of notices for the target's inbox
*
* @category General
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @author Mikael Nordfeldth <mmn@hethane.se>
* @author Alexei Sorokin <sor.alexei@meowr.ru>
* @copyright 2011 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
* @copyright 2014 Free Software Foundation, Inc http://www.fsf.org
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
class RawInboxNoticeStream extends FullNoticeStream
{
@ -104,33 +89,39 @@ class RawInboxNoticeStream extends FullNoticeStream
$notice = new Notice();
$notice->selectAdd();
$notice->selectAdd('id');
$notice->whereAdd(sprintf('notice.created > "%s"', $notice->escape($this->target->created)));
// Reply:: is a table of mentions
// Subscription:: is a table of subscriptions (every user is subscribed to themselves)
// Sort in descending order as id will give us even really old posts,
// which were recently imported. For example, if a remote instance had
// problems and just managed to post here.
$notice->whereAdd(
sprintf('id IN (SELECT DISTINCT id FROM (' .
'(SELECT id FROM notice WHERE profile_id IN (SELECT subscribed FROM subscription WHERE subscriber = %1$d)) UNION ' .
'(SELECT notice_id AS id FROM reply WHERE profile_id = %1$d) UNION ' .
'(SELECT notice_id AS id FROM attention WHERE profile_id = %1$d) UNION ' .
'(SELECT notice_id AS id FROM group_inbox WHERE group_id IN (SELECT group_id FROM group_member WHERE profile_id = %1$d)) ' .
'ORDER BY id DESC) AS T)',
$this->target->getID())
$notice->_join .= sprintf(
"\n" . 'NATURAL INNER JOIN (' .
'(SELECT id FROM notice WHERE profile_id IN (SELECT subscribed FROM subscription WHERE subscriber = %1$d)) ' .
'UNION (SELECT notice_id AS id FROM reply WHERE profile_id = %1$d) ' .
'UNION (SELECT notice_id AS id FROM attention WHERE profile_id = %1$d) ' .
'UNION (SELECT notice_id AS id FROM group_inbox WHERE group_id IN (SELECT group_id FROM group_member WHERE profile_id = %1$d))' .
') AS t1',
$this->target->getID()
);
$notice->whereAdd(sprintf(
"notice.created > TIMESTAMP '%s'",
$notice->escape($this->target->created)
));
if (!empty($since_id)) {
$notice->whereAdd(sprintf('notice.id > %d', $since_id));
$notice->whereAdd('id > ' . $since_id);
}
if (!empty($max_id)) {
$notice->whereAdd(sprintf('notice.id <= %d', $max_id));
$notice->whereAdd('id <= ' . $max_id);
}
$notice->whereAdd('scope != ' . Notice::MESSAGE_SCOPE);
$notice->whereAdd('scope <> ' . Notice::MESSAGE_SCOPE);
self::filterVerbs($notice, $this->selectVerbs);
// notice.id will give us even really old posts, which were recently
// imported. For example if a remote instance had problems and just
// managed to post here.
$notice->orderBy('id DESC');
$notice->limit($offset, $limit);
if (!$notice->find()) {

View File

@ -1,31 +1,54 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
if (!defined('GNUSOCIAL')) { exit(1); }
defined('GNUSOCIAL') || die();
/**
* Raw public stream
*
* @category Stream
* @package GNUsocial
* @author Evan Prodromou <evan@status.net>
* @copyright 2019 Free Software Foundation, Inc http://www.fsf.org
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
class NetworkPublicNoticeStream extends ModeratedNoticeStream
{
function __construct(Profile $scoped=null)
public function __construct(Profile $scoped = null)
{
parent::__construct(new CachingNoticeStream(new RawNetworkPublicNoticeStream(),
'networkpublic'),
$scoped);
parent::__construct(
new CachingNoticeStream(
new RawNetworkPublicNoticeStream(),
'networkpublic'
),
$scoped
);
}
}
/**
* Raw public stream
*
* @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/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
class RawNetworkPublicNoticeStream extends FullNoticeStream
{
function getNoticeIds($offset, $limit, $since_id, $max_id)
public function getNoticeIds($offset, $limit, $since_id, $max_id)
{
$notice = new Notice();
@ -38,11 +61,11 @@ class RawNetworkPublicNoticeStream extends FullNoticeStream
$notice->limit($offset, $limit);
}
$notice->whereAdd('is_local ='. Notice::REMOTE);
$notice->whereAdd('is_local = '. Notice::REMOTE);
// -1 == blacklisted, -2 == gateway (i.e. Twitter)
$notice->whereAdd('is_local !='. Notice::LOCAL_NONPUBLIC);
$notice->whereAdd('is_local !='. Notice::GATEWAY);
$notice->whereAdd('scope != ' . Notice::MESSAGE_SCOPE);
$notice->whereAdd('is_local <> '. Notice::LOCAL_NONPUBLIC);
$notice->whereAdd('is_local <> '. Notice::GATEWAY);
$notice->whereAdd('scope <> ' . Notice::MESSAGE_SCOPE);
Notice::addWhereSinceId($notice, $since_id);
Notice::addWhereMaxId($notice, $max_id);
@ -58,7 +81,7 @@ class RawNetworkPublicNoticeStream extends FullNoticeStream
}
$notice->free();
$notice = NULL;
$notice = null;
return $ids;
}

View File

@ -1,53 +1,52 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2011, StatusNet, Inc.
*
* Public stream
*
* 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
* @package GNUsocial
* @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/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('GNUSOCIAL')) { exit(1); }
defined('GNUSOCIAL') || die();
/**
* Public stream
*
* @category Stream
* @package StatusNet
* @package GNUsocial
* @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/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
class PublicNoticeStream extends ModeratedNoticeStream
{
function __construct(Profile $scoped=null)
public function __construct(Profile $scoped = null)
{
parent::__construct(new CachingNoticeStream(new RawPublicNoticeStream(),
'public'),
$scoped);
parent::__construct(
new CachingNoticeStream(
new RawPublicNoticeStream(),
'public'
),
$scoped
);
}
}
@ -55,16 +54,15 @@ class PublicNoticeStream extends ModeratedNoticeStream
* Raw public stream
*
* @category Stream
* @package StatusNet
* @package GNUsocial
* @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/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
class RawPublicNoticeStream extends FullNoticeStream
{
function getNoticeIds($offset, $limit, $since_id, $max_id)
public function getNoticeIds($offset, $limit, $since_id, $max_id)
{
$notice = new Notice();
@ -79,7 +77,7 @@ class RawPublicNoticeStream extends FullNoticeStream
// This feed always gives only local activities.
$notice->whereAdd('is_local = ' . Notice::LOCAL_PUBLIC);
$notice->whereAdd('scope != ' . Notice::MESSAGE_SCOPE);
$notice->whereAdd('scope <> ' . Notice::MESSAGE_SCOPE);
Notice::addWhereSinceId($notice, $since_id);
Notice::addWhereMaxId($notice, $max_id);
@ -95,7 +93,7 @@ class RawPublicNoticeStream extends FullNoticeStream
}
$notice->free();
$notice = NULL;
$notice = null;
return $ids;
}

View File

@ -1,53 +1,52 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2011, StatusNet, Inc.
*
* Stream of mentions of me
*
* 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
* @package GNUsocial
* @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/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('GNUSOCIAL')) { exit(1); }
defined('GNUSOCIAL') || die();
/**
* Stream of mentions of me
*
* @category Stream
* @package StatusNet
* @package GNUsocial
* @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/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
class ReplyNoticeStream extends ScopingNoticeStream
{
function __construct($userId, Profile $scoped=null)
public function __construct($userId, Profile $scoped = null)
{
parent::__construct(new CachingNoticeStream(new RawReplyNoticeStream($userId),
'reply:stream:' . $userId),
$scoped);
parent::__construct(
new CachingNoticeStream(
new RawReplyNoticeStream($userId),
'reply:stream:' . $userId
),
$scoped
);
}
}
@ -55,24 +54,23 @@ class ReplyNoticeStream extends ScopingNoticeStream
* Raw stream of mentions of me
*
* @category Stream
* @package StatusNet
* @package GNUsocial
* @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/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
class RawReplyNoticeStream extends NoticeStream
{
protected $userId;
function __construct($userId)
public function __construct($userId)
{
parent::__construct();
$this->userId = $userId;
}
function getNoticeIds($offset, $limit, $since_id, $max_id)
public function getNoticeIds($offset, $limit, $since_id, $max_id)
{
$reply = new Reply();
@ -94,14 +92,16 @@ class RawReplyNoticeStream extends NoticeStream
$reply->whereAddIn('notice.verb', $filter, 'string');
}
$filter = array_keys(array_filter($this->selectVerbs, function ($v) { return !$v; }));
$filter = array_keys(array_filter($this->selectVerbs, function ($v) {
return !$v;
}));
if (!empty($filter)) {
// exclude verbs in selectVerbs with values that equate to false
$reply->whereAddIn('!notice.verb', $filter, 'string');
}
}
$reply->whereAdd('notice.scope != ' . NOTICE::MESSAGE_SCOPE);
$reply->whereAdd('notice.scope <> ' . NOTICE::MESSAGE_SCOPE);
$reply->orderBy('reply.modified DESC, reply.notice_id DESC');

View File

@ -1,72 +1,63 @@
<?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('GNUSOCIAL')) { exit(1); }
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* Stream of notices for a list
*
* @category Stream
* @package StatusNet
* @package GNUsocial
* @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/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
defined('GNUSOCIAL') || die();
/**
* Stream of notices for a list
*
* @copyright 2011 StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
class PeopletagNoticeStream extends ScopingNoticeStream
{
function __construct($plist, Profile $scoped=null)
public function __construct($plist, Profile $scoped = null)
{
parent::__construct(new CachingNoticeStream(new RawPeopletagNoticeStream($plist),
'profile_list:notice_ids:' . $plist->id),
$scoped);
parent::__construct(
new CachingNoticeStream(
new RawPeopletagNoticeStream($plist),
'profile_list:notice_ids:' . $plist->id
),
$scoped
);
}
}
/**
* 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/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
class RawPeopletagNoticeStream extends NoticeStream
{
protected $profile_list;
function __construct($profile_list)
public function __construct($profile_list)
{
$this->profile_list = $profile_list;
}
@ -82,7 +73,7 @@ class RawPeopletagNoticeStream extends NoticeStream
* @return array array of notice ids.
*/
function getNoticeIds($offset, $limit, $since_id, $max_id)
public function getNoticeIds($offset, $limit, $since_id, $max_id)
{
$notice = new Notice();
@ -94,7 +85,10 @@ class RawPeopletagNoticeStream extends NoticeStream
$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));
$notice->whereAdd(sprintf(
"profile_tag.tag = '%s'",
$notice->escape($this->profile_list->tag)
));
if ($since_id != 0) {
$notice->whereAdd('notice.id > ' . $since_id);

View File

@ -1,65 +1,49 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* 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
* @package GNUsocial
* @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/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
defined('GNUSOCIAL') || die();
/**
* 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/
* @copyright 2009 StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
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;
}
$qry = 'SELECT profile_list.*, subscriber_count AS value ' .
'FROM profile_list WHERE profile_list.private = FALSE ' .
'ORDER BY value DESC ' .
'LIMIT ' . $limit;
$peopletag = Memcached_DataObject::cachedQuery('Profile_list',
$qry,
3600);
$peopletag = Memcached_DataObject::cachedQuery('Profile_list', $qry, 3600);
return $peopletag;
}

View File

@ -1,59 +1,58 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2011, StatusNet, Inc.
*
* Stream of notices by a profile
*
* 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
* @package GNUsocial
* @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/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('GNUSOCIAL')) { exit(1); }
defined('GNUSOCIAL') || die();
/**
* Stream of notices by a profile
*
* @category General
* @package StatusNet
* @package GNUsocial
* @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/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
class ProfileNoticeStream extends ScopingNoticeStream
{
protected $target;
function __construct(Profile $target, Profile $scoped=null)
public function __construct(Profile $target, Profile $scoped = null)
{
$this->target = $target;
parent::__construct(new CachingNoticeStream(new RawProfileNoticeStream($target),
'profile:notice_ids:' . $target->getID()),
$scoped);
parent::__construct(
new CachingNoticeStream(
new RawProfileNoticeStream($target),
'profile:notice_ids:' . $target->getID()
),
$scoped
);
}
function getNoticeIds($offset, $limit, $since_id=null, $max_id=null)
public function getNoticeIds($offset, $limit, $since_id = null, $max_id = null)
{
if ($this->impossibleStream()) {
return array();
@ -62,7 +61,7 @@ class ProfileNoticeStream extends ScopingNoticeStream
}
}
function getNotices($offset, $limit, $since_id=null, $max_id=null)
public function getNotices($offset, $limit, $since_id = null, $max_id = null)
{
if ($this->impossibleStream()) {
throw new PrivateStreamException($this->target, $this->scoped);
@ -71,7 +70,7 @@ class ProfileNoticeStream extends ScopingNoticeStream
}
}
function impossibleStream()
public function impossibleStream()
{
if (!$this->target->readableBy($this->scoped)) {
// cannot read because it's a private stream and either noone's logged in or they are not subscribers
@ -82,12 +81,11 @@ class ProfileNoticeStream extends ScopingNoticeStream
if (common_config('notice', 'hidespam')) {
// if this is a silenced user
if ($this->target->hasRole(Profile_role::SILENCED)
// and we are either not logged in
&& (!$this->scoped instanceof Profile
// or if we are, we are not logged in as the target, and we don't have right to review spam
|| (!$this->scoped->sameAs($this->target) && !$this->scoped->hasRight(Right::REVIEWSPAM))
)) {
if ($this->target->hasRole(Profile_role::SILENCED) &&
// and we are either not logged in
(!$this->scoped instanceof Profile ||
// or if we are, we are not logged in as the target, and we don't have right to review spam
(!$this->scoped->sameAs($this->target) && !$this->scoped->hasRight(Right::REVIEWSPAM)))) {
return true;
}
}
@ -100,11 +98,10 @@ class ProfileNoticeStream extends ScopingNoticeStream
* Raw stream of notices by a profile
*
* @category General
* @package StatusNet
* @package GNUsocial
* @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/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
class RawProfileNoticeStream extends NoticeStream
@ -112,13 +109,13 @@ class RawProfileNoticeStream extends NoticeStream
protected $target;
protected $selectVerbs = array(); // select all verbs
function __construct(Profile $target)
public function __construct(Profile $target)
{
parent::__construct();
$this->target = $target;
}
function getNoticeIds($offset, $limit, $since_id, $max_id)
public function getNoticeIds($offset, $limit, $since_id, $max_id)
{
$notice = new Notice();
@ -127,7 +124,7 @@ class RawProfileNoticeStream extends NoticeStream
$notice->selectAdd();
$notice->selectAdd('id');
$notice->whereAdd('scope != ' . Notice::MESSAGE_SCOPE);
$notice->whereAdd('scope <> ' . Notice::MESSAGE_SCOPE);
Notice::addWhereSinceId($notice, $since_id);
Notice::addWhereMaxId($notice, $max_id);

View File

@ -1,47 +1,42 @@
<?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/>.
*/
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
defined('GNUSOCIAL') || die();
class SearchEngine
{
protected $target;
protected $table;
function __construct($target, $table)
public function __construct($target, $table)
{
$this->target = $target;
$this->table = $table;
}
function query($q)
public function query($q)
{
}
function limit($offset, $count, $rss = false)
public function limit($offset, $count, $rss = false)
{
return $this->target->limit($offset, $count);
}
function set_sort_mode($mode)
public function set_sort_mode($mode)
{
switch ($mode) {
case 'chron':
@ -75,42 +70,82 @@ class SearchEngine
}
}
class PostgreSQLSearch extends SearchEngine
{
public function query($q)
{
if ($this->table === 'profile') {
$cols = implode(" || ' ' || ", array_map(
function ($col) {
return sprintf(
"COALESCE(%s.%s, '')",
common_database_tablename($this->table),
$col
);
},
['nickname', 'fullname', 'location', 'bio', 'homepage']
));
$this->target->whereAdd(sprintf(
'to_tsvector(\'english\', %2$s) @@ plainto_tsquery(\'%1$s\')',
$this->target->escape($q, true),
$cols
));
return true;
} elseif ($this->table === 'notice') {
// Don't show imported notices
$this->target->whereAdd('notice.is_local <> ' . Notice::GATEWAY);
$this->target->whereAdd(sprintf(
'to_tsvector(\'english\', content) @@ plainto_tsquery(\'%1$s\')',
$this->target->escape($q, true)
));
return true;
} else {
throw new ServerException('Unknown table: ' . $this->table);
}
}
}
class MySQLSearch extends SearchEngine
{
function query($q)
public function query($q)
{
if ('profile' === $this->table) {
$this->target->whereAdd(
sprintf('MATCH (%2$s.nickname, %2$s.fullname, %2$s.location, %2$s.bio, %2$s.homepage) ' .
'AGAINST ("%1$s" IN BOOLEAN MODE)',
$this->target->escape($q, true),
$this->table)
);
if ($this->table === 'profile') {
$this->target->whereAdd(sprintf(
'MATCH (%2$s.nickname, %2$s.fullname, %2$s.location, %2$s.bio, %2$s.homepage) ' .
'AGAINST (\'%1$s\' IN BOOLEAN MODE)',
$this->target->escape($q, true),
$this->table
));
if (strtolower($q) != $q) {
$this->target->whereAdd(
sprintf('MATCH (%2$s.nickname, %2$s.fullname, %2$s.location, %2$s.bio, %2$s.homepage) ' .
'AGAINST ("%1$s" IN BOOLEAN MODE)',
sprintf(
'MATCH (%2$s.nickname, %2$s.fullname, %2$s.location, %2$s.bio, %2$s.homepage) ' .
'AGAINST (\'%1$s\' IN BOOLEAN MODE)',
$this->target->escape(strtolower($q), true),
$this->table),
$this->table
),
'OR'
);
}
return true;
} else if ('notice' === $this->table) {
} elseif ($this->table === 'notice') {
// Don't show imported notices
$this->target->whereAdd('notice.is_local != ' . Notice::GATEWAY);
$this->target->whereAdd('notice.is_local <> ' . Notice::GATEWAY);
$this->target->whereAdd(
sprintf('MATCH (%2$s.content) AGAINST ("%1$s" IN BOOLEAN MODE)',
$this->target->escape($q, true),
$this->table)
);
$this->target->whereAdd(sprintf(
'MATCH (%2$s.content) AGAINST (\'%1$s\' IN BOOLEAN MODE)',
$this->target->escape($q, true),
$this->table
));
if (strtolower($q) != $q) {
$this->target->whereAdd(
sprintf('MATCH (%2$s.content) AGAINST ("%1$s" IN BOOLEAN MODE)',
sprintf(
'MATCH (%2$s.content) AGAINST (\'%1$s\' IN BOOLEAN MODE)',
$this->target->escape(strtolower($q), true),
$this->table),
$this->table
),
'OR'
);
}
@ -122,20 +157,22 @@ class MySQLSearch extends SearchEngine
}
}
class MySQLLikeSearch extends SearchEngine
class SQLLikeSearch extends SearchEngine
{
function query($q)
public function query($q)
{
if ('profile' === $this->table) {
$qry = sprintf('(%2$s.nickname LIKE "%%%1$s%%" OR ' .
' %2$s.fullname LIKE "%%%1$s%%" OR ' .
' %2$s.location LIKE "%%%1$s%%" OR ' .
' %2$s.bio LIKE "%%%1$s%%" OR ' .
' %2$s.homepage LIKE "%%%1$s%%")',
$this->target->escape($q, true),
$this->table);
} else if ('notice' === $this->table) {
$qry = sprintf('content LIKE "%%%1$s%%"', $this->target->escape($q, true));
if ($this->table === 'profile') {
$qry = sprintf(
'( %2$s.nickname LIKE \'%%%1$s%%\' ' .
' OR %2$s.fullname LIKE \'%%%1$s%%\' ' .
' OR %2$s.location LIKE \'%%%1$s%%\' ' .
' OR %2$s.bio LIKE \'%%%1$s%%\' ' .
' OR %2$s.homepage LIKE \'%%%1$s%%\')',
$this->target->escape($q, true),
$this->table
);
} elseif ($this->table === 'notice') {
$qry = sprintf('content LIKE \'%%%1$s%%\'', $this->target->escape($q, true));
} else {
throw new ServerException('Unknown table: ' . $this->table);
}
@ -145,21 +182,3 @@ class MySQLLikeSearch extends SearchEngine
return true;
}
}
class PGSearch extends SearchEngine
{
function query($q)
{
if ('profile' === $this->table) {
return $this->target->whereAdd('textsearch @@ plainto_tsquery(\'' . $this->target->escape($q) . '\')');
} else if ('notice' === $this->table) {
// XXX: We need to filter out gateway notices (notice.is_local = -2) --Zach
return $this->target->whereAdd('to_tsvector(\'english\', content) @@ plainto_tsquery(\'' . $this->target->escape($q) . '\')');
} else {
throw new ServerException('Unknown table: ' . $this->table);
}
}
}

View File

@ -1,48 +1,40 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* StatusNet, the distributed open-source microblogging tool
*
* Section for featured users
*
* 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
* @package GNUsocial
* @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/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
defined('GNUSOCIAL') || die();
/**
* Section for featured users
*
* @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/
* @copyright 2009 StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
class FeaturedUsersSection extends ProfileSection
{
function show()
public function show()
{
$featured_nicks = common_config('nickname', 'featured');
if (empty($featured_nicks)) {
@ -51,7 +43,7 @@ class FeaturedUsersSection extends ProfileSection
parent::show();
}
function getProfiles()
public function getProfiles()
{
$featured_nicks = common_config('nickname', 'featured');
@ -65,43 +57,30 @@ class FeaturedUsersSection extends ProfileSection
$quoted[] = "'$nick'";
}
$table = "user";
if(common_config('db','quote_identifiers')) {
$table = '"' . $table . '"';
}
$table = common_database_tablename('user');
$limit = PROFILES_PER_SECTION + 1;
$qry = 'SELECT profile.* ' .
'FROM profile JOIN '. $table .' on profile.id = '. $table .'.id ' .
'WHERE '. $table .'.nickname in (' . implode(',', $quoted) . ') ' .
'ORDER BY profile.created DESC ';
'FROM profile INNER JOIN ' . $table . ' ON profile.id = ' . $table . '.id ' .
'WHERE ' . $table . '.nickname IN (' . implode(',', $quoted) . ') ' .
'ORDER BY profile.created DESC LIMIT ' . $limit;
$limit = PROFILES_PER_SECTION + 1;
$offset = 0;
if (common_config('db','type') == 'pgsql') {
$qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
} else {
$qry .= ' LIMIT ' . $offset . ', ' . $limit;
}
$profile = Memcached_DataObject::cachedQuery('Profile',
$qry,
6 * 3600);
$profile = Memcached_DataObject::cachedQuery('Profile', $qry, 6 * 3600);
return $profile;
}
function title()
public function title()
{
// TRANS: Title for featured users section.
return _('Featured users');
}
function divId()
public function divId()
{
return 'featured_users';
}
function moreUrl()
public function moreUrl()
{
return common_local_url('featured');
}

View File

@ -1,23 +1,25 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* 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/>.
* @copyright 2008, 2009 StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('GNUSOCIAL')) { exit(1); }
defined('GNUSOCIAL') || die();
// 10x8
@ -36,12 +38,12 @@ class GalleryAction extends ProfileAction
parent::handle();
}
function showContent()
public function showContent()
{
$this->showTagsDropdown();
}
function showTagsDropdown()
public function showTagsDropdown()
{
$tag = $this->trimmed('tag');
@ -59,13 +61,17 @@ class GalleryAction extends ProfileAction
$this->elementStart('ul');
$this->elementStart('li', array('id' => 'filter_tags_all',
'class' => 'child_1'));
$this->element('a',
array('href' =>
common_local_url($this->trimmed('action'),
array('nickname' =>
$this->target->getNickname()))),
// TRANS: List element on gallery action page to show all tags.
_m('TAGS','All'));
$this->element(
'a',
[
'href' => common_local_url(
$this->trimmed('action'),
['nickname' => $this->target->getNickname()]
),
],
// TRANS: List element on gallery action page to show all tags.
_m('TAGS', 'All')
);
$this->elementEnd('li');
$this->elementStart('li', array('id'=>'filter_tags_item'));
$this->elementStart('form', array('name' => 'bytag',
@ -76,12 +82,18 @@ class GalleryAction extends ProfileAction
// TRANS: Fieldset legend on gallery action page.
$this->element('legend', null, _('Select tag to filter'));
// TRANS: Dropdown field label on gallery action page for a list containing tags.
$this->dropdown('tag', _('Tag'), $content,
// TRANS: Dropdown field title on gallery action page for a list containing tags.
_('Choose a tag to narrow list.'), false, $tag);
$this->dropdown(
'tag',
_('Tag'),
$content,
// TRANS: Dropdown field title on gallery action page for a list containing tags.
_('Choose a tag to narrow list.'),
false,
$tag
);
$this->hidden('nickname', $this->target->getNickname());
// TRANS: Submit button text on gallery action page.
$this->submit('submit', _m('BUTTON','Go'));
$this->submit('submit', _m('BUTTON', 'Go'));
$this->elementEnd('fieldset');
$this->elementEnd('form');
$this->elementEnd('li');
@ -92,7 +104,7 @@ class GalleryAction extends ProfileAction
}
// Get list of tags we tagged other users with
function getTags($lst, $usr)
public function getTags($lst, $usr)
{
$profile_tag = new Notice_tag();
$profile_tag->query('SELECT DISTINCT(tag) ' .
@ -100,7 +112,7 @@ class GalleryAction extends ProfileAction
'WHERE tagger = ' . $this->target->id . ' ' .
'AND ' . $usr . ' = ' . $this->target->id . ' ' .
'AND ' . $lst . ' = tagged ' .
'AND tagger != tagged');
'AND tagger <> tagged');
$tags = array();
while ($profile_tag->fetch()) {
$tags[] = $profile_tag->tag;
@ -109,12 +121,12 @@ class GalleryAction extends ProfileAction
return $tags;
}
function getAllTags()
public function getAllTags()
{
return array();
}
function showProfileBlock()
public function showProfileBlock()
{
$block = new AccountProfileBlock($this, $this->target);
$block->show();

View File

@ -1,35 +1,30 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* StatusNet, the distributed open-source microblogging tool
*
* Base class for sections showing lists of people
*
* 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
* @package GNUsocial
* @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/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
defined('GNUSOCIAL') || die();
/**
* Base class for sections
@ -37,44 +32,32 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
* These are the widgets that show interesting data about a person
* group, or site.
*
* @category Widget
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
* @copyright 2009 StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
class TopPostersSection extends ProfileSection
{
function getProfiles()
public function getProfiles()
{
$qry = 'SELECT profile.*, count(*) as value ' .
'FROM profile JOIN notice ON profile.id = notice.profile_id ' .
(common_config('public', 'localonly') ? 'WHERE is_local = 1 ' : '') .
'GROUP BY profile.id,nickname,fullname,profileurl,homepage,bio,location,profile.created,profile.modified,textsearch ' .
'ORDER BY value DESC ';
$limit = PROFILES_PER_SECTION;
$offset = 0;
if (common_config('db','type') == 'pgsql') {
$qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
} else {
$qry .= ' LIMIT ' . $offset . ', ' . $limit;
}
$qry = 'SELECT profile.*, COUNT(*) AS value ' .
'FROM profile JOIN notice ON profile.id = notice.profile_id ' .
(common_config('public', 'localonly') ? 'WHERE is_local = 1 ' : '') .
'GROUP BY profile.id, nickname, fullname, profileurl, homepage, bio, location, profile.created, profile.modified ' .
'ORDER BY value DESC LIMIT ' . $limit;
$profile = Memcached_DataObject::cachedQuery('Profile',
$qry,
6 * 3600);
$profile = Memcached_DataObject::cachedQuery('Profile', $qry, 6 * 3600);
return $profile;
}
function title()
public function title()
{
// TRANS: Title for top posters section.
return _('Top posters');
}
function divId()
public function divId()
{
return 'top_posters';
}

View File

@ -1,76 +1,74 @@
<?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/>.
*/
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
defined('GNUSOCIAL') || die();
class Daemon
{
var $daemonize = true;
var $_id = 'generic';
public $daemonize = true;
public $_id = 'generic';
function __construct($daemonize = true)
public function __construct($daemonize = true)
{
$this->daemonize = $daemonize;
}
function name()
public function name()
{
return null;
}
function get_id()
public function get_id()
{
return $this->_id;
}
function set_id($id)
public function set_id($id)
{
$this->_id = $id;
}
function background()
public function background()
{
/*
* This prefers to Starting PHP 5.4 (dotdeb), maybe earlier for some version/distrib
* seems MySQL connection using mysqli driver get lost when fork.
* Need to unset it so that child process recreate it.
*
* @todo FIXME cleaner way to do it ?
*/
global $_DB_DATAOBJECT;
unset($_DB_DATAOBJECT['CONNECTIONS']);
// Database connection will likely get lost after forking
$this->resetDb();
$pid = pcntl_fork();
if ($pid < 0) { // error
common_log(LOG_ERR, "Could not fork.");
return false;
} else if ($pid > 0) { // parent
common_log(LOG_INFO, "Successfully forked.");
exit(0);
} else { // child
return true;
// Double-forking.
foreach (['single', 'double'] as $v) {
switch ($pid = pcntl_fork()) {
case -1: // error
common_log(LOG_ERR, 'Could not fork.');
return false;
case 0: // child
if ($v === 'single') {
posix_setsid();
}
break;
default: // parent
if ($v === 'double') {
common_log(LOG_INFO, 'Successfully forked.');
}
die();
}
}
return true;
}
function alreadyRunning()
public function alreadyRunning()
{
$pidfilename = $this->pidFilename();
@ -89,7 +87,7 @@ class Daemon
}
}
function writePidFile()
public function writePidFile()
{
$pidfilename = $this->pidFilename();
@ -100,7 +98,7 @@ class Daemon
return file_put_contents($pidfilename, posix_getpid() . "\n");
}
function clearPidFile()
public function clearPidFile()
{
$pidfilename = $this->pidFilename();
if (!$pidfilename) {
@ -109,7 +107,7 @@ class Daemon
return unlink($pidfilename);
}
function pidFilename()
public function pidFilename()
{
$piddir = common_config('daemon', 'piddir');
if (!$piddir) {
@ -122,15 +120,17 @@ class Daemon
return $piddir . '/' . $name . '.pid';
}
function changeUser()
public function changeUser()
{
$groupname = common_config('daemon', 'group');
if ($groupname) {
$group_info = posix_getgrnam($groupname);
if (!$group_info) {
common_log(LOG_WARNING,
'Ignoring unknown group for daemon: ' . $groupname);
common_log(
LOG_WARNING,
'Ignoring unknown group for daemon: ' . $groupname
);
} else {
common_log(LOG_INFO, "Setting group to " . $groupname);
posix_setgid($group_info['gid']);
@ -142,8 +142,10 @@ class Daemon
if ($username) {
$user_info = posix_getpwnam($username);
if (!$user_info) {
common_log(LOG_WARNING,
'Ignoring unknown user for daemon: ' . $username);
common_log(
LOG_WARNING,
'Ignoring unknown user for daemon: ' . $username
);
} else {
common_log(LOG_INFO, "Setting user to " . $username);
posix_setuid($user_info['uid']);
@ -151,7 +153,7 @@ class Daemon
}
}
function runOnce()
public function runOnce()
{
if ($this->alreadyRunning()) {
common_log(LOG_INFO, $this->name() . ' already running. Exiting.');
@ -169,7 +171,7 @@ class Daemon
$this->clearPidFile();
}
function run()
public function run()
{
return true;
}

View File

@ -1,29 +1,29 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* GNU social - a federating social network
*
*
* 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 Config
* @package GNUsocial
* @author Evan Prodromou <evan@status.net>
* @copyright 2008-2009, 2019 Free Software Foundation http://fsf.org
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link https://www.gnu.org/software/social/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
defined('GNUSOCIAL') || die();
$default =
array('site' =>
array('name' => 'Just another GNU social node',
@ -74,7 +74,7 @@ $default =
'mirror' => null,
'utf8' => true,
'db_driver' => 'DB', # XXX: JanRain libs only work with DB
'quote_identifiers' => false,
'quote_identifiers' => true,
'type' => 'mysql',
'schemacheck' => 'runtime', // 'runtime' or 'script'
'annotate_queries' => false, // true to add caller comments to queries, eg /* POST Notice::saveNew */

View File

@ -68,11 +68,11 @@ abstract class Installer
'check_module' => 'mysqli',
'scheme' => 'mysqli', // DSN prefix for PEAR::DB
],
/*'pgsql' => [
'name' => 'PostgreSQL',
'pgsql' => [
'name' => 'PostgreSQL 11+',
'check_module' => 'pgsql',
'scheme' => 'pgsql', // DSN prefix for PEAR::DB
]*/
]
];
/**
@ -304,20 +304,34 @@ abstract class Installer
throw new Exception('Cannot connect to database: ' . $conn->getMessage());
}
// ensure database encoding is UTF8
$conn->query('SET NAMES utf8mb4');
if ($this->dbtype == 'mysql') {
$server_encoding = $conn->getRow("SHOW VARIABLES LIKE 'character_set_server'")[1];
if ($server_encoding != 'utf8mb4') {
$this->updateStatus("GNU social requires UTF8 character encoding. Your database is " . htmlentities($server_encoding));
switch ($this->dbtype) {
case 'pgsql':
// ensure the database encoding is UTF8
$conn->query("SET NAMES 'UTF8'");
$server_encoding = $conn->getRow('SHOW server_encoding')[0];
if ($server_encoding !== 'UTF8') {
$this->updateStatus(
'GNU social requires the UTF8 character encoding. Yours is ' .
htmlentities($server_encoding)
);
return false;
}
break;
case 'mysql':
// ensure the database encoding is utf8mb4
$conn->query("SET NAMES 'utf8mb4'");
$server_encoding = $conn->getRow("SHOW VARIABLES LIKE 'character_set_server'")[1];
if ($server_encoding !== 'utf8mb4') {
$this->updateStatus(
'GNU social requires the utf8mb4 character encoding. Yours is ' .
htmlentities($server_encoding)
);
return false;
}
break;
default:
$this->updateStatus('Unknown DB type selected: ' . $this->dbtype);
return false;
}
} elseif ($this->dbtype == 'pgsql') {
$server_encoding = $conn->getRow('SHOW server_encoding')[0];
if ($server_encoding != 'UTF8') {
$this->updateStatus("GNU social requires UTF8 character encoding. Your database is " . htmlentities($server_encoding));
return false;
}
}
$res = $this->updateStatus("Creating database tables...");
@ -362,7 +376,7 @@ abstract class Installer
*/
public function createCoreTables(DB_common $conn): bool
{
$schema = Schema::get($conn);
$schema = Schema::get($conn, $this->dbtype);
$tableDefs = $this->getCoreSchema();
foreach ($tableDefs as $name => $def) {
if (defined('DEBUG_INSTALLER')) {
@ -446,7 +460,6 @@ abstract class Installer
// database
"\$config['db']['database'] = {$vals['db_database']};\n\n" .
($this->db['type'] == 'pgsql' ? "\$config['db']['quote_identifiers'] = true;\n\n" : '') .
"\$config['db']['type'] = {$vals['db_type']};\n\n" .
"// Uncomment below for better performance. Just remember you must run\n" .
@ -457,7 +470,7 @@ abstract class Installer
$cfg = str_replace("\n", PHP_EOL, $cfg);
// write configuration file out to install directory
$res = file_put_contents(INSTALLDIR . '/config.php', $cfg);
$res = file_put_contents(INSTALLDIR . DIRECTORY_SEPARATOR . 'config.php', $cfg);
return $res;
}

View File

@ -167,7 +167,7 @@ class InternalSessionHandler implements SessionHandlerInterface
$ids = [];
$session = new Session();
$session->whereAdd('modified < "' . $epoch . '"');
$session->whereAdd("modified < TIMESTAMP '" . $epoch . "'");
$session->selectAdd();
$session->selectAdd('id');

View File

@ -1,36 +1,33 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* StatusNet, the distributed open-source microblogging tool
*
* utilities for sending email
*
* 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/>.
* Utilities for sending email
*
* @category Mail
* @package StatusNet
* @package GNUsocial
* @author Evan Prodromou <evan@status.net>
* @author Zach Copley <zach@status.net>
* @author Robin Millette <millette@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/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('GNUSOCIAL')) { exit(1); }
defined('GNUSOCIAL') || die();
require_once 'Mail.php';
@ -49,8 +46,10 @@ function mail_backend()
if (!$backend) {
$mail = new Mail();
$backend = $mail->factory(common_config('mail', 'backend'),
common_config('mail', 'params') ?: array());
$backend = $mail->factory(
common_config('mail', 'backend'),
common_config('mail', 'params') ?: []
);
if ($_PEAR->isError($backend)) {
throw new EmailException($backend->getMessage(), $backend->getCode());
}
@ -76,7 +75,7 @@ function mail_send($recipients, $headers, $body)
$backend = mail_backend();
if (!isset($headers['Content-Type'])) {
$headers['Content-Type'] = 'text/plain; charset=UTF-8';
$headers['Content-Type'] = 'text/plain; charset=UTF-8';
}
assert($backend); // throws an error if it's bad
@ -124,7 +123,6 @@ function mail_notify_from()
$notifyfrom = common_config('mail', 'notifyfrom');
if (!$notifyfrom) {
$domain = mail_domain();
$notifyfrom = '"'. str_replace('"', '\\"', common_config('site', 'name')) .'" <noreply@'.$domain.'>';
@ -194,7 +192,6 @@ function mail_subscribe_notify_profile($listenee, $other)
{
if ($other->hasRight(Right::EMAILONSUBSCRIBE) &&
$listenee->email && $listenee->emailnotifysub) {
$profile = $listenee->getProfile();
$name = $profile->getBestName();
@ -211,15 +208,19 @@ function mail_subscribe_notify_profile($listenee, $other)
$headers['To'] = $name . ' <' . $listenee->email . '>';
// TRANS: Subject of new-subscriber notification e-mail.
// TRANS: %1$s is the subscribing user's nickname, %2$s is the StatusNet sitename.
$headers['Subject'] = sprintf(_('%1$s is now following you on %2$s.'),
$other->getBestName(),
common_config('site', 'name'));
$headers['Subject'] = sprintf(
_('%1$s is now following you on %2$s.'),
$other->getBestName(),
common_config('site', 'name')
);
// TRANS: Main body of new-subscriber notification e-mail.
// TRANS: %1$s is the subscriber's long name, %2$s is the StatusNet sitename.
$body = sprintf(_('%1$s is now following you on %2$s.'),
$long_name,
common_config('site', 'name')) .
$body = sprintf(
_('%1$s is now following you on %2$s.'),
$long_name,
common_config('site', 'name')
) .
mail_profile_block($other) .
mail_footer_block();
@ -233,7 +234,6 @@ function mail_subscribe_pending_notify_profile($listenee, $other)
{
if ($other->hasRight(Right::EMAILONSUBSCRIBE) &&
$listenee->email && $listenee->emailnotifysub) {
$profile = $listenee->getProfile();
$name = $profile->getBestName();
@ -251,18 +251,22 @@ function mail_subscribe_pending_notify_profile($listenee, $other)
$headers['To'] = $name . ' <' . $listenee->email . '>';
// TRANS: Subject of pending new-subscriber notification e-mail.
// TRANS: %1$s is the subscribing user's nickname, %2$s is the StatusNet sitename.
$headers['Subject'] = sprintf(_('%1$s would like to listen to '.
$headers['Subject'] = sprintf(
_('%1$s would like to listen to '.
'your notices on %2$s.'),
$other->getBestName(),
common_config('site', 'name'));
$other->getBestName(),
common_config('site', 'name')
);
// TRANS: Main body of pending new-subscriber notification e-mail.
// TRANS: %1$s is the subscriber's long name, %2$s is the StatusNet sitename.
$body = sprintf(_('%1$s would like to listen to your notices on %2$s. ' .
$body = sprintf(
_('%1$s would like to listen to your notices on %2$s. ' .
'You may approve or reject their subscription at %3$s'),
$long_name,
common_config('site', 'name'),
common_local_url('subqueue', array('nickname' => $listenee->nickname))) .
$long_name,
common_config('site', 'name'),
common_local_url('subqueue', ['nickname' => $listenee->nickname])
) .
mail_profile_block($other) .
mail_footer_block();
@ -277,13 +281,15 @@ function mail_footer_block()
// TRANS: Common footer block for StatusNet notification emails.
// TRANS: %1$s is the StatusNet sitename,
// TRANS: %2$s is a link to the addressed user's e-mail settings.
return "\n\n" . sprintf(_('Faithfully yours,'.
"\n".'%1$s.'."\n\n".
"----\n".
"Change your email address or ".
"notification options at ".'%2$s'),
common_config('site', 'name'),
common_local_url('emailsettings')) . "\n";
return "\n\n" . sprintf(
_('Faithfully yours,'.
"\n".'%1$s.'."\n\n".
"----\n".
"Change your email address or ".
"notification options at ".'%2$s'),
common_config('site', 'name'),
common_local_url('emailsettings')
) . "\n";
}
/**
@ -326,10 +332,12 @@ function mail_profile_block($profile)
// TRANS: This is a paragraph in a new-subscriber e-mail.
// TRANS: %s is a URL where the subscriber can be reported as abusive.
$out[] = sprintf(_('If you believe this account is being used abusively, ' .
'you can block them from your subscribers list and ' .
'report as spam to site administrators at %s.'),
$blocklink);
$out[] = sprintf(
_('If you believe this account is being used abusively, ' .
'you can block them from your subscribers list and ' .
'report as spam to site administrators at %s.'),
$blocklink
);
$out[] = "";
return implode("\n", $out);
@ -354,18 +362,22 @@ function mail_new_incoming_notify($user)
$headers['To'] = $name . ' <' . $user->email . '>';
// TRANS: Subject of notification mail for new posting email address.
// TRANS: %s is the StatusNet sitename.
$headers['Subject'] = sprintf(_('New email address for posting to %s'),
common_config('site', 'name'));
$headers['Subject'] = sprintf(
_('New email address for posting to %s'),
common_config('site', 'name')
);
// TRANS: Body of notification mail for new posting email address.
// TRANS: %1$s is the StatusNet sitename, %2$s is the e-mail address to send
// TRANS: to to post by e-mail, %3$s is a URL to more instructions.
$body = sprintf(_("You have a new posting address on %1\$s.\n\n".
"Send email to %2\$s to post new messages.\n\n".
"More email instructions at %3\$s."),
common_config('site', 'name'),
$user->incomingemail,
common_local_url('doc', array('title' => 'email'))) .
$body = sprintf(
_("You have a new posting address on %1\$s.\n\n".
"Send email to %2\$s to post new messages.\n\n".
"More email instructions at %3\$s."),
common_config('site', 'name'),
$user->incomingemail,
common_local_url('doc', ['title' => 'email'])
) .
mail_footer_block();
mail_send($user->email, $headers, $body);
@ -402,42 +414,58 @@ function mail_broadcast_notice_sms($notice)
$user = new User();
$UT = common_config('db','type')=='pgsql'?'"user"':'user';
$replies = $notice->getReplies();
$user->query('SELECT nickname, smsemail, incomingemail ' .
"FROM $UT LEFT OUTER JOIN subscription " .
"ON $UT.id = subscription.subscriber " .
'AND subscription.subscribed = ' . $notice->profile_id . ' ' .
'AND subscription.subscribed != subscription.subscriber ' .
// Users (other than the sender) who `want SMS notices':
"WHERE $UT.id != " . $notice->profile_id . ' ' .
"AND $UT.smsemail IS NOT null " .
"AND $UT.smsnotify = 1 " .
// ... where either the user _is_ subscribed to the sender
// (any of the "subscription" fields IS NOT null)
// and wants to get SMS for all of this scribe's notices...
'AND (subscription.sms = 1 ' .
// ... or where the user was mentioned in
// or replied-to with the notice:
($replies ? sprintf("OR $UT.id in (%s)",
implode(',', $replies))
: '') .
')');
$repliesQry = '';
if (!empty($replies)) {
$repliesQry = sprintf(
'OR %s.id IN (%s)',
$user->escapedTableName(),
implode(',', $replies)
);
}
$user->query(sprintf(
'SELECT nickname, smsemail, incomingemail ' .
'FROM %1$s LEFT JOIN subscription ' .
'ON %1$s.id = subscription.subscriber ' .
'AND subscription.subscribed = %2$d ' .
'AND subscription.subscribed <> subscription.subscriber ' .
// Users (other than the sender) who `want SMS notices':
'WHERE %1$s.id <> %2$d ' .
'AND %1$s.smsemail IS NOT NULL ' .
'AND %1$s.smsnotify = TRUE ' .
// ... where either the user _is_ subscribed to the sender
// (any of the "subscription" fields IS NOT NULL)
// and wants to get SMS for all of this scribe's notices...
'AND (subscription.sms = TRUE ' .
// ... or where the user was mentioned in
// or replied-to with the notice:
$repliesQry .
')',
$user->escapedTableName(),
$notice->profile_id
));
while ($user->fetch()) {
common_log(LOG_INFO,
'Sending notice ' . $notice->id . ' to ' . $user->smsemail,
__FILE__);
$success = mail_send_sms_notice_address($notice,
$user->smsemail,
$user->incomingemail,
$user->nickname);
common_log(
LOG_INFO,
'Sending notice ' . $notice->id . ' to ' . $user->smsemail,
__FILE__
);
$success = mail_send_sms_notice_address(
$notice,
$user->smsemail,
$user->incomingemail,
$user->nickname
);
if (!$success) {
// XXX: Not sure, but I think that's the right thing to do
common_log(LOG_WARNING,
'Sending notice ' . $notice->id . ' to ' .
$user->smsemail . ' FAILED, cancelling.',
__FILE__);
common_log(
LOG_WARNING,
'Sending notice ' . $notice->id . ' to ' . $user->smsemail . ' FAILED, canceling.',
__FILE__
);
return false;
}
}
@ -462,10 +490,12 @@ function mail_broadcast_notice_sms($notice)
*/
function mail_send_sms_notice($notice, $user)
{
return mail_send_sms_notice_address($notice,
$user->smsemail,
$user->incomingemail,
$user->nickname);
return mail_send_sms_notice_address(
$notice,
$user->smsemail,
$user->incomingemail,
$user->nickname
);
}
/**
@ -496,8 +526,7 @@ function mail_send_sms_notice_address($notice, $smsemail, $incomingemail, $nickn
$headers['To'] = $to;
// TRANS: Subject line for SMS-by-email notification messages.
// TRANS: %s is the posting user's nickname.
$headers['Subject'] = sprintf(_('%s status'),
$other->getBestName());
$headers['Subject'] = sprintf(_('%s status'), $other->getBestName());
$body = $notice->content;
@ -554,14 +583,16 @@ function mail_notify_nudge($from, $to)
// TRANS: Body for 'nudge' notification email.
// TRANS: %1$s is the nuding user's long name, $2$s is the nudging user's nickname,
// TRANS: %3$s is a URL to post notices at.
$body = sprintf(_("%1\$s (%2\$s) is wondering what you are up to ".
"these days and is inviting you to post some news.\n\n".
"So let's hear from you :)\n\n".
"%3\$s\n\n".
"Don't reply to this email; it won't get to them."),
$from_profile->getBestName(),
$from->nickname,
common_local_url('all', array('nickname' => $to->nickname))) .
$body = sprintf(
_('%1$s (%2$s) is wondering what you are up to ' .
"these days and is inviting you to post some news.\n\n" .
"So let's hear from you :)\n\n" .
"%3\$s\n\n" .
"Don't reply to this email; it won't get to them."),
$from_profile->getBestName(),
$from->nickname,
common_local_url('all', ['nickname' => $to->nickname])
) .
mail_footer_block();
common_switch_locale();
@ -612,17 +643,19 @@ function mail_notify_message(Notice $message, Profile $from = null, ?array $to =
// TRANS: Body for direct-message notification email.
// TRANS: %1$s is the sending user's long name, %2$s is the sending user's nickname,
// TRANS: %3$s is the message content, %4$s a URL to the message,
$body = sprintf(_("%1\$s (%2\$s) sent you a private message:\n\n".
"------------------------------------------------------\n".
"%3\$s\n".
"------------------------------------------------------\n\n".
"You can reply to their message here:\n\n".
"%4\$s\n\n".
"Don't reply to this email; it won't get to them."),
$from->getBestName(),
$from->getNickname(),
$message->getContent(),
common_local_url('newmessage', ['to' => $from->getID()])) .
$body = sprintf(
_("%1\$s (%2\$s) sent you a private message:\n\n".
"------------------------------------------------------\n".
"%3\$s\n".
"------------------------------------------------------\n\n".
"You can reply to their message here:\n\n".
"%4\$s\n\n".
"Don't reply to this email; it won't get to them."),
$from->getBestName(),
$from->getNickname(),
$message->getContent(),
common_local_url('newmessage', ['to' => $from->getID()])
) .
mail_footer_block();
$headers = _mail_prepare_headers('message', $t->getNickname(), $from->getNickname());
@ -675,8 +708,11 @@ function mail_notify_attn(Profile $rcpt, Notice $notice)
common_switch_locale($user->language);
if ($notice->hasConversation()) {
$conversationUrl = common_local_url('conversation',
array('id' => $notice->conversation)).'#notice-'.$notice->getID();
$conversationUrl = common_local_url(
'conversation',
['id' => $notice->conversation]
) . '#notice-'.$notice->getID();
// TRANS: Line in @-reply notification e-mail. %s is conversation URL.
$conversationEmailText = sprintf(_("The full conversation can be read here:\n\n".
"\t%s"), $conversationUrl) . "\n\n";
@ -688,32 +724,40 @@ function mail_notify_attn(Profile $rcpt, Notice $notice)
// TRANS: %1$s is the "fancy name" for a profile.
$subject = sprintf(_('%1$s sent a notice to your attention'), $sender->getFancyName());
// TRANS: Body of @-reply notification e-mail.
// TRANS: %1$s is the sending user's name, $2$s is the StatusNet sitename,
// TRANS: %3$s is a URL to the notice, %4$s is the notice text,
// TRANS: %5$s is the text "The full conversation can be read here:" and a URL to the full conversion if it exists (otherwise empty),
// TRANS: %6$s is a URL to reply to the notice, %7$s is a URL to all @-replies for the addressed user,
$body = sprintf(_("%1\$s just sent a notice to your attention (an '@-reply') on %2\$s.\n\n".
"The notice is here:\n\n".
"\t%3\$s\n\n" .
"It reads:\n\n".
"\t%4\$s\n\n" .
"%5\$s" .
"You can reply back here:\n\n".
"\t%6\$s\n\n" .
"The list of all @-replies for you here:\n\n" .
"%7\$s"),
$sender->getFancyName(),//%1
common_config('site', 'name'),//%2
common_local_url('shownotice',
array('notice' => $notice->getID())),//%3
$notice->getContent(),//%4
$conversationEmailText,//%5
common_local_url('newnotice',
array('replyto' => $sender->getNickname(), 'inreplyto' => $notice->getID())),//%6
common_local_url('replies',
array('nickname' => $rcpt->getNickname()))) . //%7
mail_footer_block();
// TRANS: Body of @-reply notification e-mail.
// TRANS: %1$s is the sending user's name, $2$s is the GNU social sitename,
// TRANS: %3$s is a URL to the notice, %4$s is the notice text,
// TRANS: %5$s is the text "The full conversation can be read here:" and a URL to the full conversion if it exists (otherwise empty),
// TRANS: %6$s is a URL to reply to the notice, %7$s is a URL to all @-replies for the addressed user,
$body = sprintf(
_("%1\$s just sent a notice to your attention (an '@-reply') on %2\$s.\n\n".
"The notice is here:\n\n".
"\t%3\$s\n\n" .
"It reads:\n\n".
"\t%4\$s\n\n" .
"%5\$s" .
"You can reply back here:\n\n".
"\t%6\$s\n\n" .
"The list of all @-replies for you here:\n\n" .
"%7\$s"),
$sender->getFancyName(), //%1
common_config('site', 'name'), //%2
common_local_url(
'shownotice',
['notice' => $notice->getID()]
), //%3
$notice->getContent(), //%4
$conversationEmailText, //%5
common_local_url(
'newnotice',
['replyto' => $sender->getNickname(), 'inreplyto' => $notice->getID()]
), //%6
common_local_url(
'replies',
['nickname' => $rcpt->getNickname()]
)
) . //%7
mail_footer_block();
$headers = _mail_prepare_headers('mention', $rcpt->getNickname(), $sender->getNickname());
common_switch_locale();
@ -764,20 +808,23 @@ function mail_notify_group_join($group, $joiner)
$headers['To'] = $admin->getBestName() . ' <' . $adminUser->email . '>';
// TRANS: Subject of group join notification e-mail.
// TRANS: %1$s is the joining user's nickname, %2$s is the group name, and %3$s is the StatusNet sitename.
$headers['Subject'] = sprintf(_('%1$s has joined '.
'your group %2$s on %3$s'),
$joiner->getBestName(),
$group->getBestName(),
common_config('site', 'name'));
$headers['Subject'] = sprintf(
_('%1$s has joined your group %2$s on %3$s'),
$joiner->getBestName(),
$group->getBestName(),
common_config('site', 'name')
);
// TRANS: Main body of group join notification e-mail.
// TRANS: %1$s is the subscriber's long name, %2$s is the group name, and %3$s is the StatusNet sitename,
// TRANS: %4$s is a block of profile info about the subscriber.
// TRANS: %5$s is a link to the addressed user's e-mail settings.
$body = sprintf(_('%1$s has joined your group %2$s on %3$s.'),
$joiner->getFancyName(),
$group->getFancyName(),
common_config('site', 'name')) .
$body = sprintf(
_('%1$s has joined your group %2$s on %3$s.'),
$joiner->getFancyName(),
$group->getFancyName(),
common_config('site', 'name')
) .
mail_profile_block($joiner) .
mail_footer_block();
@ -811,20 +858,24 @@ function mail_notify_group_join_pending($group, $joiner)
$headers['To'] = $admin->getBestName() . ' <' . $adminUser->email . '>';
// TRANS: Subject of pending group join request notification e-mail.
// TRANS: %1$s is the joining user's nickname, %2$s is the group name, and %3$s is the StatusNet sitename.
$headers['Subject'] = sprintf(_('%1$s wants to join your group %2$s on %3$s.'),
$joiner->getBestName(),
$group->getBestName(),
common_config('site', 'name'));
$headers['Subject'] = sprintf(
_('%1$s wants to join your group %2$s on %3$s.'),
$joiner->getBestName(),
$group->getBestName(),
common_config('site', 'name')
);
// TRANS: Main body of pending group join request notification e-mail.
// TRANS: %1$s is the subscriber's long name, %2$s is the group name, and %3$s is the StatusNet sitename,
// TRANS: %4$s is the URL to the moderation queue page.
$body = sprintf(_('%1$s would like to join your group %2$s on %3$s. ' .
'You may approve or reject their group membership at %4$s'),
$joiner->getFancyName(),
$group->getFancyName(),
common_config('site', 'name'),
common_local_url('groupqueue', array('nickname' => $group->nickname))) .
$body = sprintf(
_('%1$s would like to join your group %2$s on %3$s. ' .
'You may approve or reject their group membership at %4$s'),
$joiner->getFancyName(),
$group->getFancyName(),
common_config('site', 'name'),
common_local_url('groupqueue', ['nickname' => $group->nickname])
) .
mail_profile_block($joiner) .
mail_footer_block();

View File

@ -1,21 +1,20 @@
<?php
/*
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2010, StatusNet, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
defined('GNUSOCIAL') || die();
/**
* Base class for daemon that can launch one or more processing threads,
@ -24,7 +23,7 @@
* This is mainly intended for indefinite workloads such as monitoring
* a queue or maintaining an IM channel.
*
* Child classes should implement the
* Child classes should implement the
*
* We can then pass individual items through the QueueHandler subclasses
* they belong to. We additionally can handle queues for multiple sites.
@ -34,14 +33,14 @@
*/
abstract class SpawningDaemon extends Daemon
{
protected $threads=1;
protected $threads = 1;
const EXIT_OK = 0;
const EXIT_ERR = 1;
const EXIT_SHUTDOWN = 100;
const EXIT_RESTART = 101;
function __construct($id=null, $daemonize=true, $threads=1)
public function __construct($id = null, $daemonize = true, $threads = 1)
{
parent::__construct($daemonize);
@ -56,7 +55,7 @@ abstract class SpawningDaemon extends Daemon
*
* @return int exit code; use self::EXIT_SHUTDOWN to request not to respawn.
*/
public abstract function runThread();
abstract public function runThread();
/**
* Spawn one or more background processes and let them start running.
@ -69,17 +68,17 @@ abstract class SpawningDaemon extends Daemon
* though ParallelizingDaemon is probably better for workloads
* that have forseeable endpoints.
*/
function run()
public function run()
{
$this->initPipes();
$children = array();
$children = [];
for ($i = 1; $i <= $this->threads; $i++) {
$pid = pcntl_fork();
if ($pid < 0) {
$this->log(LOG_ERR, "Couldn't fork for thread $i; aborting\n");
exit(1);
} else if ($pid == 0) {
} elseif ($pid === 0) {
$this->initAndRunChild($i);
} else {
$this->log(LOG_INFO, "Spawned thread $i as pid $pid");
@ -87,7 +86,7 @@ abstract class SpawningDaemon extends Daemon
}
sleep(common_config('queue', 'spawndelay'));
}
$this->log(LOG_INFO, "Waiting for children to complete.");
while (count($children) > 0) {
$status = null;
@ -101,7 +100,7 @@ abstract class SpawningDaemon extends Daemon
if (pcntl_wifexited($status)) {
$exitCode = pcntl_wexitstatus($status);
$info = "status $exitCode";
} else if (pcntl_wifsignaled($status)) {
} elseif (pcntl_wifsignaled($status)) {
$exitCode = self::EXIT_ERR;
$signal = pcntl_wtermsig($status);
$info = "signal $signal";
@ -114,7 +113,7 @@ abstract class SpawningDaemon extends Daemon
$pid = pcntl_fork();
if ($pid < 0) {
$this->log(LOG_ERR, "Couldn't fork to respawn thread $i; aborting thread.\n");
} else if ($pid == 0) {
} elseif ($pid === 0) {
$this->initAndRunChild($i);
} else {
$this->log(LOG_INFO, "Respawned thread $i as pid $pid");
@ -134,7 +133,7 @@ abstract class SpawningDaemon extends Daemon
* Create an IPC socket pair which child processes can use to detect
* if the parent process has been killed.
*/
function initPipes()
public function initPipes()
{
$sockets = stream_socket_pair(STREAM_PF_UNIX, STREAM_SOCK_STREAM, 0);
if ($sockets) {
@ -197,10 +196,19 @@ abstract class SpawningDaemon extends Daemon
*/
protected function resetDb()
{
// @fixme do we need to explicitly open the db too
// or is this implied?
global $_DB_DATAOBJECT;
unset($_DB_DATAOBJECT['CONNECTIONS']);
// Can't be called statically
$user = new User();
$conn = $user->getDatabaseConnection();
$conn->disconnect();
// Remove the disconnected connection from the list
foreach ($_DB_DATAOBJECT['CONNECTIONS'] as $k => $v) {
if ($v === $conn) {
unset($_DB_DATAOBJECT['CONNECTIONS'][$k]);
}
}
// Reconnect main memcached, or threads will stomp on
// each other and corrupt their requests.
@ -216,14 +224,13 @@ abstract class SpawningDaemon extends Daemon
}
}
function log($level, $msg)
public function log($level, $msg)
{
common_log($level, get_class($this) . ' ('. $this->get_id() .'): '.$msg);
}
function name()
public function name()
{
return strtolower(get_class($this).'.'.$this->get_id());
}
}

View File

@ -1,24 +1,23 @@
<?php
/*
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2008-2011, 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/>.
*/
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/* XXX: break up into separate modules (HTTP, user, files) */
defined('GNUSOCIAL') || die();
/**
* Show a server error.
*/
@ -52,12 +51,14 @@ function common_init_locale($language=null)
}
putenv('LANGUAGE='.$language);
putenv('LANG='.$language);
$ok = setlocale(LC_ALL,
$language . ".utf8",
$language . ".UTF8",
$language . ".utf-8",
$language . ".UTF-8",
$language);
$ok = setlocale(
LC_ALL,
$language . '.utf8',
$language . '.UTF8',
$language . '.utf-8',
$language . '.UTF-8',
$language
);
return $ok;
}
@ -356,12 +357,14 @@ function common_set_cookie($key, $value, $expiration=0)
} else {
$cookiepath = '/';
}
return setcookie($key,
$value,
$expiration,
$cookiepath,
$server,
GNUsocial::useHTTPS());
return setcookie(
$key,
$value,
$expiration,
$cookiepath,
$server,
GNUsocial::useHTTPS()
);
}
define('REMEMBERME', 'rememberme');
@ -592,7 +595,6 @@ function common_to_alphanumeric($str)
function common_purify($html, array $args=[])
{
$cfg = \HTMLPurifier_Config::createDefault();
/**
* rel values that should be avoided since they can be used to infer
@ -839,9 +841,10 @@ function common_find_mentions($text, Profile $sender, Notice $parent=null)
}
$tagged = $sender->getTaggedSubscribers($tag);
$url = common_local_url('showprofiletag',
['nickname' => $sender->getNickname(),
'tag' => $tag]);
$url = common_local_url(
'showprofiletag',
['nickname' => $sender->getNickname(), 'tag' => $tag]
);
$mentions[] = ['mentioned' => $tagged,
'type' => 'list',
@ -888,17 +891,21 @@ function common_find_mentions($text, Profile $sender, Notice $parent=null)
function common_find_mentions_raw($text, $preMention='@')
{
$tmatches = [];
preg_match_all('/^T (' . Nickname::DISPLAY_FMT . ') /',
$text,
$tmatches,
PREG_OFFSET_CAPTURE);
preg_match_all(
'/^T (' . Nickname::DISPLAY_FMT . ') /',
$text,
$tmatches,
PREG_OFFSET_CAPTURE
);
$atmatches = [];
// the regexp's "(?!\@)" makes sure it doesn't matches the single "@remote" in "@remote@server.com"
preg_match_all('/'.Nickname::BEFORE_MENTIONS.preg_quote($preMention, '/').'(' . Nickname::DISPLAY_FMT . ')\b(?!\@)/',
$text,
$atmatches,
PREG_OFFSET_CAPTURE);
preg_match_all(
'/' . Nickname::BEFORE_MENTIONS . preg_quote($preMention, '/') . '(' . Nickname::DISPLAY_FMT . ')\b(?!\@)/',
$text,
$atmatches,
PREG_OFFSET_CAPTURE
);
$matches = array_merge($tmatches[1], $atmatches[1]);
return $matches;
@ -961,7 +968,8 @@ function common_url_schemes($filter = null)
$schemes,
function ($scheme) use ($filter) {
return is_null($filter) || ($scheme & $filter);
})
}
)
);
}
@ -1339,8 +1347,10 @@ function common_relative_profile($sender, $nickname, $dt=null)
// Try to find profiles this profile is subscribed to that have this nickname
$recipient = new Profile();
// XXX: use a join instead of a subquery
$recipient->whereAdd('EXISTS (SELECT subscribed from subscription where subscriber = '.intval($sender->id).' and subscribed = id)', 'AND');
$recipient->whereAdd(
sprintf('id IN (SELECT subscribed FROM subscription WHERE subscriber = %d)', $sender->id),
'AND'
);
$recipient->whereAdd("nickname = '" . $recipient->escape($nickname) . "'", 'AND');
if ($recipient->find(true)) {
// XXX: should probably differentiate between profiles with
@ -1349,8 +1359,10 @@ function common_relative_profile($sender, $nickname, $dt=null)
}
// Try to find profiles that listen to this profile and that have this nickname
$recipient = new Profile();
// XXX: use a join instead of a subquery
$recipient->whereAdd('EXISTS (SELECT subscriber from subscription where subscribed = '.intval($sender->id).' and subscriber = id)', 'AND');
$recipient->whereAdd(
sprintf('id IN (SELECT subscriber FROM subscription WHERE subscribed = %d)', $sender->id),
'AND'
);
$recipient->whereAdd("nickname = '" . $recipient->escape($nickname) . "'", 'AND');
if ($recipient->find(true)) {
// XXX: should probably differentiate between profiles with
@ -1701,11 +1713,13 @@ function common_enqueue_notice($notice)
function common_profile_url($nickname)
{
return common_local_url('showstream',
['nickname' => $nickname],
null,
null,
false);
return common_local_url(
'showstream',
['nickname' => $nickname],
null,
null,
false
);
}
/**
@ -2210,11 +2224,13 @@ function common_remove_magic_from_request()
function common_user_uri(&$user)
{
return common_local_url('userbyid',
['id' => $user->id],
null,
null,
false);
return common_local_url(
'userbyid',
['id' => $user->id],
null,
null,
false
);
}
/**
@ -2225,11 +2241,12 @@ function common_user_uri(&$user)
* alphanums and remove lookalikes (0, O, 1, I) = 32 chars = 5 bits to make it easy for the user to type in
* @return string confirmation_code of length $bits/5
*/
function common_confirmation_code($bits, $codechars = '23456789ABCDEFGHJKLMNPQRSTUVWXYZ') {
function common_confirmation_code($bits, $codechars = '23456789ABCDEFGHJKLMNPQRSTUVWXYZ')
{
$chars = ceil($bits/5);
$codechars_length = strlen($codechars)-1;
$code = '';
for($i = 0; $i < $chars; ++$i) {
for ($i = 0; $i < $chars; ++$i) {
$random_char = $codechars[random_int(0, $codechars_length)];
$code .= $random_char;
}
@ -2403,15 +2420,13 @@ function common_compatible_license($from, $to)
}
/**
* returns a quoted table name, if required according to config
* returns a quoted table name
*/
function common_database_tablename($tablename)
{
if (common_config('db', 'quote_identifiers')) {
$tablename = '"'. $tablename .'"';
}
//table prefixes could be added here later
return $tablename;
$schema = Schema::get();
// table prefixes could be added here later
return $schema->quoteIdentifier($tablename);
}
/**
@ -2692,10 +2707,13 @@ function _common_size_str_to_int($size): int
*
* @return int
*/
function common_get_preferred_php_upload_limit(): int {
return min(_common_size_str_to_int(ini_get('post_max_size')),
_common_size_str_to_int(ini_get('upload_max_filesize')),
_common_size_str_to_int(ini_get('memory_limit')));
function common_get_preferred_php_upload_limit(): int
{
return min(
_common_size_str_to_int(ini_get('post_max_size')),
_common_size_str_to_int(ini_get('upload_max_filesize')),
_common_size_str_to_int(ini_get('memory_limit'))
);
}
function html_sprintf()

View File

@ -1,28 +1,28 @@
<?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/>.
*/
if (!defined('GNUSOCIAL')) { exit(1); }
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* @package Activity
* @maintainer Mikael Nordfeldth <mmn@hethane.se>
* @package Favorite
* @author Mikael Nordfeldth <mmn@hethane.se>
* @copyright 2014 Free Software Foundation, Inc http://www.fsf.org
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
defined('GNUSOCIAL') || die();
class FavoriteModule extends ActivityVerbHandlerModule
{
const PLUGIN_VERSION = '2.0.0';
@ -93,15 +93,14 @@ class FavoriteModule extends ActivityVerbHandlerModule
while ($fave->fetch()) {
try {
$fave->decache();
$fave->query(sprintf('UPDATE fave '.
'SET uri = "%s", '.
' modified = "%s" '.
'WHERE user_id = %d '.
'AND notice_id = %d',
Fave::newUri($fave->getActor(), $fave->getTarget(), $fave->modified),
common_sql_date(strtotime($fave->modified)),
$fave->user_id,
$fave->notice_id));
$fave->query(sprintf(
"UPDATE fave SET uri = '%s', modified = TIMESTAMP '%s' " .
'WHERE user_id = %d AND notice_id = %d',
Fave::newUri($fave->getActor(), $fave->getTarget(), $fave->modified),
common_sql_date(strtotime($fave->modified)),
$fave->user_id,
$fave->notice_id
));
} catch (Exception $e) {
common_log(LOG_ERR, "Error updating fave URI: " . $e->getMessage());
}
@ -114,77 +113,129 @@ class FavoriteModule extends ActivityVerbHandlerModule
public function onRouterInitialized(URLMapper $m)
{
// Web UI actions
$m->connect('main/favor',
['action' => 'favor']);
$m->connect('main/disfavor',
['action' => 'disfavor']);
$m->connect(
'main/favor',
['action' => 'favor']
);
$m->connect(
'main/disfavor',
['action' => 'disfavor']
);
if (common_config('singleuser', 'enabled')) {
$nickname = User::singleUserNickname();
$m->connect('favorites',
['action' => 'showfavorites',
'nickname' => $nickname]);
$m->connect('favoritesrss',
['action' => 'favoritesrss',
'nickname' => $nickname]);
$m->connect(
'favorites',
[
'action' => 'showfavorites',
'nickname' => $nickname,
]
);
$m->connect(
'favoritesrss',
[
'action' => 'favoritesrss',
'nickname' => $nickname,
]
);
} else {
$m->connect('favoritedrss',
['action' => 'favoritedrss']);
$m->connect('favorited/',
['action' => 'favorited']);
$m->connect('favorited',
['action' => 'favorited']);
$m->connect(
'favoritedrss',
['action' => 'favoritedrss']
);
$m->connect(
'favorited/',
['action' => 'favorited']
);
$m->connect(
'favorited',
['action' => 'favorited']
);
$m->connect(':nickname/favorites',
['action' => 'showfavorites'],
['nickname' => Nickname::DISPLAY_FMT]);
$m->connect(':nickname/favorites/rss',
['action' => 'favoritesrss'],
['nickname' => Nickname::DISPLAY_FMT]);
$m->connect(
':nickname/favorites',
['action' => 'showfavorites'],
['nickname' => Nickname::DISPLAY_FMT]
);
$m->connect(
':nickname/favorites/rss',
['action' => 'favoritesrss'],
['nickname' => Nickname::DISPLAY_FMT]
);
}
// Favorites for API
$m->connect('api/favorites/create.:format',
['action' => 'ApiFavoriteCreate'],
['format' => '(xml|json)']);
$m->connect('api/favorites/destroy.:format',
['action' => 'ApiFavoriteDestroy'],
['format' => '(xml|json)']);
$m->connect('api/favorites/list.:format',
['action' => 'ApiTimelineFavorites'],
['format' => '(xml|json|rss|atom|as)']);
$m->connect('api/favorites/:id.:format',
['action' => 'ApiTimelineFavorites'],
['id' => Nickname::INPUT_FMT,
'format' => '(xml|json|rss|atom|as)']);
$m->connect('api/favorites.:format',
['action' => 'ApiTimelineFavorites'],
['format' => '(xml|json|rss|atom|as)']);
$m->connect('api/favorites/create/:id.:format',
['action' => 'ApiFavoriteCreate'],
['id' => '[0-9]+',
'format' => '(xml|json)']);
$m->connect('api/favorites/destroy/:id.:format',
['action' => 'ApiFavoriteDestroy'],
['id' => '[0-9]+',
'format' => '(xml|json)']);
$m->connect(
'api/favorites/create.:format',
['action' => 'ApiFavoriteCreate'],
['format' => '(xml|json)']
);
$m->connect(
'api/favorites/destroy.:format',
['action' => 'ApiFavoriteDestroy'],
['format' => '(xml|json)']
);
$m->connect(
'api/favorites/list.:format',
['action' => 'ApiTimelineFavorites'],
['format' => '(xml|json|rss|atom|as)']
);
$m->connect(
'api/favorites/:id.:format',
['action' => 'ApiTimelineFavorites'],
[
'id' => Nickname::INPUT_FMT,
'format' => '(xml|json|rss|atom|as)',
]
);
$m->connect(
'api/favorites.:format',
['action' => 'ApiTimelineFavorites'],
['format' => '(xml|json|rss|atom|as)']
);
$m->connect(
'api/favorites/create/:id.:format',
['action' => 'ApiFavoriteCreate'],
[
'id' => '[0-9]+',
'format' => '(xml|json)',
]
);
$m->connect(
'api/favorites/destroy/:id.:format',
['action' => 'ApiFavoriteDestroy'],
[
'id' => '[0-9]+',
'format' => '(xml|json)',
]
);
// AtomPub API
$m->connect('api/statusnet/app/favorites/:profile/:notice.atom',
['action' => 'AtomPubShowFavorite'],
['profile' => '[0-9]+',
'notice' => '[0-9]+']);
$m->connect(
'api/statusnet/app/favorites/:profile/:notice.atom',
['action' => 'AtomPubShowFavorite'],
[
'profile' => '[0-9]+',
'notice' => '[0-9]+',
]
);
$m->connect('api/statusnet/app/favorites/:profile.atom',
['action' => 'AtomPubFavoriteFeed'],
['profile' => '[0-9]+']);
$m->connect(
'api/statusnet/app/favorites/:profile.atom',
['action' => 'AtomPubFavoriteFeed'],
['profile' => '[0-9]+']
);
// Required for qvitter API
$m->connect('api/statuses/favs/:id.:format',
['action' => 'ApiStatusesFavs'],
['id' => '[0-9]+',
'format' => '(xml|json)']);
$m->connect(
'api/statuses/favs/:id.:format',
['action' => 'ApiStatusesFavs'],
[
'id' => '[0-9]+',
'format' => '(xml|json)',
]
);
}
// FIXME: Set this to abstract public in lib/modules/ActivityHandlerPlugin.php when all plugins have migrated!
@ -443,10 +494,12 @@ class FavoriteModule extends ActivityVerbHandlerModule
$emailfave = $scoped->getConfigPref('email', 'notify_fave') ? 1 : 0;
$action->elementStart('li');
$action->checkbox('email-notify_fave',
// TRANS: Checkbox label in e-mail preferences form.
_('Send me email when someone adds my notice as a favorite.'),
$emailfave);
$action->checkbox(
'email-notify_fave',
// TRANS: Checkbox label in e-mail preferences form.
_('Send me email when someone adds my notice as a favorite.'),
$emailfave
);
$action->elementEnd('li');
return true;
@ -454,9 +507,9 @@ class FavoriteModule extends ActivityVerbHandlerModule
public function onStartEmailSaveForm(Action $action, Profile $scoped)
{
$emailfave = $action->booleanintstring('email-notify_fave');
$emailfave = $action->boolean('email-notify_fave');
try {
if ($emailfave == $scoped->getPref('email', 'notify_fave')) {
if ($emailfave == (bool) $scoped->getPref('email', 'notify_fave')) {
// No need to update setting
return true;
}
@ -473,24 +526,31 @@ class FavoriteModule extends ActivityVerbHandlerModule
public function onEndPersonalGroupNav(Menu $menu, Profile $target, Profile $scoped=null)
{
$menu->out->menuItem(common_local_url('showfavorites', array('nickname' => $target->getNickname())),
// TRANS: Menu item in personal group navigation menu.
_m('MENU','Favorites'),
// @todo i18n FIXME: Need to make this two messages.
// TRANS: Menu item title in personal group navigation menu.
// TRANS: %s is a username.
sprintf(_('%s\'s favorite notices'), $target->getBestName()),
$scoped instanceof Profile && $target->id === $scoped->id && $menu->actionName =='showfavorites',
'nav_timeline_favorites');
$menu->out->menuItem(
common_local_url('showfavorites', ['nickname' => $target->getNickname()]),
// TRANS: Menu item in personal group navigation menu.
_m('MENU', 'Favorites'),
// @todo i18n FIXME: Need to make this two messages.
// TRANS: Menu item title in personal group navigation menu.
// TRANS: %s is a username.
sprintf(_('%s\'s favorite notices'), $target->getBestName()),
($scoped instanceof Profile && $target->id === $scoped->id && $menu->actionName === 'showfavorites'),
'nav_timeline_favorites'
);
}
public function onEndPublicGroupNav(Menu $menu)
{
if (!common_config('singleuser', 'enabled')) {
// TRANS: Menu item in search group navigation panel.
$menu->out->menuItem(common_local_url('favorited'), _m('MENU','Popular'),
// TRANS: Menu item title in search group navigation panel.
_('Popular notices'), $menu->actionName == 'favorited', 'nav_timeline_favorited');
$menu->out->menuItem(
common_local_url('favorited'),
_m('MENU', 'Popular'),
// TRANS: Menu item title in search group navigation panel.
_('Popular notices'),
($menu->actionName === 'favorited'),
'nav_timeline_favorited'
);
}
}
@ -519,7 +579,7 @@ class FavoriteModule extends ActivityVerbHandlerModule
{
if ($action->isPost()) {
// The below tests are only for presenting to the user. POSTs which inflict
// duplicate favorite entries are handled with AlreadyFulfilledException.
// duplicate favorite entries are handled with AlreadyFulfilledException.
return false;
}
@ -529,9 +589,13 @@ class FavoriteModule extends ActivityVerbHandlerModule
switch (true) {
case $exists && ActivityUtils::compareVerbs($verb, array(ActivityVerb::FAVORITE, ActivityVerb::LIKE)):
case !$exists && ActivityUtils::compareVerbs($verb, array(ActivityVerb::UNFAVORITE, ActivityVerb::UNLIKE)):
common_redirect(common_local_url('activityverb',
array('id' => $target->getID(),
'verb' => ActivityUtils::resolveUri($expected_verb, true))));
common_redirect(common_local_url(
'activityverb',
[
'id' => $target->getID(),
'verb' => ActivityUtils::resolveUri($expected_verb, true),
]
));
break;
default:
// No need to redirect as we are on the correct action already.
@ -617,23 +681,23 @@ function mail_notify_fave(User $rcpt, Profile $sender, Notice $notice)
// TRANS: %3$s is a URL to the faved notice, %4$s is the faved notice text,
// TRANS: %5$s is a URL to all faves of the adding user, %6$s is the StatusNet sitename,
// TRANS: %7$s is the adding user's nickname.
$body = sprintf(_("%1\$s (@%7\$s) just added your notice from %2\$s".
" as one of their favorites.\n\n" .
"The URL of your notice is:\n\n" .
"%3\$s\n\n" .
"The text of your notice is:\n\n" .
"%4\$s\n\n" .
"You can see the list of %1\$s's favorites here:\n\n" .
"%5\$s"),
$bestname,
common_exact_date($notice->created),
common_local_url('shownotice',
array('notice' => $notice->id)),
$notice->content,
common_local_url('showfavorites',
array('nickname' => $sender->getNickname())),
common_config('site', 'name'),
$sender->getNickname()) .
$body = sprintf(
_("%1\$s (@%7\$s) just added your notice from %2\$s".
" as one of their favorites.\n\n" .
"The URL of your notice is:\n\n" .
"%3\$s\n\n" .
"The text of your notice is:\n\n" .
"%4\$s\n\n" .
"You can see the list of %1\$s's favorites here:\n\n" .
"%5\$s"),
$bestname,
common_exact_date($notice->created),
common_local_url('shownotice', ['notice' => $notice->id]),
$notice->content,
common_local_url('showfavorites', ['nickname' => $sender->getNickname()]),
common_config('site', 'name'),
$sender->getNickname()
) .
mail_footer_block();
$headers = _mail_prepare_headers('fave', $rcpt->getNickname(), $sender->getNickname());

View File

@ -1,48 +1,43 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2011, StatusNet, Inc.
*
* Notice stream for favorites
*
* 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
* @package GNUsocial
* @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/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('GNUSOCIAL')) { exit(1); }
defined('GNUSOCIAL') || die();
/**
* Notice stream for favorites
*
* @category Stream
* @package StatusNet
* @package GNUsocial
* @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/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
class FaveNoticeStream extends ScopingNoticeStream
{
function __construct(Profile $target, Profile $scoped=null)
public function __construct(Profile $target, Profile $scoped = null)
{
$stream = new RawFaveNoticeStream($target, $scoped);
if ($target->sameAs($scoped)) {
@ -58,11 +53,10 @@ class FaveNoticeStream extends ScopingNoticeStream
* Raw notice stream for favorites
*
* @category Stream
* @package StatusNet
* @package GNUsocial
* @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/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
class RawFaveNoticeStream extends NoticeStream
{
@ -71,7 +65,7 @@ class RawFaveNoticeStream extends NoticeStream
protected $selectVerbs = array();
function __construct(Profile $target, Profile $scoped=null)
public function __construct(Profile $target, Profile $scoped = null)
{
parent::__construct();
@ -92,7 +86,7 @@ class RawFaveNoticeStream extends NoticeStream
* @param <type> $max_id
* @return <type>
*/
function getNoticeIds($offset, $limit, $since_id, $max_id)
public function getNoticeIds($offset, $limit, $since_id, $max_id)
{
$fav = new Fave();
$qry = null;
@ -101,10 +95,10 @@ class RawFaveNoticeStream extends NoticeStream
$qry = 'SELECT fave.* FROM fave ';
$qry .= 'WHERE fave.user_id = ' . $this->user_id . ' ';
} else {
$qry = 'SELECT fave.* FROM fave ';
$qry .= 'INNER JOIN notice ON fave.notice_id = notice.id ';
$qry .= 'WHERE fave.user_id = ' . $this->user_id . ' ';
$qry .= 'AND notice.is_local != ' . Notice::GATEWAY . ' ';
$qry = 'SELECT fave.* FROM fave ';
$qry .= 'INNER JOIN notice ON fave.notice_id = notice.id ';
$qry .= 'WHERE fave.user_id = ' . $this->user_id . ' ';
$qry .= 'AND notice.is_local <> ' . Notice::GATEWAY . ' ';
}
if ($since_id != 0) {
@ -137,4 +131,3 @@ class RawFaveNoticeStream extends NoticeStream
return $ids;
}
}

View File

@ -51,9 +51,9 @@ class Activitypub_pending_follow_requests extends Managed_DataObject
{
return [
'fields' => [
'local_profile_id' => ['type' => 'integer', 'not null' => true],
'remote_profile_id' => ['type' => 'integer', 'not null' => true],
'relation_id' => ['type' => 'serial', 'not null' => true],
'local_profile_id' => ['type' => 'int', 'not null' => true],
'remote_profile_id' => ['type' => 'int', 'not null' => true],
'relation_id' => ['type' => 'serial', 'not null' => true],
],
'primary key' => ['relation_id'],
'foreign keys' => [

View File

@ -61,7 +61,7 @@ class Activitypub_profile extends Managed_DataObject
return [
'fields' => [
'uri' => ['type' => 'text', 'not null' => true],
'profile_id' => ['type' => 'integer'],
'profile_id' => ['type' => 'int', 'not null' => true],
'inboxuri' => ['type' => 'text', 'not null' => true],
'sharedInboxuri' => ['type' => 'text'],
'created' => ['type' => 'datetime', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was created'],

View File

@ -53,7 +53,7 @@ class Activitypub_rsa extends Managed_DataObject
{
return [
'fields' => [
'profile_id' => ['type' => 'integer'],
'profile_id' => ['type' => 'int', 'not null' => true],
'private_key' => ['type' => 'text'],
'public_key' => ['type' => 'text', 'not null' => true],
'created' => ['type' => 'datetime', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was created'],

View File

@ -1,47 +1,38 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2011, StatusNet, Inc.
*
* Score of a notice by activity spam service
*
* 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 Spam
* @package StatusNet
* @package GNUsocial
* @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/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('STATUSNET')) {
exit(1);
}
defined('GNUSOCIAL') || die();
/**
* Score of a notice per the activity spam service
*
* @category Spam
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/
* @copyright 2011 StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*
* @see DB_DataObject
* @see DB_DataObject
*/
class Spam_score extends Managed_DataObject
{
@ -54,7 +45,6 @@ class Spam_score extends Managed_DataObject
public static function save($notice, $result)
{
$orig = null;
$score = Spam_score::getKV('notice_id', $notice->id);
@ -93,12 +83,13 @@ class Spam_score extends Managed_DataObject
'notice_id' => array('type' => 'int',
'not null' => true,
'description' => 'notice getting scored'),
'score' => array('type' => 'double',
'score' => array('type' => 'float',
'size' => 'big',
'not null' => true,
'description' => 'score for the notice (0.0, 1.0)'),
'scaled' => array('type' => 'int',
'description' => 'scaled score for the notice (0, 10000)'),
'is_spam' => array('type' => 'tinyint',
'is_spam' => array('type' => 'bool',
'description' => 'flag for spamosity'),
'created' => array('type' => 'datetime',
'not null' => true,
@ -146,7 +137,7 @@ class Spam_score extends Managed_DataObject
if ($score->find()) {
while ($score->fetch()) {
$orig = clone($score);
$score->is_spam = ($score->score >= 0.90) ? 1 : 0;
$score->is_spam = ($score->score >= 0.90) ? true : false;
$score->update($orig);
}
}
@ -169,9 +160,8 @@ class Spam_score extends Managed_DataObject
}
}
function saveNew($notice, $result)
public function saveNew($notice, $result)
{
$score = new Spam_score();
$score->notice_id = $notice->id;

View File

@ -1,52 +1,45 @@
<?php
/**
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2012, StatusNet, Inc.
*
* Spam notice stream
*
* 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 Spam
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2012 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
if (!defined('GNUSOCIAL')) { exit(1); }
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* Spam notice stream
*
* @category Spam
* @package StatusNet
* @package GNUsocial
* @author Evan Prodromou <evan@status.net>
* @copyright 2012 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
defined('GNUSOCIAL') || die();
/**
* Spam notice stream
*
* @copyright 2012 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
*/
class SpamNoticeStream extends ScopingNoticeStream
{
function __construct(Profile $scoped=null)
public function __construct(Profile $scoped = null)
{
parent::__construct(new CachingNoticeStream(new RawSpamNoticeStream(), 'spam_score:notice_ids'),
$scoped);
parent::__construct(
new CachingNoticeStream(new RawSpamNoticeStream(), 'spam_score:notice_ids'),
$scoped
);
}
}
@ -54,20 +47,16 @@ class SpamNoticeStream extends ScopingNoticeStream
* Raw stream of spammy notices
*
* @category Stream
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2011 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
class RawSpamNoticeStream extends NoticeStream
{
function getNoticeIds($offset, $limit, $since_id, $max_id)
public function getNoticeIds($offset, $limit, $since_id, $max_id)
{
$ss = new Spam_score();
$ss->is_spam = 1;
$ss->is_spam = true;
$ss->selectAdd();
$ss->selectAdd('notice_id');

View File

@ -1,20 +1,22 @@
<?php
/*
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2013 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/>.
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* @copyright 2013 StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
define('INSTALLDIR', realpath(dirname(__FILE__) . '/../../..'));
@ -33,13 +35,13 @@ END_OF_SILENCESPAMMER_HELP;
require_once INSTALLDIR.'/scripts/commandline.inc';
function testAllUsers($filter, $minimum, $percent) {
function testAllUsers($filter, $minimum, $percent)
{
$found = false;
$offset = 0;
$limit = 1000;
do {
$user = new User();
$user->orderBy('created');
$user->limit($offset, $limit);
@ -56,37 +58,36 @@ function testAllUsers($filter, $minimum, $percent) {
}
$offset += $found;
}
} while ($found > 0);
}
function silencespammer($filter, $user, $minimum, $percent) {
function silencespammer($filter, $user, $minimum, $percent)
{
printfnq("Testing user %s\n", $user->nickname);
$profile = Profile::getKV('id', $user->id);
if ($profile->isSilenced()) {
printfnq("Already silenced %s\n", $user->nickname);
return;
printfnq("Already silenced %s\n", $user->nickname);
return;
}
$cnt = $profile->noticeCount();
if ($cnt < $minimum) {
printfnq("Only %d notices posted (minimum %d); skipping\n", $cnt, $minimum);
return;
return;
}
$ss = new Spam_score();
$ss->query(sprintf("SELECT count(*) as spam_count ".
"FROM notice join spam_score on notice.id = spam_score.notice_id ".
"WHERE notice.profile_id = %d AND spam_score.is_spam = 1", $profile->id));
'WHERE notice.profile_id = %d AND spam_score.is_spam = TRUE', $profile->id));
while ($ss->fetch()) {
$spam_count = $ss->spam_count;
}
}
$spam_percent = ($spam_count * 100.0 / $cnt);
@ -94,10 +95,10 @@ function silencespammer($filter, $user, $minimum, $percent) {
printfnq("Silencing user %s (%d/%d = %0.2f%% spam)\n", $user->nickname, $spam_count, $cnt, $spam_percent);
try {
$profile->silence();
} catch(Exception $e) {
} catch (Exception $e) {
printfnq("Error: %s", $e->getMessage());
}
}
}
}
}
try {

View File

@ -1,33 +1,32 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* StatusNet, the distributed open-source microblogging tool
*
* Simple-minded queue manager for storing items in the database
*
* PHP version 5
*
* LICENCE: This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category QueueManager
* @package StatusNet
* @package GNUsocial
* @author Evan Prodromou <evan@status.net>
* @author Brion Vibber <brion@status.net>
* @copyright 2009-2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
defined('GNUSOCIAL') || die();
class DBQueueManager extends QueueManager
{
/**
@ -39,7 +38,7 @@ class DBQueueManager extends QueueManager
{
$qi = new Queue_item();
$qi->frame = $this->encode($object);
$qi->frame = DB_DataObject_Cast::blob($this->encode($object));
$qi->transport = $queue;
$qi->created = common_sql_now();
$result = $qi->insert();
@ -121,7 +120,8 @@ class DBQueueManager extends QueueManager
// What to do if no handler was found. For example, the OpportunisticQM
// should avoid deleting items just because it can't reach XMPP queues etc.
protected function noHandlerFound(Queue_item $qi, $rep=null) {
protected function noHandlerFound(Queue_item $qi, $rep = null)
{
$this->_log(LOG_INFO, "[{$qi->transport}:{$rep}] No handler for queue {$qi->transport}; discarding.");
$this->_done($qi);
}

View File

@ -1,31 +1,31 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2011, StatusNet, Inc.
*
* Data class for email reminders
*
* 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 EmailReminder
* @author Zach Copley <zach@status.net>
* @copyright 2011 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
defined('GNUSOCIAL') || die();
class Email_reminder extends Managed_DataObject
{
public $__table = 'email_reminder';
@ -46,8 +46,8 @@ class Email_reminder extends Managed_DataObject
* @param int $days Number of days after the code was created
* @return boolean true if any Email_reminder records were found
*/
static function needsReminder($type, $object, $days = null) {
public static function needsReminder($type, $object, $days = null)
{
$reminder = new Email_reminder();
$reminder->type = $type;
$reminder->code = $object->code;
@ -72,8 +72,8 @@ class Email_reminder extends Managed_DataObject
* @param int $days Number of days after the code was created
* @return int $result row ID of the new reminder record
*/
static function recordReminder($type, $object, $days) {
public static function recordReminder($type, $object, $days)
{
$reminder = new Email_reminder();
$reminder->type = $type;
$reminder->code = $object->code;
@ -83,9 +83,9 @@ class Email_reminder extends Managed_DataObject
if (empty($result)) {
common_log_db_error($reminder, 'INSERT', __FILE__);
throw new ServerException(
// TRANS: Server exception thrown when a reminder record could not be inserted into the database.
_m('Database error inserting reminder record.')
throw new ServerException(
// TRANS: Server exception thrown when a reminder record could not be inserted into the database.
_m('Database error inserting reminder record.')
);
}
@ -108,13 +108,13 @@ class Email_reminder extends Managed_DataObject
),
'code' => array(
'type' => 'varchar',
'not null' => 'true',
'not null' => true,
'length' => 191,
'description' => 'confirmation code'
),
'days' => array(
'type' => 'int',
'not null' => 'true',
'not null' => true,
'description' => 'number of days since code creation'
),
'sent' => array(

View File

@ -1,45 +1,38 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/*
* StatusNet - the distributed open-source microblogging tool
*
* Handler for reminder queue items which send reminder emails to all users
* we would like to complete a given process (e.g.: registration).
*
* 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 Email
* @package StatusNet
* @package GNUsocial
* @author Zach Copley <zach@status.net>
* @copyright 2011 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('STATUSNET')) {
exit(1);
}
defined('GNUSOCIAL') || die();
/**
* Handler for reminder queue items which send reminder emails to all users
* we would like to complete a given process (e.g.: registration)
*
* @category Email
* @package StatusNet
* @author Zach Copley <zach@status.net>
* @copyright 2011 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
class SiteConfirmReminderHandler extends QueueHandler
{
@ -52,7 +45,7 @@ class SiteConfirmReminderHandler extends QueueHandler
*
* @return string
*/
function transport()
public function transport()
{
return 'siterem';
}
@ -63,14 +56,14 @@ class SiteConfirmReminderHandler extends QueueHandler
* @param array $remitem type of reminder to send and any special options
* @return boolean true on success, false on failure
*/
function handle($remitem) : bool
public function handle($remitem): bool
{
list($type, $opts) = $remitem;
$qm = QueueManager::get();
try {
switch($type) {
switch ($type) {
case UserConfirmRegReminderHandler::REGISTER_REMINDER:
$confirm = new Confirm_address();
$confirm->address_type = $type;
@ -87,7 +80,11 @@ class SiteConfirmReminderHandler extends QueueHandler
case UserInviteReminderHandler::INVITE_REMINDER:
$invitation = new Invitation();
// Only send one reminder (the latest one), regardless of how many invitations a user has
$sql = 'SELECT * FROM (SELECT * FROM invitation WHERE registered_user_id IS NULL ORDER BY created DESC) invitees GROUP BY invitees.address';
$sql = 'SELECT * FROM invitation ' .
'WHERE (address, created) IN ' .
'(SELECT address, MAX(created) FROM invitation GROUP BY address) AND ' .
'registered_user_id IS NULL ' .
'ORDER BY created DESC';
$invitation->query($sql);
while ($invitation->fetch()) {
try {

View File

@ -1,35 +1,30 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* Data class for email summary status
*
* PHP version 5
*
* @category Data
* @package StatusNet
* @author Evan Prodromou <evan@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) 2010, StatusNet, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* @category Data
* @package GNUsocial
* @author Evan Prodromou <evan@status.net>
* @copyright 2010, StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('STATUSNET')) {
exit(1);
}
defined('GNUSOCIAL') || die();
require_once INSTALLDIR . '/classes/Memcached_DataObject.php';
@ -38,19 +33,17 @@ require_once INSTALLDIR . '/classes/Memcached_DataObject.php';
*
* Email summary information for users
*
* @category Action
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/
* @category Action
* @copyright 2010, StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*
* @see DB_DataObject
* @see DB_DataObject
*/
class Email_summary_status extends Managed_DataObject
{
public $__table = 'email_summary_status'; // table name
public $user_id; // int(4) primary_key not_null
public $send_summary; // tinyint not_null
public $send_summary; // bool not_null default_true
public $last_summary_id; // int(4) null
public $created; // datetime not_null
public $modified; // datetime not_null
@ -60,9 +53,9 @@ class Email_summary_status extends Managed_DataObject
return array(
'fields' => array(
'user_id' => array('type' => 'int', 'not null' => true, 'description' => 'user id'),
'send_summary' => array('type' => 'int', 'size' => 'tiny', 'default' => 1, 'not null' => true, 'description' => 'whether to send a summary or not'),
'send_summary' => array('type' => 'bool', 'default' => true, 'not null' => true, 'description' => 'whether to send a summary or not'),
'last_summary_id' => array('type' => 'int', 'description' => 'last summary id'),
'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
'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('user_id'),
@ -79,7 +72,7 @@ class Email_summary_status extends Managed_DataObject
*
* @return int flag for whether to send this user a summary email
*/
static function getSendSummary($user_id)
public static function getSendSummary($user_id)
{
$ess = Email_summary_status::getKV('user_id', $user_id);
@ -97,7 +90,7 @@ class Email_summary_status extends Managed_DataObject
*
* @return Email_summary_status instance for this user, with count already incremented.
*/
static function getLastSummaryID($user_id)
public static function getLastSummaryID($user_id)
{
$ess = Email_summary_status::getKV('user_id', $user_id);

View File

@ -94,8 +94,10 @@ class Happening extends Managed_DataObject
'unique keys' => array(
'happening_uri_key' => array('uri'),
),
'foreign keys' => array('happening_profile_id__key' => array('profile', array('profile_id' => 'id')),
'happening_uri__key' => array('notice', array('uri' => 'uri'))),
'foreign keys' => array(
'happening_profile_id_fkey' => array('profile', array('profile_id' => 'id')),
'happening_uri_fkey' => array('notice', array('uri' => 'uri'))
),
'indexes' => array('happening_created_idx' => array('created'),
'happening_start_end_idx' => array('start_time', 'end_time')),
);

View File

@ -85,8 +85,10 @@ class RSVP extends Managed_DataObject
'rsvp_uri_key' => array('uri'),
'rsvp_profile_event_key' => array('profile_id', 'event_uri'),
),
'foreign keys' => array('rsvp_event_uri_key' => array('happening', array('event_uri' => 'uri')),
'rsvp_profile_id__key' => array('profile', array('profile_id' => 'id'))),
'foreign keys' => array(
'rsvp_event_uri_fkey' => array('happening', array('event_uri' => 'uri')),
'rsvp_profile_id_fkey' => array('profile', array('profile_id' => 'id'))
),
'indexes' => array('rsvp_created_idx' => array('created')),
);
}

View File

@ -1,36 +1,30 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* StatusNet, the distributed open-source microblogging tool
*
* Action for showing Twitter-like JSON search results
*
* 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 Search
* @package StatusNet
* @package GNUsocial
* @author Zach Copley <zach@status.net>
* @copyright 2011 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('STATUSNET')) {
exit(1);
}
defined('GNUSOCIAL') || die();
class UserautocompleteAction extends Action
{
@ -44,7 +38,7 @@ class UserautocompleteAction extends Action
* @return boolean true if nothing goes wrong
* @throws ClientException
*/
public function prepare(array $args = array())
public function prepare(array $args = [])
{
parent::prepare($args);
$this->query = $this->trimmed('term');
@ -87,7 +81,7 @@ class UserautocompleteAction extends Action
. ' AND LEFT(LOWER(profile.nickname), '
. strlen($this->query)
. ') = \'%s\' '
. ' LIMIT 0, 10';
. ' LIMIT 10';
$profile->query(sprintf($sql, $this->query));
}

View File

@ -1,35 +1,30 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* Data class for counting greetings
*
* PHP version 5
*
* @category Data
* @package StatusNet
* @author Evan Prodromou <evan@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) 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/>.
* @category Data
* @package GNUsocial
* @author Evan Prodromou <evan@status.net>
* @copyright 2009, StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('STATUSNET')) {
exit(1);
}
defined('GNUSOCIAL') || die();
require_once INSTALLDIR . '/classes/Memcached_DataObject.php';
@ -44,19 +39,17 @@ require_once INSTALLDIR . '/classes/Memcached_DataObject.php';
* extension of DB_DataObject that provides caching, internationalization,
* and other bits of good functionality to StatusNet-specific data classes.
*
* @category Action
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/
* @category Action
* @copyright 2009, StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*
* @see DB_DataObject
* @see DB_DataObject
*/
class User_followeveryone_prefs extends Managed_DataObject
{
public $__table = 'user_followeveryone_prefs'; // table name
public $user_id; // int(4) primary_key not_null
public $followeveryone; // tinyint(1)
public $followeveryone; // bool default_true
public $created; // datetime() not_null
public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP
@ -65,7 +58,7 @@ class User_followeveryone_prefs extends Managed_DataObject
return array(
'fields' => array(
'user_id' => array('type' => 'int', 'not null' => true, 'description' => 'user id'),
'followeveryone' => array('type' => 'int', 'default' => 1, 'size' => 'tiny', 'description' => 'whether to follow everyone'),
'followeveryone' => array('type' => 'bool', 'default' => true, 'description' => 'whether to follow everyone'),
'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'),
),
@ -76,7 +69,7 @@ class User_followeveryone_prefs extends Managed_DataObject
);
}
static function followEveryone($user_id)
public static function followEveryone($user_id)
{
$ufep = self::getKV('user_id', $user_id);
@ -87,7 +80,7 @@ class User_followeveryone_prefs extends Managed_DataObject
}
}
static function savePref($user_id, $followEveryone)
public static function savePref($user_id, $followEveryone)
{
$ufep = self::getKV('user_id', $user_id);

View File

@ -62,33 +62,22 @@ class GroupFavoritedAction extends ShowgroupAction
$groupId = (int)$this->group->id;
$weightexpr = common_sql_weight('fave.modified', common_config('popular', 'dropoff'));
$cutoff = sprintf(
"fave.modified > '%s'",
"fave.modified > TIMESTAMP '%s'",
common_sql_date(time() - common_config('popular', 'cutoff'))
);
$qry = 'SELECT notice.*, ' .
$weightexpr . ' as weight ' .
'FROM notice ' .
"JOIN group_inbox ON notice.id = group_inbox.notice_id " .
'JOIN fave ON notice.id = fave.notice_id ' .
"WHERE $cutoff AND group_id = $groupId " .
'GROUP BY id,profile_id,uri,content,rendered,url,created,notice.modified,reply_to,is_local,source,notice.conversation ' .
'ORDER BY weight DESC';
$offset = ($this->page - 1) * NOTICES_PER_PAGE;
$limit = NOTICES_PER_PAGE + 1;
if (common_config('db', 'type') == 'pgsql') {
$qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
} else {
$qry .= ' LIMIT ' . $offset . ', ' . $limit;
}
$qry = 'SELECT notice.*, ' . $weightexpr . ' AS weight ' .
'FROM notice ' .
'INNER JOIN group_inbox ON notice.id = group_inbox.notice_id ' .
'INNER JOIN fave ON notice.id = fave.notice_id ' .
'WHERE ' . $cutoff . ' AND group_id = ' . $groupId . ' ' .
'GROUP BY id, profile_id, uri, content, rendered, url, created, notice.modified, reply_to, is_local, source, notice.conversation ' .
'ORDER BY weight DESC LIMIT ' . $limit . ' OFFSET ' . $offset;
$notice = Memcached_DataObject::cachedQuery(
'Notice',
$qry,
600
);
$notice = Memcached_DataObject::cachedQuery('Notice', $qry, 600);
$nl = new NoticeList($notice, $this);

View File

@ -1,52 +1,37 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2012, StatusNet, Inc.
*
* ModLogPlugin.php
*
* 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 Moderation
* @package StatusNet
* @package GNUsocial
* @author Evan Prodromou <evan@status.net>
* @copyright 2012 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('STATUSNET')) {
// This check helps protect against security problems;
// your code file can't be executed directly from the web.
exit(1);
}
defined('GNUSOCIAL') || die();
/**
* Moderation logging
*
* Shows a history of moderation for this user in the sidebar
*
* @category Moderation
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2012 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
class ModLogPlugin extends Plugin
{
const PLUGIN_VERSION = '2.0.0';
@ -63,7 +48,7 @@ class ModLogPlugin extends Plugin
* @return boolean hook value; true means continue processing, false means stop.
*/
function onCheckSchema()
public function onCheckSchema()
{
$schema = Schema::get();
@ -72,7 +57,7 @@ class ModLogPlugin extends Plugin
return true;
}
function onEndGrantRole($profile, $role)
public function onEndGrantRole($profile, $role)
{
$modlog = new ModLog();
@ -86,7 +71,7 @@ class ModLogPlugin extends Plugin
}
$modlog->role = $role;
$modlog->is_grant = 1;
$modlog->is_grant = true;
$modlog->created = common_sql_now();
$modlog->insert();
@ -94,7 +79,7 @@ class ModLogPlugin extends Plugin
return true;
}
function onEndRevokeRole($profile, $role)
public function onEndRevokeRole($profile, $role)
{
$modlog = new ModLog();
@ -109,7 +94,7 @@ class ModLogPlugin extends Plugin
}
$modlog->role = $role;
$modlog->is_grant = 0;
$modlog->is_grant = false;
$modlog->created = common_sql_now();
$modlog->insert();
@ -117,7 +102,7 @@ class ModLogPlugin extends Plugin
return true;
}
function onEndShowSections(Action $action)
public function onEndShowSections(Action $action)
{
if (!$action instanceof ShowstreamAction) {
// early return for actions we're not interested in
@ -140,7 +125,6 @@ class ModLogPlugin extends Plugin
$cnt = $ml->find();
if ($cnt > 0) {
$action->elementStart('div', array('id' => 'entity_mod_log',
'class' => 'section'));
@ -158,9 +142,14 @@ class ModLogPlugin extends Plugin
if (empty($mod)) {
$action->text(_('[unknown]'));
} else {
$action->element('a', array('href' => $mod->getUrl(),
'title' => $mod->getFullname()),
$mod->getNickname());
$action->element(
'a',
[
'href' => $mod->getUrl(),
'title' => $mod->getFullname(),
],
$mod->getNickname()
);
}
} else {
$action->text(_('[unknown]'));
@ -175,7 +164,8 @@ class ModLogPlugin extends Plugin
}
}
function onUserRightsCheck($profile, $right, &$result) {
public function onUserRightsCheck($profile, $right, &$result)
{
switch ($right) {
case self::VIEWMODLOG:
$result = ($profile->hasRole(Profile_role::MODERATOR) || $profile->hasRole('modhelper'));

View File

@ -1,49 +1,37 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2012, StatusNet, Inc.
*
* ModLog.php -- data object to store moderation logs
*
* 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/>.
* Data object to store moderation logs
*
* @category Moderation
* @package StatusNet
* @package GNUsocial
* @author Evan Prodromou <evan@status.net>
* @copyright 2012 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('STATUSNET')) {
exit(1);
}
defined('GNUSOCIAL') || die();
/**
* Class comment here
* @copyright 2012 StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*
* @category Category here
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/
*
* @see DB_DataObject
* @see DB_DataObject
*/
class ModLog extends Managed_DataObject
{
public $__table = 'mod_log'; // table name
@ -52,7 +40,7 @@ class ModLog extends Managed_DataObject
public $profile_id; // profile id
public $moderator_id; // profile id
public $role; // the role
public $grant; // 1 = grant, 0 = revoke
public $is_grant; // true = grant, false = revoke
public $created; // datetime
/**
@ -75,9 +63,8 @@ class ModLog extends Managed_DataObject
'length' => 32,
'not null' => true,
'description' => 'role granted or revoked'),
'is_grant' => array('type' => 'int',
'size' => 'tiny',
'default' => 1,
'is_grant' => array('type' => 'bool',
'default' => true,
'description' => 'Was this a grant or revocation of a role'),
'created' => array('type' => 'datetime',
'not null' => true,
@ -86,7 +73,7 @@ class ModLog extends Managed_DataObject
'primary key' => array('id'),
'foreign keys' => array(
'mod_log_profile_id_fkey' => array('profile', array('profile_id' => 'id')),
'mod_log_moderator_id_fkey' => array('user', array('user_id' => 'id'))
'mod_log_moderator_id_fkey' => array('user', array('moderator_id' => 'id'))
),
'indexes' => array(
'mod_log_profile_id_created_idx' => array('profile_id', 'created'),

View File

@ -326,15 +326,18 @@ class Nodeinfo_2_0Action extends Action
*/
public function getActiveUsers(int $days): int
{
$userTable = common_database_tablename('user');
$query = "
SELECT COUNT(DISTINCT profile_id) as active_users_count
SELECT COUNT(DISTINCT profile_id) AS active_users_count
FROM (
SELECT profile_id FROM notice WHERE notice.created >= NOW() - INTERVAL {$days} DAY AND notice.is_local = 1
SELECT profile_id FROM notice
WHERE notice.created >= (CURRENT_TIMESTAMP - INTERVAL '{$days}' DAY) AND notice.is_local = 1
UNION ALL
SELECT user_id FROM fave INNER JOIN user ON fave.user_id = user.id WHERE fave.created >= NOW() - INTERVAL {$days} DAY
SELECT user_id FROM fave INNER JOIN {$userTable} ON fave.user_id = {$userTable}.id
WHERE fave.created >= (CURRENT_TIMESTAMP - INTERVAL '{$days}' DAY)
UNION ALL
SELECT id FROM user WHERE user.created >= NOW() - INTERVAL {$days} DAY
) as source";
SELECT id FROM {$userTable} WHERE {$userTable}.created >= (CURRENT_TIMESTAMP - INTERVAL '{$days}' DAY)
) AS source";
$activeUsersCount = new DB_DataObject();
$activeUsersCount->query($query);

View File

@ -1,32 +1,31 @@
<?php
/*
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2009-2010, StatusNet, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* OStatusPlugin implementation for GNU Social
*
* Depends on: WebFinger plugin
*
* @package OStatusPlugin
* @maintainer Brion Vibber <brion@status.net>
* @package OStatusPlugin
* @author Brion Vibber <brion@status.net>
* @copyright 2009-2010 StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('GNUSOCIAL')) { exit(1); }
defined('GNUSOCIAL') || die();
require_once __DIR__ . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'util.php';
@ -43,44 +42,68 @@ class OStatusPlugin extends Plugin
public function onRouterInitialized(URLMapper $m)
{
// Discovery actions
$m->connect('main/ostatustag',
['action' => 'ostatustag']);
$m->connect('main/ostatustag?nickname=:nickname',
['action' => 'ostatustag'],
['nickname' => '[A-Za-z0-9_-]+']);
$m->connect('main/ostatus/group/:group',
['action' => 'ostatusinit'],
['group' => '[A-Za-z0-9_-]+']);
$m->connect('main/ostatus/peopletag/:peopletag/tagger/:tagger',
['action' => 'ostatusinit'],
['tagger' => '[A-Za-z0-9_-]+',
'peopletag' => '[A-Za-z0-9_-]+']);
$m->connect('main/ostatus',
['action' => 'ostatusinit']);
$m->connect(
'main/ostatustag',
['action' => 'ostatustag']
);
$m->connect(
'main/ostatustag?nickname=:nickname',
['action' => 'ostatustag'],
['nickname' => '[A-Za-z0-9_-]+']
);
$m->connect(
'main/ostatus/group/:group',
['action' => 'ostatusinit'],
['group' => '[A-Za-z0-9_-]+']
);
$m->connect(
'main/ostatus/peopletag/:peopletag/tagger/:tagger',
['action' => 'ostatusinit'],
[
'tagger' => '[A-Za-z0-9_-]+',
'peopletag' => '[A-Za-z0-9_-]+',
]
);
$m->connect(
'main/ostatus',
['action' => 'ostatusinit']
);
// Remote subscription actions
$m->connect('main/ostatusgroup',
['action' => 'ostatusgroup']);
$m->connect('main/ostatuspeopletag',
['action' => 'ostatuspeopletag']);
$m->connect(
'main/ostatusgroup',
['action' => 'ostatusgroup']
);
$m->connect(
'main/ostatuspeopletag',
['action' => 'ostatuspeopletag']
);
// WebSub actions
$m->connect('main/push/hub', ['action' => 'pushhub']);
$m->connect('main/push/callback/:feed',
['action' => 'pushcallback'],
['feed' => '[0-9]+']);
$m->connect(
'main/push/callback/:feed',
['action' => 'pushcallback'],
['feed' => '[0-9]+']
);
// Salmon endpoint
$m->connect('main/salmon/user/:id',
['action' => 'usersalmon'],
['id' => '[0-9]+']);
$m->connect('main/salmon/group/:id',
['action' => 'groupsalmon'],
['id' => '[0-9]+']);
$m->connect('main/salmon/peopletag/:id',
['action' => 'peopletagsalmon'],
['id' => '[0-9]+']);
$m->connect(
'main/salmon/user/:id',
['action' => 'usersalmon'],
['id' => '[0-9]+']
);
$m->connect(
'main/salmon/group/:id',
['action' => 'groupsalmon'],
['id' => '[0-9]+']
);
$m->connect(
'main/salmon/peopletag/:id',
['action' => 'peopletagsalmon'],
['id' => '[0-9]+']
);
return true;
}
@ -89,7 +112,7 @@ class OStatusPlugin extends Plugin
* @param QueueManager $qm
* @return boolean hook return
*/
function onEndInitializeQueueManager(QueueManager $qm)
public function onEndInitializeQueueManager(QueueManager $qm)
{
// Prepare outgoing distributions after notice save.
$qm->connect('ostatus', 'OStatusQueueHandler');
@ -114,7 +137,7 @@ class OStatusPlugin extends Plugin
/**
* Put saved notices into the queue for pubsub distribution.
*/
function onStartEnqueueNotice($notice, &$transports)
public function onStartEnqueueNotice($notice, &$transports)
{
if ($notice->inScope(null) && $notice->getProfile()->hasRight(Right::PUBLICNOTICE)) {
$transports[] = 'ostatus';
@ -131,7 +154,7 @@ class OStatusPlugin extends Plugin
* Set up a WebSub hub link to our internal link for canonical timeline
* Atom feeds for users and groups.
*/
function onStartApiAtom($feed)
public function onStartApiAtom($feed)
{
$id = null;
@ -140,11 +163,11 @@ class OStatusPlugin extends Plugin
$user = $feed->getUser();
$id = $user->id;
$profile = $user->getProfile();
} else if ($feed instanceof AtomGroupNoticeFeed) {
} elseif ($feed instanceof AtomGroupNoticeFeed) {
$salmonAction = 'groupsalmon';
$group = $feed->getGroup();
$id = $group->id;
} else if ($feed instanceof AtomListNoticeFeed) {
} elseif ($feed instanceof AtomListNoticeFeed) {
$salmonAction = 'peopletagsalmon';
$peopletag = $feed->getList();
$id = $peopletag->id;
@ -179,25 +202,32 @@ class OStatusPlugin extends Plugin
* @param Profile $profile
* @return bool hook return value
*/
function onStartProfileRemoteSubscribe(HTMLOutputter $output, Profile $profile): bool
public function onStartProfileRemoteSubscribe(HTMLOutputter $output, Profile $profile): bool
{
$this->onStartProfileListItemActionElements($output);
return true;
}
function onStartGroupSubscribe($widget, $group)
public function onStartGroupSubscribe($widget, $group)
{
$cur = common_current_user();
if (empty($cur)) {
$widget->out->elementStart('li', 'entity_subscribe');
$url = common_local_url('ostatusinit',
array('group' => $group->nickname));
$widget->out->element('a', array('href' => $url,
'class' => 'entity_remote_subscribe'),
// TRANS: Link to subscribe to a remote entity.
_m('Subscribe'));
$url = common_local_url(
'ostatusinit',
['group' => $group->nickname]
);
$widget->out->element(
'a',
[
'href' => $url,
'class' => 'entity_remote_subscribe',
],
// TRANS: Link to subscribe to a remote entity.
_m('Subscribe')
);
$widget->out->elementEnd('li');
return false;
@ -206,19 +236,26 @@ class OStatusPlugin extends Plugin
return true;
}
function onStartSubscribePeopletagForm($output, $peopletag)
public function onStartSubscribePeopletagForm($output, $peopletag)
{
$cur = common_current_user();
if (empty($cur)) {
$output->elementStart('li', 'entity_subscribe');
$profile = $peopletag->getTagger();
$url = common_local_url('ostatusinit',
array('tagger' => $profile->nickname, 'peopletag' => $peopletag->tag));
$output->element('a', array('href' => $url,
'class' => 'entity_remote_subscribe'),
// TRANS: Link to subscribe to a remote entity.
_m('Subscribe'));
$url = common_local_url(
'ostatusinit',
['tagger' => $profile->nickname, 'peopletag' => $peopletag->tag]
);
$output->element(
'a',
[
'href' => $url,
'class' => 'entity_remote_subscribe',
],
// TRANS: Link to subscribe to a remote entity.
_m('Subscribe')
);
$output->elementEnd('li');
return false;
@ -230,10 +267,11 @@ class OStatusPlugin extends Plugin
/*
* If the field being looked for is URI look for the profile
*/
function onStartProfileCompletionSearch($action, $profile, $search_engine) {
public function onStartProfileCompletionSearch($action, $profile, $search_engine)
{
if ($action->field == 'uri') {
$profile->joinAdd(array('id', 'user:id'));
$profile->whereAdd('uri LIKE "%' . $profile->escape($q) . '%"');
$profile->joinAdd(['id', 'user:id']);
$profile->whereAdd("uri LIKE '%" . $profile->escape($q) . "%'");
$profile->query();
$validate = new Validate();
@ -242,17 +280,16 @@ class OStatusPlugin extends Plugin
try {
if ($validate->email($q)) {
$oprofile = Ostatus_profile::ensureWebfinger($q);
} else if ($validate->uri($q)) {
} elseif ($validate->uri($q)) {
$oprofile = Ostatus_profile::ensureProfileURL($q);
} else {
// TRANS: Exception in OStatus when invalid URI was entered.
throw new Exception(_m('Invalid URI.'));
}
return $this->filter(array($oprofile->localProfile()));
} catch (Exception $e) {
// TRANS: Error message in OStatus plugin. Do not translate the domain names example.com
// TRANS: and example.net, as these are official standard domain names for use in examples.
// TRANS: Error message in OStatus plugin. Do not translate the domain names example.com
// TRANS: and example.net, as these are official standard domain names for use in examples.
$this->msg = _m("Sorry, we could not reach that address. Please make sure that the OStatus address is like nickname@example.com or http://example.net/nickname.");
return array();
}
@ -269,13 +306,15 @@ class OStatusPlugin extends Plugin
*
* @return array The matching IDs (without $preMention) and each respective position in the given string.
*/
static function extractWebfingerIds($text, $preMention='@')
public static function extractWebfingerIds($text, $preMention = '@')
{
$wmatches = array();
$result = preg_match_all('/(?<!\S)'.preg_quote($preMention, '/').'('.Nickname::WEBFINGER_FMT.')/',
$text,
$wmatches,
PREG_OFFSET_CAPTURE);
$result = preg_match_all(
'/(?<!\S)' . preg_quote($preMention, '/') . '(' . Nickname::WEBFINGER_FMT . ')/',
$text,
$wmatches,
PREG_OFFSET_CAPTURE
);
if ($result === false) {
common_log(LOG_ERR, __METHOD__ . ': Error parsing webfinger IDs from text (preg_last_error=='.preg_last_error().').');
return [];
@ -292,15 +331,17 @@ class OStatusPlugin extends Plugin
*
* @return array The matching URLs (without @ or acct:) and each respective position in the given string.
*/
static function extractUrlMentions($text, $preMention='@')
public static function extractUrlMentions($text, $preMention = '@')
{
$wmatches = array();
// In the regexp below we need to match / _before_ URL_REGEX_VALID_PATH_CHARS because it otherwise gets merged
// with the TLD before (but / is in URL_REGEX_VALID_PATH_CHARS anyway, it's just its positioning that is important)
$result = preg_match_all('/(?:^|\s+)'.preg_quote($preMention, '/').'('.URL_REGEX_DOMAIN_NAME.'(?:\/['.URL_REGEX_VALID_PATH_CHARS.']*)*)/',
$text,
$wmatches,
PREG_OFFSET_CAPTURE);
$result = preg_match_all(
'/(?:^|\s+)' . preg_quote($preMention, '/') . '(' . URL_REGEX_DOMAIN_NAME . '(?:\/[' . URL_REGEX_VALID_PATH_CHARS . ']*)*)/',
$text,
$wmatches,
PREG_OFFSET_CAPTURE
);
if ($result === false) {
common_log(LOG_ERR, __METHOD__ . ': Error parsing profile URL mentions from text (preg_last_error=='.preg_last_error().').');
return [];
@ -319,7 +360,7 @@ class OStatusPlugin extends Plugin
* @param array &$mention in/out param: set of found mentions
* @return boolean hook return value
*/
function onEndFindMentions(Profile $sender, $text, &$mentions)
public function onEndFindMentions(Profile $sender, $text, &$mentions)
{
$matches = array();
@ -472,7 +513,7 @@ class OStatusPlugin extends Plugin
* @param Profile &$profile
* @return hook return code
*/
function onStartCommandGetProfile($command, $arg, &$profile)
public function onStartCommandGetProfile($command, $arg, &$profile)
{
$oprofile = $this->pullRemoteProfile($arg);
if ($oprofile instanceof Ostatus_profile && !$oprofile->isGroup()) {
@ -499,7 +540,7 @@ class OStatusPlugin extends Plugin
* @param User_group &$group
* @return hook return code
*/
function onStartCommandGetGroup($command, $arg, &$group)
public function onStartCommandGetGroup($command, $arg, &$group)
{
$oprofile = $this->pullRemoteProfile($arg);
if ($oprofile instanceof Ostatus_profile && $oprofile->isGroup()) {
@ -546,21 +587,24 @@ class OStatusPlugin extends Plugin
return null;
}
function onEndProfileSettingsActions($out) {
public function onEndProfileSettingsActions($out) {
$siteName = common_config('site', 'name');
$js = 'navigator.registerContentHandler("application/vnd.mozilla.maybe.feed", "'.addslashes(common_local_url('RemoteFollowSub', null, array('profile' => '%s'))).'", "'.addslashes($siteName).'")';
$out->elementStart('li');
$out->element('a',
array('href' => 'javascript:'.$js),
// TRANS: Option in profile settings to add this instance to Firefox as a feedreader
_('Add to Firefox as feedreader'));
$out->element(
'a',
['href' => 'javascript:' . $js],
// TRANS: Option in profile settings to add this instance to Firefox as a feedreader
_('Add to Firefox as feedreader')
);
$out->elementEnd('li');
}
/**
* Make sure necessary tables are filled out.
*/
function onCheckSchema() {
public function onCheckSchema()
{
$schema = Schema::get();
$schema->ensureTable('ostatus_profile', Ostatus_profile::schemaDef());
$schema->ensureTable('feedsub', FeedSub::schemaDef());
@ -569,12 +613,14 @@ class OStatusPlugin extends Plugin
return true;
}
public function onEndShowStylesheets(Action $action) {
public function onEndShowStylesheets(Action $action)
{
$action->cssLink($this->path('theme/base/css/ostatus.css'));
return true;
}
function onEndShowStatusNetScripts($action) {
public function onEndShowStatusNetScripts($action)
{
$action->script($this->path('js/ostatus.js'));
return true;
}
@ -589,7 +635,7 @@ class OStatusPlugin extends Plugin
* @param string out &$title
* @return mixed hook return code
*/
function onStartNoticeSourceLink($notice, &$name, &$url, &$title)
public function onStartNoticeSourceLink($notice, &$name, &$url, &$title)
{
// If we don't handle this, keep the event handler going
if (!in_array($notice->source, array('ostatus', 'share'))) {
@ -626,7 +672,7 @@ class OStatusPlugin extends Plugin
* @param DOMDocument $feed
* @return mixed hook return code
*/
function onStartFeedSubReceive($feedsub, $feed)
public function onStartFeedSubReceive($feedsub, $feed)
{
$oprofile = Ostatus_profile::getKV('feeduri', $feedsub->uri);
if ($oprofile instanceof Ostatus_profile) {
@ -645,7 +691,7 @@ class OStatusPlugin extends Plugin
* @param integer $count in/out
* @return mixed hook return code
*/
function onFeedSubSubscriberCount($feedsub, &$count)
public function onFeedSubSubscriberCount($feedsub, &$count)
{
$oprofile = Ostatus_profile::getKV('feeduri', $feedsub->uri);
if ($oprofile instanceof Ostatus_profile) {
@ -668,7 +714,7 @@ class OStatusPlugin extends Plugin
*
* @throws Exception
*/
function onStartSubscribe(Profile $profile, Profile $other)
public function onStartSubscribe(Profile $profile, Profile $other)
{
if (!$profile->isLocal()) {
return true;
@ -693,7 +739,7 @@ class OStatusPlugin extends Plugin
*
* @throws Exception
*/
function onEndSubscribe(Profile $profile, Profile $other)
public function onEndSubscribe(Profile $profile, Profile $other)
{
if (!$profile->isLocal()) {
return true;
@ -722,7 +768,7 @@ class OStatusPlugin extends Plugin
* @param Profile $other
* @return hook return value
*/
function onEndUnsubscribe(Profile $profile, Profile $other)
public function onEndUnsubscribe(Profile $profile, Profile $other)
{
if (!$profile->isLocal()) {
return true;
@ -740,19 +786,23 @@ class OStatusPlugin extends Plugin
$act->verb = ActivityVerb::UNFOLLOW;
$act->id = TagURI::mint('unfollow:%d:%d:%s',
$profile->id,
$other->id,
common_date_iso8601(time()));
$act->id = TagURI::mint(
'unfollow:%d:%d:%s',
$profile->id,
$other->id,
common_date_iso8601(time())
);
$act->time = time();
// TRANS: Title for unfollowing a remote profile.
$act->title = _m('TITLE','Unfollow');
$act->title = _m('TITLE', 'Unfollow');
// TRANS: Success message for unsubscribe from user attempt through OStatus.
// TRANS: %1$s is the unsubscriber's name, %2$s is the unsubscribed user's name.
$act->content = sprintf(_m('%1$s stopped following %2$s.'),
$profile->getBestName(),
$other->getBestName());
$act->content = sprintf(
_m('%1$s stopped following %2$s.'),
$profile->getBestName(),
$other->getBestName()
);
$act->actor = $profile->asActivityObject();
$act->objects[] = $other->asActivityObject();
@ -773,7 +823,7 @@ class OStatusPlugin extends Plugin
* @return mixed hook return value
* @throws Exception of various kinds, some from $oprofile->subscribe();
*/
function onStartJoinGroup($group, $profile)
public function onStartJoinGroup($group, $profile)
{
$oprofile = Ostatus_profile::getKV('group_id', $group->id);
if (!$oprofile instanceof Ostatus_profile) {
@ -786,10 +836,12 @@ class OStatusPlugin extends Plugin
// has not yet been created.
$act = new Activity();
$act->id = TagURI::mint('join:%d:%d:%s',
$profile->id,
$group->id,
common_date_iso8601(time()));
$act->id = TagURI::mint(
'join:%d:%d:%s',
$profile->id,
$group->id,
common_date_iso8601(time())
);
$act->actor = $profile->asActivityObject();
$act->verb = ActivityVerb::JOIN;
@ -797,12 +849,14 @@ class OStatusPlugin extends Plugin
$act->time = time();
// TRANS: Title for joining a remote groep.
$act->title = _m('TITLE','Join');
$act->title = _m('TITLE', 'Join');
// TRANS: Success message for subscribe to group attempt through OStatus.
// TRANS: %1$s is the member name, %2$s is the subscribed group's name.
$act->content = sprintf(_m('%1$s has joined group %2$s.'),
$profile->getBestName(),
$oprofile->getBestName());
$act->content = sprintf(
_m('%1$s has joined group %2$s.'),
$profile->getBestName(),
$oprofile->getBestName()
);
if ($oprofile->notifyActivity($act, $profile)) {
return true;
@ -827,7 +881,7 @@ class OStatusPlugin extends Plugin
*
* @return mixed hook return value
*/
function onEndLeaveGroup($group, $profile)
public function onEndLeaveGroup($group, $profile)
{
$oprofile = Ostatus_profile::getKV('group_id', $group->id);
if (!$oprofile instanceof Ostatus_profile) {
@ -840,10 +894,12 @@ class OStatusPlugin extends Plugin
$member = $profile;
$act = new Activity();
$act->id = TagURI::mint('leave:%d:%d:%s',
$member->id,
$group->id,
common_date_iso8601(time()));
$act->id = TagURI::mint(
'leave:%d:%d:%s',
$member->id,
$group->id,
common_date_iso8601(time())
);
$act->actor = $member->asActivityObject();
$act->verb = ActivityVerb::LEAVE;
@ -851,12 +907,14 @@ class OStatusPlugin extends Plugin
$act->time = time();
// TRANS: Title for leaving a remote group.
$act->title = _m('TITLE','Leave');
$act->title = _m('TITLE', 'Leave');
// TRANS: Success message for unsubscribe from group attempt through OStatus.
// TRANS: %1$s is the member name, %2$s is the unsubscribed group's name.
$act->content = sprintf(_m('%1$s has left group %2$s.'),
$member->getBestName(),
$oprofile->getBestName());
$act->content = sprintf(
_m('%1$s has left group %2$s.'),
$member->getBestName(),
$oprofile->getBestName()
);
$oprofile->notifyActivity($act, $member);
}
@ -873,7 +931,7 @@ class OStatusPlugin extends Plugin
* @throws Exception of various kinds, some from $oprofile->subscribe();
*/
function onStartSubscribePeopletag($peopletag, $user)
public function onStartSubscribePeopletag($peopletag, $user)
{
$oprofile = Ostatus_profile::getKV('peopletag_id', $peopletag->id);
if (!$oprofile instanceof Ostatus_profile) {
@ -886,10 +944,12 @@ class OStatusPlugin extends Plugin
$tagger = Profile::getKV($peopletag->tagger);
$act = new Activity();
$act->id = TagURI::mint('subscribe_peopletag:%d:%d:%s',
$sub->id,
$peopletag->id,
common_date_iso8601(time()));
$act->id = TagURI::mint(
'subscribe_peopletag:%d:%d:%s',
$sub->id,
$peopletag->id,
common_date_iso8601(time())
);
$act->actor = $sub->asActivityObject();
$act->verb = ActivityVerb::FOLLOW;
@ -897,13 +957,15 @@ class OStatusPlugin extends Plugin
$act->time = time();
// TRANS: Title for following a remote list.
$act->title = _m('TITLE','Follow list');
$act->title = _m('TITLE', 'Follow list');
// TRANS: Success message for remote list follow through OStatus.
// TRANS: %1$s is the subscriber name, %2$s is the list, %3$s is the lister's name.
$act->content = sprintf(_m('%1$s is now following people listed in %2$s by %3$s.'),
$sub->getBestName(),
$oprofile->getBestName(),
$tagger->getBestName());
$act->content = sprintf(
_m('%1$s is now following people listed in %2$s by %3$s.'),
$sub->getBestName(),
$oprofile->getBestName(),
$tagger->getBestName()
);
if ($oprofile->notifyActivity($act, $sub)) {
return true;
@ -924,7 +986,7 @@ class OStatusPlugin extends Plugin
* @return mixed hook return value
*/
function onEndUnsubscribePeopletag($peopletag, $user)
public function onEndUnsubscribePeopletag($peopletag, $user)
{
$oprofile = Ostatus_profile::getKV('peopletag_id', $peopletag->id);
if (!$oprofile instanceof Ostatus_profile) {
@ -938,10 +1000,12 @@ class OStatusPlugin extends Plugin
$tagger = Profile::getKV($peopletag->tagger);
$act = new Activity();
$act->id = TagURI::mint('unsubscribe_peopletag:%d:%d:%s',
$sub->id,
$peopletag->id,
common_date_iso8601(time()));
$act->id = TagURI::mint(
'unsubscribe_peopletag:%d:%d:%s',
$sub->id,
$peopletag->id,
common_date_iso8601(time())
);
$act->actor = $member->asActivityObject();
$act->verb = ActivityVerb::UNFOLLOW;
@ -952,10 +1016,12 @@ class OStatusPlugin extends Plugin
$act->title = _m('Unfollow list');
// TRANS: Success message for remote list unfollow through OStatus.
// TRANS: %1$s is the subscriber name, %2$s is the list, %3$s is the lister's name.
$act->content = sprintf(_m('%1$s stopped following the list %2$s by %3$s.'),
$sub->getBestName(),
$oprofile->getBestName(),
$tagger->getBestName());
$act->content = sprintf(
_m('%1$s stopped following the list %2$s by %3$s.'),
$sub->getBestName(),
$oprofile->getBestName(),
$tagger->getBestName()
);
$oprofile->notifyActivity($act, $user);
}
@ -967,7 +1033,7 @@ class OStatusPlugin extends Plugin
* @param Notice $notice being favored
* @return hook return value
*/
function onEndFavorNotice(Profile $profile, Notice $notice)
public function onEndFavorNotice(Profile $profile, Notice $notice)
{
// Only distribute local users' favor actions, remote users
// will have already distributed theirs.
@ -1005,7 +1071,7 @@ class OStatusPlugin extends Plugin
* @return hook return value
* @throws Exception of various kinds, some from $oprofile->subscribe();
*/
function onEndTagProfile($ptag)
public function onEndTagProfile($ptag)
{
$oprofile = Ostatus_profile::getKV('profile_id', $ptag->tagged);
if (!$oprofile instanceof Ostatus_profile) {
@ -1023,18 +1089,23 @@ class OStatusPlugin extends Plugin
$tagged = Profile::getKV('id', $ptag->tagged);
$act->verb = ActivityVerb::TAG;
$act->id = TagURI::mint('tag_profile:%d:%d:%s',
$plist->tagger, $plist->id,
common_date_iso8601(time()));
$act->id = TagURI::mint(
'tag_profile:%d:%d:%s',
$plist->tagger,
$plist->id,
common_date_iso8601(time())
);
$act->time = time();
// TRANS: Title for listing a remote profile.
$act->title = _m('TITLE','List');
$act->title = _m('TITLE', 'List');
// TRANS: Success message for remote list addition through OStatus.
// TRANS: %1$s is the list creator's name, %2$s is the added list member, %3$s is the list name.
$act->content = sprintf(_m('%1$s listed %2$s in the list %3$s.'),
$tagger->getBestName(),
$tagged->getBestName(),
$plist->getBestName());
$act->content = sprintf(
_m('%1$s listed %2$s in the list %3$s.'),
$tagger->getBestName(),
$tagged->getBestName(),
$plist->getBestName()
);
$act->actor = $tagger->asActivityObject();
$act->objects = array($tagged->asActivityObject());
@ -1056,7 +1127,7 @@ class OStatusPlugin extends Plugin
* @param Profile_tag $ptag the people tag that was deleted
* @return hook return value
*/
function onEndUntagProfile($ptag)
public function onEndUntagProfile($ptag)
{
$oprofile = Ostatus_profile::getKV('profile_id', $ptag->tagged);
if (!$oprofile instanceof Ostatus_profile) {
@ -1074,18 +1145,23 @@ class OStatusPlugin extends Plugin
$tagged = Profile::getKV('id', $ptag->tagged);
$act->verb = ActivityVerb::UNTAG;
$act->id = TagURI::mint('untag_profile:%d:%d:%s',
$plist->tagger, $plist->id,
common_date_iso8601(time()));
$act->id = TagURI::mint(
'untag_profile:%d:%d:%s',
$plist->tagger,
$plist->id,
common_date_iso8601(time())
);
$act->time = time();
// TRANS: Title for unlisting a remote profile.
$act->title = _m('TITLE','Unlist');
$act->title = _m('TITLE', 'Unlist');
// TRANS: Success message for remote list removal through OStatus.
// TRANS: %1$s is the list creator's name, %2$s is the removed list member, %3$s is the list name.
$act->content = sprintf(_m('%1$s removed %2$s from the list %3$s.'),
$tagger->getBestName(),
$tagged->getBestName(),
$plist->getBestName());
$act->content = sprintf(
_m('%1$s removed %2$s from the list %3$s.'),
$tagger->getBestName(),
$tagged->getBestName(),
$plist->getBestName()
);
$act->actor = $tagger->asActivityObject();
$act->objects = array($tagged->asActivityObject());
@ -1107,7 +1183,7 @@ class OStatusPlugin extends Plugin
*
* @return hook return value
*/
function onEndDisfavorNotice(Profile $profile, Notice $notice)
public function onEndDisfavorNotice(Profile $profile, Notice $notice)
{
// Only distribute local users' disfavor actions, remote users
// will have already distributed theirs.
@ -1123,18 +1199,22 @@ class OStatusPlugin extends Plugin
$act = new Activity();
$act->verb = ActivityVerb::UNFAVORITE;
$act->id = TagURI::mint('disfavor:%d:%d:%s',
$profile->id,
$notice->id,
common_date_iso8601(time()));
$act->id = TagURI::mint(
'disfavor:%d:%d:%s',
$profile->id,
$notice->id,
common_date_iso8601(time())
);
$act->time = time();
// TRANS: Title for unliking a remote notice.
$act->title = _m('Unlike');
// TRANS: Success message for remove a favorite notice through OStatus.
// TRANS: %1$s is the unfavoring user's name, %2$s is URI to the no longer favored notice.
$act->content = sprintf(_m('%1$s no longer likes %2$s.'),
$profile->getBestName(),
$notice->getUrl());
$act->content = sprintf(
_m('%1$s no longer likes %2$s.'),
$profile->getBestName(),
$notice->getUrl()
);
$act->actor = $profile->asActivityObject();
$act->objects[] = $notice->asActivityObject();
@ -1144,7 +1224,7 @@ class OStatusPlugin extends Plugin
return true;
}
function onStartGetProfileUri($profile, &$uri)
public function onStartGetProfileUri($profile, &$uri)
{
$oprofile = Ostatus_profile::getKV('profile_id', $profile->id);
if ($oprofile instanceof Ostatus_profile) {
@ -1154,12 +1234,12 @@ class OStatusPlugin extends Plugin
return true;
}
function onStartUserGroupHomeUrl($group, &$url)
public function onStartUserGroupHomeUrl($group, &$url)
{
return $this->onStartUserGroupPermalink($group, $url);
}
function onStartUserGroupPermalink($group, &$url)
public function onStartUserGroupPermalink($group, &$url)
{
$oprofile = Ostatus_profile::getKV('group_id', $group->id);
if ($oprofile instanceof Ostatus_profile) {
@ -1170,21 +1250,21 @@ class OStatusPlugin extends Plugin
}
}
function onStartShowUserGroupsContent($action)
public function onStartShowUserGroupsContent($action)
{
$this->showEntityRemoteSubscribe($action);
return true;
}
function onEndShowGroupsMiniList($action)
public function onEndShowGroupsMiniList($action)
{
$this->showEntityRemoteSubscribe($action);
return true;
}
function showEntityRemoteSubscribe($action)
public function showEntityRemoteSubscribe($action)
{
if (!$action->getScoped() instanceof Profile) {
// early return if we're not logged in
@ -1195,10 +1275,15 @@ class OStatusPlugin extends Plugin
$action->elementStart('div', 'entity_actions');
$action->elementStart('p', array('id' => 'entity_remote_subscribe',
'class' => 'entity_subscribe'));
$action->element('a', array('href' => common_local_url('ostatusgroup'),
'class' => 'entity_remote_subscribe'),
// TRANS: Link text for link to remote subscribe.
_m('Remote'));
$action->element(
'a',
[
'href' => common_local_url('ostatusgroup'),
'class' => 'entity_remote_subscribe',
],
// TRANS: Link text for link to remote subscribe.
_m('Remote')
);
$action->elementEnd('p');
$action->elementEnd('div');
}
@ -1208,7 +1293,7 @@ class OStatusPlugin extends Plugin
* Ping remote profiles with updates to this profile.
* Salmon pings are queued for background processing.
*/
function onEndBroadcastProfile(Profile $profile)
public function onEndBroadcastProfile(Profile $profile)
{
$user = User::getKV('id', $profile->id);
@ -1233,16 +1318,20 @@ class OStatusPlugin extends Plugin
$act = new Activity();
$act->verb = ActivityVerb::UPDATE_PROFILE;
$act->id = TagURI::mint('update-profile:%d:%s',
$profile->id,
common_date_iso8601(time()));
$act->id = TagURI::mint(
'update-profile:%d:%s',
$profile->id,
common_date_iso8601(time())
);
$act->time = time();
// TRANS: Title for activity.
$act->title = _m('Profile update');
// TRANS: Ping text for remote profile update through OStatus.
// TRANS: %s is user that updated their profile.
$act->content = sprintf(_m('%s has updated their profile page.'),
$profile->getBestName());
$act->content = sprintf(
_m('%s has updated their profile page.'),
$profile->getBestName()
);
$act->actor = $profile->asActivityObject();
$act->objects[] = $act->actor;
@ -1254,7 +1343,7 @@ class OStatusPlugin extends Plugin
return true;
}
function onEndShowAccountProfileBlock(HTMLOutputter $out, Profile $profile)
public function onEndShowAccountProfileBlock(HTMLOutputter $out, Profile $profile)
{
if ($profile->isLocal()) {
return true;
@ -1288,7 +1377,7 @@ class OStatusPlugin extends Plugin
}
// FIXME: This one can accept both an Action and a Widget. Confusing! Refactor to (HTMLOutputter $out, Profile $target)!
function onStartProfileListItemActionElements($item)
public function onStartProfileListItemActionElements($item)
{
if (common_logged_in()) {
// only non-logged in users get to see the "remote subscribe" form
@ -1314,8 +1403,10 @@ class OStatusPlugin extends Plugin
$output->elementStart('li', 'entity_tag');
$url = common_local_url('ostatustag', ['nickname' => $target->getNickname()]);
$output->element('a',
['href' => $url,
'class' => 'entity_remote_tag'],
[
'href' => $url,
'class' => 'entity_remote_tag',
],
// TRANS: Link text for a user to list an OStatus user.
_m('List'));
$output->elementEnd('li');
@ -1388,7 +1479,7 @@ class OStatusPlugin extends Plugin
return false;
}
function onStartGetProfileFromURI($uri, &$profile)
public function onStartGetProfileFromURI($uri, &$profile)
{
// Don't want to do Web-based discovery on our own server,
// so we check locally first. This duplicates the functionality
@ -1417,7 +1508,7 @@ class OStatusPlugin extends Plugin
}
}
function onEndWebFingerNoticeLinks(XML_XRD $xrd, Notice $target)
public function onEndWebFingerNoticeLinks(XML_XRD $xrd, Notice $target)
{
$salmon_url = null;
$actor = $target->getProfile();
@ -1439,16 +1530,19 @@ class OStatusPlugin extends Plugin
return true;
}
function onEndWebFingerProfileLinks(XML_XRD $xrd, Profile $target)
public function onEndWebFingerProfileLinks(XML_XRD $xrd, Profile $target)
{
if ($target->getObjectType() === ActivityObject::PERSON) {
$this->addWebFingerPersonLinks($xrd, $target);
} elseif ($target->getObjectType() === ActivityObject::GROUP) {
$xrd->links[] = new XML_XRD_Element_Link(Discovery::UPDATESFROM,
common_local_url('ApiTimelineGroup',
array('id' => $target->getGroup()->getID(), 'format' => 'atom')),
'application/atom+xml');
$xrd->links[] = new XML_XRD_Element_Link(
Discovery::UPDATESFROM,
common_local_url(
'ApiTimelineGroup',
['id' => $target->getGroup()->getID(), 'format' => 'atom']
),
'application/atom+xml'
);
}
// Salmon
@ -1479,10 +1573,14 @@ class OStatusPlugin extends Plugin
protected function addWebFingerPersonLinks(XML_XRD $xrd, Profile $target)
{
$xrd->links[] = new XML_XRD_Element_Link(Discovery::UPDATESFROM,
common_local_url('ApiTimelineUser',
array('id' => $target->id, 'format' => 'atom')),
'application/atom+xml');
$xrd->links[] = new XML_XRD_Element_Link(
Discovery::UPDATESFROM,
common_local_url(
'ApiTimelineUser',
['id' => $target->id, 'format' => 'atom']
),
'application/atom+xml'
);
// Get this profile's keypair
$magicsig = Magicsig::getKV('user_id', $target->id);
@ -1494,8 +1592,10 @@ class OStatusPlugin extends Plugin
return false; // value doesn't mean anything, just figured I'd indicate this function didn't do anything
}
if (Event::handle('StartAttachPubkeyToUserXRD', array($magicsig, $xrd, $target))) {
$xrd->links[] = new XML_XRD_Element_Link(Magicsig::PUBLICKEYREL,
'data:application/magic-public-key,'. $magicsig->toString());
$xrd->links[] = new XML_XRD_Element_Link(
Magicsig::PUBLICKEYREL,
'data:application/magic-public-key,' . $magicsig->toString()
);
// The following event handles plugins like Diaspora which add their own version of the Magicsig pubkey
Event::handle('EndAttachPubkeyToUserXRD', array($magicsig, $xrd, $target));
}
@ -1507,7 +1607,7 @@ class OStatusPlugin extends Plugin
}
// FIXME: Maybe this shouldn't be so authoritative that it breaks other remote profile lookups?
static public function onCheckActivityAuthorship(Activity $activity, Profile &$profile)
public static function onCheckActivityAuthorship(Activity $activity, Profile &$profile)
{
try {
$oprofile = Ostatus_profile::ensureProfileURL($profile->getUrl());
@ -1562,8 +1662,13 @@ class OStatusPlugin extends Plugin
// 201 Created is what Mastodon returns when it's ok
// 202 Accepted is what we get from Diaspora, also good
if (!in_array($response->getStatus(), array(200, 201, 202))) {
common_log(LOG_ERR, sprintf('Salmon (from profile %d) endpoint %s returned status %s: %s',
$magic_env->getActor()->getID(), $endpoint_uri, $response->getStatus(), $response->getBody()));
common_log(LOG_ERR, sprintf(
'Salmon (from profile %d) endpoint %s returned status %s: %s',
$magic_env->getActor()->getID(),
$endpoint_uri,
$response->getStatus(),
$response->getBody()
));
return true;
}

View File

@ -1,29 +1,32 @@
<?php
/*
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2009-2010, StatusNet, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
if (!defined('GNUSOCIAL')) { exit(1); }
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* @package OStatusPlugin
* @maintainer Brion Vibber <brion@status.net>
* FeedSub handles low-level WebSub (PubSubHubbub/PuSH) subscriptions.
* Higher-level behavior building OStatus stuff on top is handled
* under Ostatus_profile.
*
* @package OStatusPlugin
* @author Brion Vibber <brion@status.net>
* @copyright 2009-2010 StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
defined('GNUSOCIAL') || die();
/*
WebSub (previously PubSubHubbub/PuSH) subscription flow:
@ -37,14 +40,8 @@ WebSub (previously PubSubHubbub/PuSH) subscription flow:
main/push/callback
hub sends us updates via POST
*/
/**
* FeedSub handles low-level WebSub (PubSubHubbub/PuSH) subscriptions.
* Higher-level behavior building OStatus stuff on top is handled
* under Ostatus_profile.
*/
class FeedSub extends Managed_DataObject
{
public $__table = 'feedsub';
@ -71,7 +68,7 @@ class FeedSub extends Managed_DataObject
'uri' => array('type' => 'varchar', 'not null' => true, 'length' => 191, 'description' => 'FeedSub uri'),
'huburi' => array('type' => 'text', 'description' => 'FeedSub hub-uri'),
'secret' => array('type' => 'text', 'description' => 'FeedSub stored secret'),
'sub_state' => array('type' => 'enum("subscribe","active","unsubscribe","inactive","nohub")', 'not null' => true, 'description' => 'subscription state'),
'sub_state' => array('type' => 'enum', 'enum' => array('subscribe', 'active', 'unsubscribe', 'inactive', 'nohub'), 'not null' => true, 'description' => 'subscription state'),
'sub_start' => array('type' => 'datetime', 'description' => 'subscription start'),
'sub_end' => array('type' => 'datetime', 'description' => 'subscription end'),
'last_update' => array('type' => 'datetime', 'description' => 'when this record was last updated'),
@ -96,7 +93,7 @@ class FeedSub extends Managed_DataObject
return $this->uri;
}
function getLeaseRemaining()
public function getLeaseRemaining()
{
if (empty($this->sub_end)) {
return null;
@ -118,8 +115,8 @@ class FeedSub extends Managed_DataObject
if (empty($this->huburi)
&& (!common_config('feedsub', 'fallback_hub')
|| $this->sub_state === 'nohub')) {
// Here we have no huburi set. Also, either there is no
// fallback hub configured or sub_state is "nohub".
// Here we have no huburi set. Also, either there is no
// fallback hub configured or sub_state is "nohub".
return false;
}
return true;
@ -180,7 +177,6 @@ class FeedSub extends Managed_DataObject
try {
// discover the hub uri
$feedsub->ensureHub();
} catch (FeedSubNoHubException $e) {
// Only throw this exception if we can't handle huburi-less feeds
// (i.e. we have a fallback hub or we can do feed polling (nohub)
@ -263,7 +259,7 @@ class FeedSub extends Managed_DataObject
*/
public function subscribe($rediscovered=false)
{
if ($this->sub_state && $this->sub_state != 'inactive') {
if ($this->sub_state !== 'inactive') {
common_log(LOG_WARNING, sprintf('Attempting to (re)start WebSub subscription to %s in unexpected state %s', $this->getUri(), $this->sub_state));
}
@ -276,7 +272,7 @@ class FeedSub extends Managed_DataObject
if (common_config('feedsub', 'fallback_hub')) {
// No native hub on this feed?
// Use our fallback hub, which handles polling on our behalf.
} else if (common_config('feedsub', 'nohub')) {
} elseif (common_config('feedsub', 'nohub')) {
// For this to actually work, we'll need some polling mechanism.
// The FeedPoller plugin should take care of it.
return;
@ -298,7 +294,8 @@ class FeedSub extends Managed_DataObject
*
* @throws ServerException if feed state is not valid
*/
public function unsubscribe() {
public function unsubscribe()
{
if ($this->sub_state != 'active') {
common_log(LOG_WARNING, sprintf('Attempting to (re)end WebSub subscription to %s in unexpected state %s', $this->getUri(), $this->sub_state));
}
@ -344,7 +341,7 @@ class FeedSub extends Managed_DataObject
*/
public function garbageCollect()
{
if ($this->sub_state == '' || $this->sub_state == 'inactive') {
if ($this->sub_state === 'inactive') {
// No active WebSub subscription, we can just leave it be.
return true;
}
@ -366,12 +363,12 @@ class FeedSub extends Managed_DataObject
return true;
}
static public function renewalCheck()
public static function renewalCheck()
{
$fs = new FeedSub();
// the "" empty string check is because we historically haven't saved unsubscribed feeds as NULL
$fs->whereAdd('sub_end IS NOT NULL AND sub_end!="" AND sub_end < NOW() + INTERVAL 1 day');
if (!$fs->find()) { // find can be both false and 0, depending on why nothing was found
$fs->whereAdd("sub_end IS NOT NULL AND sub_end < (CURRENT_TIMESTAMP + INTERVAL '1' DAY)");
// find can be both false and 0, depending on why nothing was found
if (!$fs->find()) {
throw new NoResultException($fs);
}
return $fs;
@ -437,10 +434,10 @@ class FeedSub extends Managed_DataObject
if ($status == 202 || $status == 204) {
common_log(LOG_INFO, __METHOD__ . ': sub req ok, awaiting verification callback');
return;
} else if ($status >= 200 && $status < 300) {
} elseif ($status >= 200 && $status < 300) {
common_log(LOG_ERR, __METHOD__ . ": sub req returned unexpected HTTP $status: " . $response->getBody());
$msg = sprintf(_m("Unexpected HTTP status: %d"), $status);
} else if ($status == 422 && !$rediscovered) {
} elseif ($status == 422 && !$rediscovered) {
// Error code regarding something wrong in the data (it seems
// that we're talking to a WebSub hub at least, so let's check
// our own data to be sure we're not mistaken somehow, which
@ -482,7 +479,8 @@ class FeedSub extends Managed_DataObject
if ($lease_seconds > 0) {
$this->sub_end = common_sql_date(time() + $lease_seconds);
} else {
$this->sub_end = null; // Backwards compatibility to StatusNet (PuSH <0.4 supported permanent subs)
// Backwards compatibility to StatusNet (PuSH <0.4 supported permanent subs)
$this->sub_end = DB_DataObject_Cast::sql('NULL');
}
$this->modified = common_sql_now();
@ -498,11 +496,10 @@ class FeedSub extends Managed_DataObject
{
$original = clone($this);
// @fixme these should all be null, but DB_DataObject doesn't save null values...?????
$this->secret = '';
$this->sub_state = '';
$this->sub_start = '';
$this->sub_end = '';
$this->secret = DB_DataObject_Cast::sql('NULL');
$this->sub_state = 'inactive';
$this->sub_start = DB_DataObject_Cast::sql('NULL');
$this->sub_end = DB_DataObject_Cast::sql('NULL');
$this->modified = common_sql_now();
return $this->update($original);
@ -544,7 +541,6 @@ class FeedSub extends Managed_DataObject
}
$this->receiveFeed($post);
} catch (FeedSubBadPushSignatureException $e) {
// We got a signature, so something could be wrong. Let's check to see if
// maybe upstream has switched to another hub. Let's fetch feed and then
@ -628,7 +624,6 @@ class FeedSub extends Managed_DataObject
throw new FeedSubBadPushSignatureException('Incoming WebSub push signature did not match expected HMAC hash.');
}
return true;
} else {
common_log(LOG_ERR, sprintf(__METHOD__.': ignoring WebSub push with bogus HMAC==', _ve($hmac)));
}

View File

@ -57,7 +57,7 @@ class HubSub extends Managed_DataObject
'secret' => array('type' => 'text', 'description' => 'HubSub stored secret'),
'sub_start' => array('type' => 'datetime', 'description' => 'subscription start'),
'sub_end' => array('type' => 'datetime', 'description' => 'subscription end'),
'errors' => array('type' => 'integer', 'not null' => true, 'default' => 0, 'description' => 'Queue handling error count, is reset on success.'),
'errors' => array('type' => 'int', 'not null' => true, 'default' => 0, 'description' => 'Queue handling error count, is reset on success.'),
'error_start' => array('type' => 'datetime', 'default' => null, 'description' => 'time of first error since latest success, should be null if no errors have been counted'),
'last_error' => array('type' => 'datetime', 'default' => null, 'description' => 'time of last failure, if ever'),
'last_error_msg' => array('type' => 'text', 'default' => null, 'description' => 'Last error _message_'),

View File

@ -51,9 +51,9 @@ class Ostatus_profile extends Managed_DataObject
return array(
'fields' => array(
'uri' => array('type' => 'varchar', 'length' => 191, 'not null' => true),
'profile_id' => array('type' => 'integer'),
'group_id' => array('type' => 'integer'),
'peopletag_id' => array('type' => 'integer'),
'profile_id' => array('type' => 'int'),
'group_id' => array('type' => 'int'),
'peopletag_id' => array('type' => 'int'),
'feeduri' => array('type' => 'varchar', 'length' => 191),
'salmonuri' => array('type' => 'varchar', 'length' => 191),
'avatar' => array('type' => 'text'),

View File

@ -1,24 +1,26 @@
#!/usr/bin/env php
<?php
/*
* StatusNet - a distributed open-source microblogging tool
* Copyright (C) 2010 StatusNet, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* @copyright 2010 StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
/*
/*
* Run this from INSTALLDIR/plugins/OStatus/scripts
*/
@ -53,7 +55,7 @@ echo "Looking for feed subscriptions with dirty no good huburis...\n";
$feedsub = new FeedSub();
$feedsub->sub_state = 'subscribe';
$feedsub->whereAdd('created < DATE_SUB(NOW(), INTERVAL 1 HOUR)');
$feedsub->whereAdd("created < (CURRENT_TIMESTAMP - INTERVAL '1' HOUR)");
$feedsub->find();
$cnt = 0;

View File

@ -1,21 +1,23 @@
#!/usr/bin/env php
<?php
/*
* StatusNet - a distributed open-source microblogging tool
* Copyright (C) 2010, StatusNet, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* @copyright 2010 StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
define('INSTALLDIR', realpath(dirname(__FILE__) . '/../../..'));
@ -39,7 +41,8 @@ END_OF_HELP;
require_once INSTALLDIR.'/scripts/commandline.inc';
function showProfileInfo(Ostatus_profile $oprofile) {
function showProfileInfo(Ostatus_profile $oprofile)
{
if ($oprofile->isGroup()) {
echo "group\n";
} else {
@ -51,7 +54,8 @@ function showProfileInfo(Ostatus_profile $oprofile) {
echo "\n";
}
function fixProfile(Ostatus_profile $oprofile) {
function fixProfile(Ostatus_profile $oprofile)
{
echo "Before:\n";
showProfileInfo($oprofile);
@ -102,10 +106,10 @@ if (have_option('all')) {
echo "Failed on URI=="._ve($oprofile->uri).": {$e->getMessage()}\n";
}
}
} else if (have_option('suspicious')) {
} elseif (have_option('suspicious')) {
$oprofile = new Ostatus_profile();
$oprofile->joinAdd(array('profile_id', 'profile:id'));
$oprofile->whereAdd("nickname rlike '^[0-9]$'");
$oprofile->joinAdd(['profile_id', 'profile:id']);
$oprofile->whereAdd("CHAR_LENGTH(nickname) = 1 AND nickname BETWEEN '0' AND '9'");
$oprofile->find();
echo "Found $oprofile->N matching profiles:\n\n";
while ($oprofile->fetch()) {
@ -116,7 +120,7 @@ if (have_option('all')) {
echo "Failed on URI=="._ve($oprofile->uri).": {$e->getMessage()}\n";
}
}
} else if (!empty($args[0]) && $validate->uri($args[0])) {
} elseif (!empty($args[0]) && $validate->uri($args[0])) {
$uri = $args[0];
$oprofile = Ostatus_profile::getKV('uri', $uri);

View File

@ -1,35 +1,30 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* StatusNet, the distributed open-source microblogging tool
*
* Settings for OpenID
*
* 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
* @package GNUsocial
* @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/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('GNUSOCIAL')) {
exit(1);
}
defined('GNUSOCIAL') || die();
require_once INSTALLDIR.'/plugins/OpenID/openid.php';
@ -38,11 +33,8 @@ require_once INSTALLDIR.'/plugins/OpenID/openid.php';
*
* Lets users add, edit and delete OpenIDs from their account
*
* @category Settings
* @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/
* @copyright 2008-2009 StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
class OpenidsettingsAction extends SettingsAction
{
@ -100,17 +92,26 @@ class OpenidsettingsAction extends SettingsAction
$this->elementStart('ul', 'form_data');
$this->elementStart('li');
// TRANS: Field label.
$this->input('openid_url', _m('OpenID URL'), null,
// TRANS: Form guide.
_m('An OpenID URL which identifies you.'),
null, true,
['placeholder'=>'https://example.com/you']);
$this->input(
'openid_url',
_m('OpenID URL'),
null,
// TRANS: Form guide.
_m('An OpenID URL which identifies you.'),
null,
true,
['placeholder' => 'https://example.com/you']
);
$this->elementEnd('li');
$this->elementStart('li');
// TRANS: Field label.
$this->checkbox('openid-synch', _m('Synchronize Account'), false,
// TRANS: Form guide.
_m('Synchronize GNU social profile with this OpenID identity.'));
$this->checkbox(
'openid-synch',
_m('Synchronize Account'),
false,
// TRANS: Form guide.
_m('Synchronize GNU social profile with this OpenID identity.')
);
$this->elementEnd('li');
$this->elementEnd('ul');
// TRANS: Button text for adding an OpenID URL.
@ -129,13 +130,16 @@ class OpenidsettingsAction extends SettingsAction
$this->element('h2', null, _m('HEADER', 'OpenID Actions'));
if ($cnt == 1 && !$this->scoped->hasPassword()) {
$this->element('p', 'form_guide',
// TRANS: Form guide.
_m('You can\'t remove your main OpenID account ' .
'without either adding a password to your ' .
'GNU social account or another OpenID account. ' .
'You can synchronize your profile with your ' .
'OpenID by clicking the button labeled "Synchronize".'));
$this->element(
'p',
'form_guide',
// TRANS: Form guide.
_m('You can\'t remove your main OpenID account ' .
'without either adding a password to your ' .
'GNU social account or another OpenID account. ' .
'You can synchronize your profile with your ' .
'OpenID by clicking the button labeled "Synchronize".')
);
if ($oid->fetch()) {
$this->elementStart('form', ['method' => 'POST',
@ -152,12 +156,15 @@ class OpenidsettingsAction extends SettingsAction
$this->elementEnd('form');
}
} else {
$this->element('p', 'form_guide',
// TRANS: Form guide.
_m('You can remove an OpenID from your account ' .
'by clicking the button labeled "Remove". ' .
'You can synchronize your profile with an OpenID ' .
'by clicking the button labeled "Synchronize".'));
$this->element(
'p',
'form_guide',
// TRANS: Form guide.
_m('You can remove an OpenID from your account ' .
'by clicking the button labeled "Remove". ' .
'You can synchronize your profile with an OpenID ' .
'by clicking the button labeled "Synchronize".')
);
$idx = 0;
while ($oid->fetch()) {
@ -191,26 +198,38 @@ class OpenidsettingsAction extends SettingsAction
// TRANS: Fieldset legend.
$this->element('legend', null, _m('OpenID Trusted Sites'));
$this->hidden('token', common_session_token());
$this->element('p', 'form_guide',
// TRANS: Form guide.
_m('The following sites are allowed to access your ' .
'identity and log you in. You can remove a site from ' .
'this list to deny it access to your OpenID.'));
$this->element(
'p',
'form_guide',
// TRANS: Form guide.
_m('The following sites are allowed to access your ' .
'identity and log you in. You can remove a site from ' .
'this list to deny it access to your OpenID.')
);
$this->elementStart('ul', 'form_data');
$user_openid_trustroot = new User_openid_trustroot();
$user_openid_trustroot->user_id = $this->scoped->getID();
if ($user_openid_trustroot->find()) {
while ($user_openid_trustroot->fetch()) {
$this->elementStart('li');
$this->element('input', ['name' => 'openid_trustroot[]',
'type' => 'checkbox',
'class' => 'checkbox',
'value' => $user_openid_trustroot->trustroot,
'id' => 'openid_trustroot_' . crc32($user_openid_trustroot->trustroot)]);
$this->element('label',
['class'=>'checkbox',
'for' => 'openid_trustroot_' . crc32($user_openid_trustroot->trustroot)],
$user_openid_trustroot->trustroot);
$this->element(
'input',
[
'name' => 'openid_trustroot[]',
'type' => 'checkbox',
'class' => 'checkbox',
'value' => $user_openid_trustroot->trustroot,
'id' => 'openid_trustroot_' . crc32($user_openid_trustroot->trustroot),
]
);
$this->element(
'label',
[
'class'=>'checkbox',
'for' => 'openid_trustroot_' . crc32($user_openid_trustroot->trustroot),
],
$user_openid_trustroot->trustroot
);
$this->elementEnd('li');
}
}
@ -363,7 +382,7 @@ class OpenidsettingsAction extends SettingsAction
$orig = clone($prefs);
}
$prefs->hide_profile_link = $this->booleanintstring('hide_profile_link');
$prefs->hide_profile_link = $this->boolean('hide_profile_link');
if ($orig instanceof User_openid_prefs) {
$prefs->update($orig);

View File

@ -63,12 +63,12 @@ class User_openid_prefs extends Managed_DataObject
'description' => 'Per-user preferences for OpenID display',
'fields' => [
'user_id' => [
'type' => 'integer',
'type' => 'int',
'not null' => true,
'description' => 'User whose prefs we are saving'
],
'hide_profile_link' => [
'type' => 'integer',
'type' => 'int',
'not null' => true,
'default' => 0,
'description' => 'Whether to hide profile links from profile block'

View File

@ -1,25 +1,25 @@
<?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/>.
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* @copyright 2008, 2009 StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('STATUSNET')) {
exit(1);
}
defined('GNUSOCIAL') || die();
require_once('Auth/OpenID.php');
require_once('Auth/OpenID/Consumer.php');
@ -49,19 +49,19 @@ function oid_store()
}
$db = DB::connect($dsn, $options);
if (PEAR::isError($db)) {
if ((new PEAR)->isError($db)) {
throw new ServerException($db->getMessage());
}
switch (common_config('db', 'type')) {
case 'pgsql':
$store = new Auth_OpenID_PostgreSQLStore($db);
break;
case 'mysql':
$store = new Auth_OpenID_MySQLStore($db);
break;
case 'postgresql':
$store = new Auth_OpenID_PostgreSQLStore($db);
break;
default:
throw new ServerException(_m('Unknown DB type for OpenID.'));
throw new ServerException('Unknown DB type selected.');
}
}
return $store;
@ -90,9 +90,11 @@ function oid_clear_last()
function oid_set_last($openid_url)
{
common_set_cookie(OPENID_COOKIE_KEY,
$openid_url,
time() + OPENID_COOKIE_EXPIRY);
common_set_cookie(
OPENID_COOKIE_KEY,
$openid_url,
time() + OPENID_COOKIE_EXPIRY
);
}
function oid_get_last()
@ -119,7 +121,7 @@ function oid_link_user($id, $canonical, $display)
$oid->created = common_sql_now();
if (!$oid->insert()) {
$err = &$_PEAR->getStaticProperty('DB_DataObject','lastError');
$err = &$_PEAR->getStaticProperty('DB_DataObject', 'lastError');
return false;
}
@ -149,9 +151,11 @@ function oid_check_immediate($openid_url, $backto=null)
$_SESSION['openid_immediate_backto'] = $backto;
oid_authenticate($openid_url,
'finishimmediate',
true);
oid_authenticate(
$openid_url,
'finishimmediate',
true
);
}
function oid_authenticate($openid_url, $returnto, $immediate=false)
@ -177,23 +181,27 @@ function oid_authenticate($openid_url, $returnto, $immediate=false)
common_log(LOG_ERR, __METHOD__ . ": mystery fail contacting $openid_url");
// TRANS: OpenID plugin message. Given when an OpenID is not valid.
throw new ServerException(_m('Not a valid OpenID.'));
} else if (Auth_OpenID::isFailure($auth_request)) {
} elseif (Auth_OpenID::isFailure($auth_request)) {
common_log(LOG_ERR, __METHOD__ . ": OpenID fail to $openid_url: $auth_request->message");
// TRANS: OpenID plugin server error. Given when the OpenID authentication request fails.
// TRANS: %s is the failure message.
throw new ServerException(sprintf(_m('OpenID failure: %s.'), $auth_request->message));
}
$sreg_request = Auth_OpenID_SRegRequest::build(// Required
array(),
// Optional
array('nickname',
'email',
'fullname',
'language',
'timezone',
'postcode',
'country'));
$sreg_request = Auth_OpenID_SRegRequest::build(
// Required
[],
// Optional
[
'nickname',
'email',
'fullname',
'language',
'timezone',
'postcode',
'country',
]
);
if ($sreg_request) {
$auth_request->addExtension($sreg_request);
@ -224,9 +232,11 @@ function oid_authenticate($openid_url, $returnto, $immediate=false)
// autosubmitter for now.
//
//if ($auth_request->shouldSendRedirect()) {
$redirect_url = $auth_request->redirectURL($trust_root,
$process_url,
$immediate);
$redirect_url = $auth_request->redirectURL(
$trust_root,
$process_url,
$immediate
);
if (Auth_OpenID::isFailure($redirect_url)) {
// TRANS: OpenID plugin server error. Given when the OpenID authentication request cannot be redirected.
// TRANS: %s is the failure message.
@ -266,11 +276,14 @@ function oid_authenticate($openid_url, $returnto, $immediate=false)
function _oid_print_instructions()
{
common_element('div', 'instructions',
// TRANS: OpenID plugin user instructions.
_m('This form should automatically submit itself. '.
'If not, click the submit button to go to your '.
'OpenID provider.'));
common_element(
'div',
'instructions',
// TRANS: OpenID plugin user instructions.
_m('This form should automatically submit itself. '.
'If not, click the submit button to go to your '.
'OpenID provider.')
);
}
/**
@ -382,22 +395,22 @@ function oid_check_teams($response)
class AutosubmitAction extends Action
{
var $form_html = null;
var $form_id = null;
public $form_html = null;
public $form_id = null;
function handle()
public function handle()
{
parent::handle();
$this->showPage();
}
function title()
public function title()
{
// TRANS: Title
return _m('OpenID Login Submission');
}
function showContent()
public function showContent()
{
$this->raw('<p style="margin: 20px 80px">');
// @todo FIXME: This would be better using standard CSS class, but the present theme's a bit scary.
@ -414,10 +427,13 @@ class AutosubmitAction extends Action
$this->raw($this->form_html);
}
function showScripts()
public function showScripts()
{
parent::showScripts();
$this->element('script', null,
'document.getElementById(\'' . $this->form_id . '\').submit();');
$this->element(
'script',
null,
'document.getElementById(\'' . $this->form_id . '\').submit();'
);
}
}

View File

@ -1,46 +1,38 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* Data class to mark notices as bookmarks
*
* PHP version 5
*
* @category PollPlugin
* @package StatusNet
* @author Brion Vibber <brion@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) 2011, 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/>.
* @category PollPlugin
* @package GNUsocial
* @author Brion Vibber <brion@status.net>
* @copyright 2011 StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('STATUSNET')) {
exit(1);
}
defined('GNUSOCIAL') || die();
/**
* For storing the poll options and such
*
* @category PollPlugin
* @package StatusNet
* @author Brion Vibber <brion@status.net>
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/
* @copyright 2011 StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*
* @see DB_DataObject
* @see DB_DataObject
*/
class Poll extends Managed_DataObject
{
@ -136,7 +128,9 @@ class Poll extends Managed_DataObject
$pr = new Poll_response();
$pr->poll_id = $this->id;
$pr->groupBy('selection');
$pr->selectAdd('count(profile_id) as votes');
$pr->selectAdd();
$pr->selectAdd('selection');
$pr->selectAdd('COUNT(profile_id) AS votes');
$pr->find();
$raw = array();

View File

@ -1,46 +1,38 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* Data class to record responses to polls
*
* PHP version 5
*
* @category PollPlugin
* @package StatusNet
* @author Brion Vibber <brion@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) 2011, 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/>.
* @category PollPlugin
* @package GNUsocial
* @author Brion Vibber <brion@status.net>
* @copyright 2011, StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('STATUSNET')) {
exit(1);
}
defined('GNUSOCIAL') || die();
/**
* For storing the poll options and such
*
* @category PollPlugin
* @package StatusNet
* @author Brion Vibber <brion@status.net>
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/
* @copyright 2011, StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*
* @see DB_DataObject
* @see DB_DataObject
*/
class Poll_response extends Managed_DataObject
{
@ -69,7 +61,7 @@ class Poll_response extends Managed_DataObject
),
'primary key' => array('id'),
'unique keys' => array(
'poll_uri_key' => array('uri'),
'poll_response_uri_key' => array('uri'),
'poll_response_poll_id_profile_id_key' => array('poll_id', 'profile_id'),
),
'indexes' => array(

View File

@ -1,44 +1,37 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* Data class to record user prefs for polls
*
* PHP version 5
*
* @category PollPlugin
* @package StatusNet
* @author Evan Prodromou <evan@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) 2012, 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/>.
* @category PollPlugin
* @package GNUsocial
* @author Brion Vibber <brion@status.net>
* @author Evan Prodromou <evan@status.net>
* @copyright 2012, StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('STATUSNET')) {
exit(1);
}
defined('GNUSOCIAL') || die();
/**
* For storing the poll prefs
*
* @category PollPlugin
* @package StatusNet
* @author Brion Vibber <brion@status.net>
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/
* @copyright 2012, StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*
* @see DB_DataObject
*/
@ -46,7 +39,7 @@ class User_poll_prefs extends Managed_DataObject
{
public $__table = 'user_poll_prefs'; // table name
public $user_id; // int id
public $hide_responses; // boolean
public $hide_responses; // bool
public $created; // datetime
public $modified; // datetime
@ -59,7 +52,7 @@ class User_poll_prefs extends Managed_DataObject
'description' => 'Record of user preferences for polls',
'fields' => array(
'user_id' => array('type' => 'int', 'not null' => true, 'description' => 'user id'),
'hide_responses' => array('type' => 'int', 'size' => 'tiny', 'default' => 0, 'description' => 'Hide all poll responses'),
'hide_responses' => array('type' => 'bool', 'default' => false, 'description' => 'Hide all poll responses'),
'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'),
),

View File

@ -1,47 +1,36 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2011, StatusNet, Inc.
*
* Close a question to further answers
*
* 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 QnA
* @package StatusNet
* @package GNUsocial
* @author Zach Copley <zach@status.net>
* @copyright 2011 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or late
*/
if (!defined('STATUSNET')) {
// This check helps protect against security problems;
// your code file can't be executed directly from the web.
exit(1);
}
defined('GNUSOCIAL') || die();
/**
* Close a question to new answers
*
* @category QnA
* @package StatusNet
* @author Zach Copley <zach@status.net>
* @copyright 2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or late
*/
class QnaclosequestionAction extends Action
{
@ -57,7 +46,7 @@ class QnaclosequestionAction extends Action
*
* @return string Action title
*/
function title()
public function title()
{
// TRANS: Page title for close a question
return _m('Close question');
@ -71,7 +60,7 @@ class QnaclosequestionAction extends Action
* @return boolean true
* @throws ClientException
*/
function prepare(array $args = [])
public function prepare(array $args = [])
{
parent::prepare($args);
if ($this->boolean('ajax')) {
@ -107,7 +96,7 @@ class QnaclosequestionAction extends Action
*
* @return void
*/
function handle()
public function handle()
{
parent::handle();
@ -125,7 +114,7 @@ class QnaclosequestionAction extends Action
*
* @return void
*/
function closeQuestion()
public function closeQuestion()
{
$user = common_current_user();
@ -136,9 +125,8 @@ class QnaclosequestionAction extends Action
}
$orig = clone($this->question);
$this->question->closed = 1;
$this->question->closed = true;
$this->question->update($orig);
} catch (ClientException $ce) {
$this->error = $ce->getMessage();
$this->showPage();
@ -166,7 +154,7 @@ class QnaclosequestionAction extends Action
*
* @return void
*/
function showContent()
public function showContent()
{
if (!empty($this->error)) {
$this->element('p', 'error', $this->error);
@ -184,7 +172,7 @@ class QnaclosequestionAction extends Action
*
* @return boolean is read only action?
*/
function isReadOnly($args)
public function isReadOnly($args)
{
if ($_SERVER['REQUEST_METHOD'] == 'GET' ||
$_SERVER['REQUEST_METHOD'] == 'HEAD') {

View File

@ -1,47 +1,36 @@
<?php
/**
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2011, StatusNet, Inc.
*
* Revise an answer
*
* 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 QnA
* @package StatusNet
* @author Zach Copley <zach@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);
}
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* Revise an answer
*
* @category QnA
* @package StatusNet
* @package GNUsocial
* @author Zach Copley <zach@status.net>
* @copyright 2011 StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
defined('GNUSOCIAL') || die();
/**
* Revise an answer
*
* @copyright 2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
class QnareviseanswerAction extends Action
{
@ -56,7 +45,7 @@ class QnareviseanswerAction extends Action
*
* @return string Action title
*/
function title()
public function title()
{
// TRANS: Page title for revising a question
return _m('Revise answer');
@ -70,7 +59,7 @@ class QnareviseanswerAction extends Action
* @return boolean true
* @throws ClientException
*/
function prepare(array $args = [])
public function prepare(array $args = [])
{
parent::prepare($args);
if ($this->boolean('ajax')) {
@ -110,7 +99,7 @@ class QnareviseanswerAction extends Action
*
* @return void
*/
function handle()
public function handle()
{
parent::handle();
@ -119,7 +108,7 @@ class QnareviseanswerAction extends Action
if ($this->arg('revise')) {
$this->showContent();
return;
} else if ($this->arg('best')) {
} elseif ($this->arg('best')) {
if ($this->user->id == $this->question->profile_id) {
$this->markBest();
return;
@ -138,7 +127,7 @@ class QnareviseanswerAction extends Action
*
* @return void
*/
function showContent()
public function showContent()
{
if (!empty($this->error)) {
$this->element('p', 'error', $this->error);
@ -154,7 +143,7 @@ class QnareviseanswerAction extends Action
return;
}
function showAjaxReviseForm()
public function showAjaxReviseForm()
{
$this->startHTML('text/xml;charset=utf-8');
$this->elementStart('head');
@ -173,7 +162,7 @@ class QnareviseanswerAction extends Action
*
* @return void
*/
function markBest()
public function markBest()
{
$question = $this->question;
$answer = $this->answer;
@ -181,12 +170,12 @@ class QnareviseanswerAction extends Action
try {
// close the question to further answers
$orig = clone($question);
$question->closed = 1;
$question->closed = true;
$result = $question->update($orig);
// mark this answer an the best answer
$orig = clone($answer);
$answer->best = 1;
$answer->best = true;
$result = $answer->update($orig);
} catch (ClientException $ce) {
$this->error = $ce->getMessage();
@ -215,7 +204,7 @@ class QnareviseanswerAction extends Action
*
* @return void
*/
function reviseAnswer()
public function reviseAnswer()
{
$answer = $this->answer;
@ -255,7 +244,7 @@ class QnareviseanswerAction extends Action
*
* @return boolean is read only action?
*/
function isReadOnly($args)
public function isReadOnly($args)
{
if ($_SERVER['REQUEST_METHOD'] == 'GET' ||
$_SERVER['REQUEST_METHOD'] == 'HEAD') {

View File

@ -1,46 +1,38 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* Data class to save answers to questions
*
* PHP version 5
*
* @category QnA
* @package StatusNet
* @author Zach Copley <zach@status.net>
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/
*
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2011, 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/>.
* @category QnA
* @package GNUsocial
* @author Zach Copley <zach@status.net>
* @copyright 2011 StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('STATUSNET')) {
exit(1);
}
defined('STATUSNET') || die();
/**
* For storing answers
*
* @category QnA
* @package StatusNet
* @author Zach Copley <zach@status.net>
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/
* @copyright 2011 StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*
* @see DB_DataObject
* @see DB_DataObject
*/
class QnA_Answer extends Managed_DataObject
{
@ -51,7 +43,7 @@ class QnA_Answer extends Managed_DataObject
public $uri; // varchar(191) not 255 because utf8mb4 takes more space
public $question_id; // char(36) -> question.id UUID
public $profile_id; // int -> question.id
public $best; // (boolean) int -> whether the question asker has marked this as the best answer
public $best; // bool -> whether the question asker has marked this as the best answer
public $revisions; // int -> count of revisions to this answer
public $content; // text -> response text
public $created; // datetime
@ -82,18 +74,18 @@ class QnA_Answer extends Managed_DataObject
'description' => 'UUID of question being responded to',
),
'content' => array('type' => 'text'), // got a better name?
'best' => array('type' => 'int', 'size' => 'tiny'),
'best' => array('type' => 'bool'),
'revisions' => array('type' => 'int'),
'profile_id' => array('type' => 'int'),
'created' => array('type' => 'datetime', 'not null' => true),
),
'primary key' => array('id'),
'unique keys' => array(
'question_uri_key' => array('uri'),
'question_id_profile_id_key' => array('question_id', 'profile_id'),
'qna_answer_uri_key' => array('uri'),
'qna_answer_question_id_profile_id_key' => array('question_id', 'profile_id'),
),
'indexes' => array(
'profile_id_question_id_index' => array('profile_id', 'question_id'),
'qna_answer_profile_id_question_id_idx' => array('profile_id', 'question_id'),
)
);
}
@ -105,7 +97,7 @@ class QnA_Answer extends Managed_DataObject
*
* @return QnA_Answer found response or null
*/
static function getByNotice($notice)
public static function getByNotice($notice)
{
$answer = self::getKV('uri', $notice->uri);
if (empty($answer)) {
@ -119,17 +111,17 @@ class QnA_Answer extends Managed_DataObject
*
* @return Notice
*/
function getNotice()
public function getNotice()
{
return Notice::getKV('uri', $this->uri);
}
static function fromNotice($notice)
public static function fromNotice($notice)
{
return QnA_Answer::getKV('uri', $notice->uri);
}
function getUrl()
public function getUrl()
{
return $this->getNotice()->getUrl();
}
@ -139,29 +131,29 @@ class QnA_Answer extends Managed_DataObject
*
* @return QnA_Question
*/
function getQuestion()
public function getQuestion()
{
$question = QnA_Question::getKV('id', $this->question_id);
if (empty($question)) {
// TRANS: Exception thown when getting a question with a non-existing ID.
// TRANS: %s is the non-existing question ID.
throw new Exception(sprintf(_m('No question with ID %s'),$this->question_id));
throw new Exception(sprintf(_m('No question with ID %s'), $this->question_id));
}
return $question;
}
function getProfile()
public function getProfile()
{
$profile = Profile::getKV('id', $this->profile_id);
if (empty($profile)) {
// TRANS: Exception thown when getting a profile with a non-existing ID.
// TRANS: %s is the non-existing profile ID.
throw new Exception(sprintf(_m('No profile with ID %s'),$this->profile_id));
throw new Exception(sprintf(_m('No profile with ID %s'), $this->profile_id));
}
return $profile;
}
function asHTML()
public function asHTML()
{
return self::toHTML(
$this->getProfile(),
@ -170,7 +162,7 @@ class QnA_Answer extends Managed_DataObject
);
}
function asString()
public function asString()
{
return self::toString(
$this->getProfile(),
@ -179,7 +171,7 @@ class QnA_Answer extends Managed_DataObject
);
}
static function toHTML($profile, $question, $answer)
public static function toHTML($profile, $question, $answer)
{
$notice = $question->getNotice();
@ -201,7 +193,7 @@ class QnA_Answer extends Managed_DataObject
htmlspecialchars(
// Notification of how often an answer was revised.
// TRANS: %s is the number of answer revisions.
sprintf(_m('%s revision','%s revisions',$answer->revisions), $answer->revisions)
sprintf(_m('%s revision', '%s revisions', $answer->revisions), $answer->revisions)
)
);
$out->elementEnd('span');
@ -212,7 +204,7 @@ class QnA_Answer extends Managed_DataObject
return $out->getString();
}
static function toString($profile, $question, $answer)
public static function toString($profile, $question, $answer)
{
// @todo FIXME: unused variable?
$notice = $question->getNotice();
@ -237,7 +229,7 @@ class QnA_Answer extends Managed_DataObject
*
* @return Notice saved notice
*/
static function saveNew($profile, $question, $text, $options = null)
public static function saveNew($profile, $question, $text, $options = null)
{
if (empty($options)) {
$options = array();
@ -248,7 +240,7 @@ class QnA_Answer extends Managed_DataObject
$answer->profile_id = $profile->id;
$answer->question_id = $question->id;
$answer->revisions = 0;
$answer->best = 0;
$answer->best = false;
$answer->content = $text;
$answer->created = common_sql_now();
$answer->uri = common_local_url(

View File

@ -1,46 +1,38 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* Data class to mark a notice as a question
*
* PHP version 5
*
* @category QnA
* @package StatusNet
* @author Zach Copley <zach@status.net>
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/
*
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2011, 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/>.
* @category QnA
* @package GNUsocial
* @author Zach Copley <zach@status.net>
* @copyright 2011 StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('STATUSNET')) {
exit(1);
}
defined('GNUSOCIAL') || die();
/**
* For storing a question
*
* @category QnA
* @package StatusNet
* @author Zach Copley <zach@status.net>
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/
* @copyright 2011 StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*
* @see DB_DataObject
* @see DB_DataObject
*/
class QnA_Question extends Managed_DataObject
{
@ -52,7 +44,7 @@ class QnA_Question extends Managed_DataObject
public $profile_id; // int -> profile.id
public $title; // text
public $description; // text
public $closed; // int (boolean) whether a question is closed
public $closed; // bool -> whether a question is closed
public $created; // datetime
/**
@ -76,7 +68,7 @@ class QnA_Question extends Managed_DataObject
),
'profile_id' => array('type' => 'int'),
'title' => array('type' => 'text'),
'closed' => array('type' => 'int', 'size' => 'tiny'),
'closed' => array('type' => 'bool'),
'description' => array('type' => 'text'),
'created' => array(
'type' => 'datetime',
@ -85,7 +77,7 @@ class QnA_Question extends Managed_DataObject
),
'primary key' => array('id'),
'unique keys' => array(
'question_uri_key' => array('uri'),
'qna_question_uri_key' => array('uri'),
),
);
}
@ -97,28 +89,28 @@ class QnA_Question extends Managed_DataObject
*
* @return Question found question or null
*/
static function getByNotice($notice)
public static function getByNotice($notice)
{
return self::getKV('uri', $notice->uri);
}
function getNotice()
public function getNotice()
{
return Notice::getKV('uri', $this->uri);
}
function getUrl()
public function getUrl()
{
return $this->getNotice()->getUrl();
}
function getProfile()
public function getProfile()
{
$profile = Profile::getKV('id', $this->profile_id);
if (empty($profile)) {
// TRANS: Exception trown when getting a profile for a non-existing ID.
// TRANS: %s is the provided profile ID.
throw new Exception(sprintf(_m('No profile with ID %s'),$this->profile_id));
throw new Exception(sprintf(_m('No profile with ID %s'), $this->profile_id));
}
return $profile;
}
@ -130,7 +122,7 @@ class QnA_Question extends Managed_DataObject
*
* @return Answer object or null
*/
function getAnswer(Profile $profile)
public function getAnswer(Profile $profile)
{
$a = new QnA_Answer();
$a->question_id = $this->id;
@ -143,7 +135,7 @@ class QnA_Question extends Managed_DataObject
}
}
function getAnswers()
public function getAnswers()
{
$a = new QnA_Answer();
$a->question_id = $this->id;
@ -155,7 +147,7 @@ class QnA_Question extends Managed_DataObject
}
}
function countAnswers()
public function countAnswers()
{
$a = new QnA_Answer();
@ -164,22 +156,22 @@ class QnA_Question extends Managed_DataObject
return $a->count();
}
static function fromNotice($notice)
public static function fromNotice($notice)
{
return QnA_Question::getKV('uri', $notice->uri);
}
function asHTML()
public function asHTML()
{
return self::toHTML($this->getProfile(), $this);
}
function asString()
public function asString()
{
return self::toString($this->getProfile(), $this);
}
static function toHTML($profile, $question)
public static function toHTML($profile, $question)
{
$notice = $question->getNotice();
@ -205,7 +197,7 @@ class QnA_Question extends Managed_DataObject
$out->elementStart('span', 'answer-count');
// TRANS: Number of given answers to a question.
// TRANS: %s is the number of given answers.
$out->text(sprintf(_m('%s answer','%s answers',$cnt), $cnt));
$out->text(sprintf(_m('%s answer', '%s answers', $cnt), $cnt));
$out->elementEnd('span');
}
@ -221,7 +213,7 @@ class QnA_Question extends Managed_DataObject
return $out->getString();
}
static function toString($profile, $question, $answers)
public static function toString($profile, $question, $answers)
{
return sprintf(htmlspecialchars($question->description));
}
@ -237,7 +229,7 @@ class QnA_Question extends Managed_DataObject
*
* @return Notice saved notice
*/
static function saveNew($profile, $title, $description, $options = array())
public static function saveNew($profile, $title, $description, $options = [])
{
$q = new QnA_Question();

View File

@ -1,46 +1,38 @@
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* Data class to save users votes for
*
* PHP version 5
*
* @category QnA
* @package StatusNet
* @author Zach Copley <zach@status.net>
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/
*
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2011, 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/>.
* @category QnA
* @package GNUsocial
* @author Zach Copley <zach@status.net>
* @copyright 2011 StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
if (!defined('STATUSNET')) {
exit(1);
}
defined('GNUSOCIAL') || die();
/**
* For storing votes on question and answers
*
* @category QnA
* @package StatusNet
* @author Zach Copley <zach@status.net>
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/
* @copyright 2011 StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*
* @see DB_DataObject
* @see DB_DataObject
*/
class QnA_Vote extends Managed_DataObject
{
@ -87,11 +79,11 @@ class QnA_Vote extends Managed_DataObject
),
'primary key' => array('id'),
'indexes' => array(
'profile_id_question_Id_index' => array(
'qna_vote_profile_id_question_id_idx' => array(
'profile_id',
'question_id'
),
'profile_id_question_Id_index' => array(
'qna_vote_profile_id_question_id_idx' => array(
'profile_id',
'answer_id'
)
@ -110,7 +102,7 @@ class QnA_Vote extends Managed_DataObject
*
* @return Void
*/
static function save($profile, $question, $answer, $vote)
public static function save($profile, $question, $answer, $vote)
{
$v = new QnA_Vote();
$v->id = UUID::gen();

View File

@ -1,36 +1,18 @@
<?php
/**
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2011, StatusNet, Inc.
*
* A channel for real-time browser data
*
* 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 Realtime
* @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')) {
exit(1);
}
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/**
* A channel for real-time browser data
@ -38,11 +20,20 @@ if (!defined('STATUSNET')) {
* For each user currently browsing the site, we want to know which page they're on
* so we can send real-time updates to their browser.
*
* @category Realtime
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/
* @category Realtime
* @package GNUsocial
* @author Evan Prodromou <evan@status.net>
* @copyright 2011 StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
defined('GNUSOCIAL') || die();
/**
* A channel for real-time browser data
*
* @copyright 2011 StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*
* @see DB_DataObject
*/
@ -88,7 +79,7 @@ class Realtime_channel extends Managed_DataObject
'length' => 32,
'not null' => true,
'description' => 'shared secret key for this channel'),
'audience' => array('type' => 'integer',
'audience' => array('type' => 'int',
'not null' => true,
'default' => 0,
'description' => 'reference count'),
@ -111,7 +102,7 @@ class Realtime_channel extends Managed_DataObject
);
}
static function saveNew($user_id, $action, $arg1, $arg2)
public static function saveNew($user_id, $action, $arg1, $arg2)
{
$channel = new Realtime_channel();
@ -131,7 +122,7 @@ class Realtime_channel extends Managed_DataObject
return $channel;
}
static function getChannel($user_id, $action, $arg1, $arg2)
public static function getChannel($user_id, $action, $arg1, $arg2)
{
$channel = self::fetchChannel($user_id, $action, $arg1, $arg2);
@ -152,7 +143,7 @@ class Realtime_channel extends Managed_DataObject
return $channel;
}
static function getAllChannels($action, $arg1, $arg2)
public static function getAllChannels($action, $arg1, $arg2)
{
$channel = new Realtime_channel();
@ -170,9 +161,9 @@ class Realtime_channel extends Managed_DataObject
$channel->arg2 = $arg2;
}
$channel->whereAdd('modified > "' . common_sql_date(time() - self::TIMEOUT) . '"');
$channel->whereAdd(sprintf("modified > TIMESTAMP '%s'", common_sql_date(time() - self::TIMEOUT)));
$channels = array();
$channels = [];
if ($channel->find()) {
$channels = $channel->fetchAll();
@ -181,7 +172,7 @@ class Realtime_channel extends Managed_DataObject
return $channels;
}
static function fetchChannel($user_id, $action, $arg1, $arg2)
public static function fetchChannel($user_id, $action, $arg1, $arg2)
{
$channel = new Realtime_channel();
@ -213,7 +204,7 @@ class Realtime_channel extends Managed_DataObject
}
}
function increment()
public function increment()
{
// XXX: race
$orig = clone($this);
@ -222,7 +213,7 @@ class Realtime_channel extends Managed_DataObject
$this->update($orig);
}
function touch()
public function touch()
{
// XXX: race
$orig = clone($this);
@ -230,7 +221,7 @@ class Realtime_channel extends Managed_DataObject
$this->update($orig);
}
function decrement()
public function decrement()
{
// XXX: race
if ($this->audience == 1) {

View File

@ -1,23 +1,27 @@
#!/usr/bin/env php
<?php
// This file is part of GNU social - https://www.gnu.org/software/social
//
// GNU social is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
/*
* StatusNet - a distributed open-source microblogging tool
* Copyright (C) 2011, StatusNet, Inc.
*
* Script to print out current version of the software
*
* 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/>.
* @package Realtime
* @author Mikael Nordfeldth <mmn@hethane.se>
* @copyright 2011, StatusNet, Inc.
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
define('INSTALLDIR', realpath(__DIR__ . '/../../..'));
@ -42,7 +46,7 @@ function cleanupChannels()
$rc->selectAdd();
$rc->selectAdd('channel_key');
$rc->whereAdd('modified < "' . common_sql_date(time() - Realtime_channel::TIMEOUT) . '"');
$rc->whereAdd(sprintf("modified < TIMESTAMP '%s'", common_sql_date(time() - Realtime_channel::TIMEOUT)));
if ($rc->find()) {
$keys = $rc->fetchAll();

Some files were not shown because too many files have changed in this diff Show More