[DATABASE] Always quote identifiers

The code used to operate under the assumption that MariaDB doesn't support
quoting identifiers. Not only is that not exactly true, but MariaDB has
reserved keywords that cannot be used as table or column names unquoted.
This commit is contained in:
Alexei Sorokin 2019-09-11 08:15:16 +03:00 committed by Diogo Peralta Cordeiro
parent 1b41a38719
commit d26aac77b3
18 changed files with 1335 additions and 1191 deletions

View File

@ -178,9 +178,6 @@ 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.

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,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
@ -943,11 +945,10 @@ class File extends Managed_DataObject
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)'
'UPDATE %1$s SET urlhash = %2$s;',
$tablefix->escapedTableName(),
// The line below is "result of sha256 on column `url`"
'sha2(url, 256)'
));
echo "DONE.\n";
echo "Resuming core schema upgrade...";

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 file_redirection
@ -59,12 +56,13 @@ class File_redirection extends Managed_DataObject
);
}
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 +94,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 +129,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 +143,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 +173,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 +189,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 +206,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 +224,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 +258,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 +283,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 +308,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 +318,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 +359,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 +396,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 +415,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 +426,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 +440,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";
@ -435,16 +459,18 @@ class File_redirection extends Managed_DataObject
// 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)'));
$tablefix->query(sprintf(
'UPDATE %1$s SET urlhash = %2$s;',
$tablefix->escapedTableName(),
// The line below is "result of sha256 on column `url`"
'sha2(url, 256)'
));
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,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,7 +221,7 @@ abstract class Managed_DataObject extends Memcached_DataObject
* @param array $column
* @return int
*/
function columnBitmap($column)
public function columnBitmap($column)
{
$type = $column['type'];
@ -254,7 +257,7 @@ abstract class Managed_DataObject extends Memcached_DataObject
return $style;
}
function links()
public function links()
{
$links = array();
@ -277,7 +280,7 @@ abstract class Managed_DataObject extends Memcached_DataObject
*
* @return array of strings
*/
function _allCacheKeys()
public function _allCacheKeys()
{
$table = static::schemaDef();
$ckeys = array();
@ -322,7 +325,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 +359,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 +384,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 +397,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 +540,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 +581,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()

File diff suppressed because it is too large Load Diff

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,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
{
@ -79,7 +80,7 @@ class Profile_list extends Managed_DataObject
* @return Profile the tagger
*/
function getTagger()
public function getTagger()
{
return Profile::getByID($this->tagger);
}
@ -91,7 +92,7 @@ class Profile_list extends Managed_DataObject
* @return String
*/
function getBestName()
public function getBestName()
{
return $this->tag;
}
@ -102,15 +103,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 +126,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 +134,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 +153,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 +178,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 +199,7 @@ class Profile_list extends Managed_DataObject
* @return Profile results
*/
function getSubscribers($offset=0, $limit=null, $since=0, $upto=0)
public function getSubscribers($offset = 0, $limit = null, $since = 0, $upto = 0)
{
$subs = new Profile();
@ -227,24 +236,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 +271,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,7 +295,7 @@ class Profile_list extends Managed_DataObject
* @return Profile results
*/
function getTagged($offset=0, $limit=null, $since=0, $upto=0)
public function getTagged($offset = 0, $limit = null, $since = 0, $upto = 0)
{
$tagged = new Profile();
$tagged->joinAdd(array('id', 'profile_tag:tagged'));
@ -323,7 +330,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 +357,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 +368,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 +389,7 @@ class Profile_list extends Managed_DataObject
* @return string atom author element
*/
function asAtomAuthor()
public function asAtomAuthor()
{
$xs = new XMLStringer(true);
@ -404,7 +411,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 +426,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 +459,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 +488,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 +506,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 +524,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 +554,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 +573,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 +588,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 +650,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 +658,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 +698,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 +709,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 +745,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 +765,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 +784,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 +815,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 +847,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 +875,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 +924,7 @@ class Profile_list extends Managed_DataObject
}
}
function insert()
public function insert()
{
$result = parent::insert();
if ($result) {

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
@ -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,7 +258,7 @@ class User extends Managed_DataObject
}
}
if(isset($email_confirmed) && $email_confirmed) {
if (isset($email_confirmed) && $email_confirmed) {
$user->email = $email;
}
@ -278,7 +274,6 @@ class User extends Managed_DataObject
$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.* ' .
@ -863,14 +872,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 +952,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 +960,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 +977,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 +989,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 +1000,7 @@ class User extends Managed_DataObject
return false;
}
function registrationActivity()
public function registrationActivity()
{
$profile = $this->getProfile();
@ -1007,16 +1018,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;
@ -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,7 +295,8 @@ 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'));
@ -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) {
@ -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

@ -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
*/
@ -52,7 +52,6 @@ class PgsqlSchema extends Schema
* @return array tabledef for that table.
* @throws SchemaTableMissingException
*/
public function getTableDef($table)
{
$def = [];
@ -68,7 +67,6 @@ class PgsqlSchema extends Schema
$orderedFields = [];
foreach ($columns as $row) {
$name = $row['column_name'];
$orderedFields[$row['ordinal_position']] = $name;
@ -146,7 +144,7 @@ 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)) {
} elseif (preg_match("/^{$table}_(.*)_fkey$/", $keyName, $matches)) {
$fkey = $this->getForeignKeyInfo($table, $keyName);
$colMap = array_combine($cols, $fkey['col_names']);
$def['foreign keys'][$keyName] = [$fkey['table_name'], $colMap];
@ -166,7 +164,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,7 +181,7 @@ class PgsqlSchema extends Schema
* @return array of arrays
* @throws PEAR_Exception
*/
function getIndexInfo($table)
public function getIndexInfo($table)
{
$query = 'SELECT ' .
'(SELECT relname FROM pg_class WHERE oid=indexrelid) AS key_name, ' .
@ -202,7 +200,7 @@ class PgsqlSchema extends Schema
* @return array array of rows with keys: fkey_name, table_name, table_id, col_names (array of strings)
* @throws PEAR_Exception
*/
function getForeignKeyInfo($table, $constraint_name)
public function getForeignKeyInfo($table, $constraint_name)
{
// In a sane world, it'd be easier to query the column names directly.
// But it's pretty hard to work with arrays such as col_indexes in direct SQL here.
@ -234,7 +232,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 ' .
@ -284,7 +282,7 @@ class PgsqlSchema extends Schema
* @return string correct SQL for that column
*/
function columnSql(array $cd)
public function columnSql(array $cd)
{
$line = [];
$line[] = parent::columnSql($cd);
@ -311,7 +309,7 @@ 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) . ' ';
@ -323,13 +321,13 @@ class PgsqlSchema extends Schema
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);
}
}
@ -342,23 +340,12 @@ 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.
@ -377,7 +364,7 @@ class PgsqlSchema extends Schema
$size = $column['size'];
if ($size == 'small') {
return 'int2';
} else if ($size == 'big') {
} elseif ($size == 'big') {
return 'int8';
}
}
@ -388,7 +375,7 @@ class PgsqlSchema extends Schema
}
// @fixme need name... :P
function typeAndSize($column)
public function typeAndSize($column)
{
if ($column['type'] == 'enum') {
$vals = array_map([$this, 'quote'], $column['enum']);
@ -408,7 +395,7 @@ 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
@ -443,7 +430,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,10 @@ class Schema
* Main public entry point. Use this to get
* the schema object.
*
* @param null $conn
* @param object|null $conn
* @return Schema the Schema object for the connection
*/
static function get($conn = null)
public static function get($conn = null)
{
if (is_null($conn)) {
$key = 'default';
@ -95,7 +93,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 +117,6 @@ class Schema
* @return bool success flag
* @throws PEAR_Exception
*/
public function createTable($tableName, $def)
{
$statements = $this->buildCreateTable($tableName, $def);
@ -194,7 +190,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 +202,7 @@ class Schema
* @param array $def table definition
* @return string
*/
function endCreateTable($name, array $def)
public function endCreateTable($name, array $def)
{
return ')';
}
@ -218,9 +214,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 +226,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 +239,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 +253,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 +261,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 +278,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 +294,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 +306,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 +336,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,7 +365,6 @@ class Schema
* @return bool success flag
* @throws PEAR_Exception
*/
public function createIndex($table, $columnNames, $name = null)
{
global $_PEAR;
@ -382,9 +377,11 @@ class Schema
$name = "{$table}_" . implode("_", $columnNames) . "_idx";
}
$res = $this->conn->query("ALTER TABLE $table " .
"ADD INDEX $name (" .
implode(",", $columnNames) . ")");
$res = $this->conn->query(
'ALTER TABLE ' . $this->quoteIdentifier($table) .
' ADD INDEX ' . $name . ' (' .
implode(',', $columnNames) . ')'
);
if ($_PEAR->isError($res)) {
PEAR_ErrorToPEAR_Exception($res);
@ -402,12 +399,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 +425,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 +452,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 +479,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 +509,6 @@ class Schema
* @return bool success flag
* @throws PEAR_Exception
*/
public function ensureTable($tableName, $def)
{
$statements = $this->buildEnsureTable($tableName, $def);
@ -527,7 +524,7 @@ class Schema
* @return bool success flag
* @throws PEAR_Exception
*/
function runSqlSet(array $statements)
public function runSqlSet(array $statements)
{
global $_PEAR;
@ -561,8 +558,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);
@ -610,14 +606,20 @@ class Schema
}
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 +641,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 +659,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,7 +704,7 @@ 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) .
@ -718,7 +721,7 @@ 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) .
@ -733,12 +736,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 +749,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 +757,7 @@ class Schema
$phrase[] = implode(' ', $sql);
}
function appendAlterAddPrimary(array &$phrase, array $def)
public function appendAlterAddPrimary(array &$phrase, array $def)
{
$sql = [];
$sql[] = 'ADD';
@ -762,22 +765,22 @@ class Schema
$phrase[] = implode(' ', $sql);
}
function appendAlterDropPrimary(array &$phrase)
public function appendAlterDropPrimary(array &$phrase)
{
$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 +791,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 +819,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 +832,6 @@ class Schema
*
* @return array strings for name values
*/
protected function _names($cds)
{
$names = [];
@ -850,7 +852,6 @@ class Schema
*
* @return ColumnDef matching item or null if no match.
*/
protected function _byName($cds, $name)
{
foreach ($cds as $cd) {
@ -874,7 +875,7 @@ class Schema
* @return string correct SQL for that column
*/
function columnSql(array $cd)
public function columnSql(array $cd)
{
$line = [];
$line[] = $this->typeAndSize($cd);
@ -882,7 +883,7 @@ class Schema
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 +896,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(array $column)
{
//$type = $this->mapType($column);
//$type = $this->mapType($column)['type'];
$type = $column['type'];
if (isset($column['size'])) {
$type = $column['size'] . $type;
@ -914,7 +915,7 @@ class Schema
if (isset($column['scale'])) {
$lengths[] = $column['scale'];
}
} else if (isset($column['length'])) {
} elseif (isset($column['length'])) {
$lengths[] = $column['length'];
}
@ -977,12 +978,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 +1004,7 @@ class Schema
* @param array $tableDef
* @return array
*/
function filterDef(array $tableDef)
public function filterDef(array $tableDef)
{
return $tableDef;
}
@ -1019,7 +1020,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 +1034,7 @@ class Schema
return $def;
}
function isNumericType($type)
public function isNumericType($type)
{
$type = strtolower($type);
$known = ['int', 'serial', 'numeric'];
@ -1074,20 +1075,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,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,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

@ -446,7 +446,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 +456,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

@ -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 = 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:
$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,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

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