* This means queries could possibly return fewer results than the limit and still set a query-continue * Add iicontinue, rvcontinue, cicontinue, incontinue, amfrom to faciliate query-continue for these modules * Implemented by blocking additions to the ApiResult object if they would make it too large ** Important things like query-continue values and warnings are exempt from this check ** RSS feeds and exported XML are also exempted (size-checking them would be too messy) ** Result size is checked against $wgAPIMaxResultSize, which defaults to 8 MB For those who really care, per-file details follow: ApiResult.php: * Introduced ApiResult::$mSize which keeps track of the result size. * Introduced ApiResult::size() which calculates an array's size (which is the sum of the strlen()s of its elements). * ApiResult::addValue() now checks that the result size stays below $wgAPIMaxResultSize. If the item won't fit, it won't be added and addValue() will return false. Callers should check the return value and set a query-continue if it's false. * Closed the back door that is ApiResult::getData(): callers can't manipulate the data array directly anymore so they can't bypass the result size limit. * Added ApiResult::setIndexedTagName_internal() which will call setIndexedTagName() on an array already in the result. This is needed for the 'new' order of adding results, which means addValue()ing one result at a time until you hit the limit or run out, then calling this function to set the tag name. * Added ApiResult::disableSizeCheck() and enableSizeCheck() which disable and enable size checking in addValue(). This is used for stuff like query-continue elements and warnings which shouldn't count towards the result size. * Added ApiResult::unsetValue() which removes an element from the result and decreases $mSize. ApiBase.php: * Like ApiResult::getData(), ApiBase::getResultData() no longer returns a reference. * Use ApiResult::disableSizeCheck() in ApiBase::setWarning() ApiQueryBase.php: * Added ApiQueryBase::addPageSubItem(), which adds page subitems one item at a time. * addPageSubItem() and addPageSubItems() now return whether the subitem fit in the result. * Use ApiResult::disableSizeCheck() in setContinueEnumParameter() ApiMain.php: * Use ApiResult::disableSizeCheck() in ApiMain::substituteResultWithError() * Use getParameter() rather than $mRequest to obtain requestid DefaultSettings.php: * Added $wgAPIMaxResultSize, with a default value of 8 MB ApiQuery*.php: * Added results one at a time, and set a query-continue if the result is full. ApiQueryLangLinks.php and friends: * Migrated from addPageSubItems() to addPageSubItem(). This eliminates the need for $lastId. ApiQueryAllLinks.php, ApiQueryWatchlist.php, ApiQueryAllimages.php, ApiQuerySearch.php: * Renamed $data to something more appropriate ($pageids, $ids or $titles) ApiQuerySiteinfo.php: * Abuse siprop as a query-continue parameter and set it to all props that couldn't be processed. ApiQueryRandom.php: * Doesn't do continuations, because the result is supposed to be random. * Be smart enough to not run the second query if the results of the first didn't fit. ApiQueryImageInfo.php, ApiQueryRevisions.php, ApiQueryCategoryInfo.php, ApiQueryInfo.php: * Added continue parameter which basically skips the first so many items ApiQueryBacklinks.php: * Throw the result in a big array first and addValue() that one element at a time if necessary ** This is necessary because the results aren't retrieved in order * Introduced $this->pageMap to map namespace and title to page ID * Rewritten extractRowInfo() and extractRedirRowInfo() a little * Declared all private member variables explicitly ApiQueryDeletedrevs.php: * Use a pagemap just like in Backlinks * Introduce fake page IDs and keep track of them so we know where to add what ** This doesn't change the output format, because the fake page IDs start at 0 and are consecutive ApiQueryAllmessages.php: * Add amfrom to facilitate query-continue ApiQueryUsers.php: * Rewrite: put the getOtherUsersInfo() code in execute()
178 lines
5.4 KiB
PHP
178 lines
5.4 KiB
PHP
<?php
|
|
|
|
/*
|
|
* Created on July 30, 2007
|
|
*
|
|
* API for MediaWiki 1.8+
|
|
*
|
|
* Copyright (C) 2007 Roan Kattouw <Firstname>.<Lastname>@home.nl
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 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 General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
* http://www.gnu.org/copyleft/gpl.html
|
|
*/
|
|
|
|
if (!defined('MEDIAWIKI')) {
|
|
// Eclipse helper - will be ignored in production
|
|
require_once ('ApiQueryBase.php');
|
|
}
|
|
|
|
/**
|
|
* Query module to get information about a list of users
|
|
*
|
|
* @ingroup API
|
|
*/
|
|
|
|
class ApiQueryUsers extends ApiQueryBase {
|
|
|
|
public function __construct($query, $moduleName) {
|
|
parent :: __construct($query, $moduleName, 'us');
|
|
}
|
|
|
|
public function execute() {
|
|
$params = $this->extractRequestParams();
|
|
$result = $this->getResult();
|
|
$r = array();
|
|
|
|
if (!is_null($params['prop'])) {
|
|
$this->prop = array_flip($params['prop']);
|
|
} else {
|
|
$this->prop = array();
|
|
}
|
|
|
|
$users = (array)$params['users'];
|
|
$goodNames = $done = array();
|
|
$result = $this->getResult();
|
|
// Canonicalize user names
|
|
foreach($users as $u) {
|
|
$n = User::getCanonicalName($u);
|
|
if($n === false || $n === '')
|
|
{
|
|
$vals = array('name' => $u, 'invalid' => '');
|
|
$fit = $result->addValue(array('query', $this->getModuleName()),
|
|
null, $vals);
|
|
if(!$fit)
|
|
{
|
|
$this->setContinueEnumParameter('users',
|
|
implode('|', array_diff($users, $done)));
|
|
$goodNames = array();
|
|
break;
|
|
}
|
|
$done[] = $u;
|
|
}
|
|
else
|
|
$goodNames[] = $n;
|
|
}
|
|
if(count($goodNames))
|
|
{
|
|
$db = $this->getDb();
|
|
$this->addTables('user', 'u1');
|
|
$this->addFields('u1.user_name');
|
|
$this->addWhereFld('u1.user_name', $goodNames);
|
|
$this->addFieldsIf('u1.user_editcount', isset($this->prop['editcount']));
|
|
$this->addFieldsIf('u1.user_registration', isset($this->prop['registration']));
|
|
|
|
if(isset($this->prop['groups'])) {
|
|
$this->addTables('user_groups');
|
|
$this->addJoinConds(array('user_groups' => array('LEFT JOIN', 'ug_user=u1.user_id')));
|
|
$this->addFields('ug_group');
|
|
}
|
|
if(isset($this->prop['blockinfo'])) {
|
|
$this->addTables('ipblocks');
|
|
$this->addTables('user', 'u2');
|
|
$u2 = $this->getAliasedName('user', 'u2');
|
|
$this->addJoinConds(array(
|
|
'ipblocks' => array('LEFT JOIN', 'ipb_user=u1.user_id'),
|
|
$u2 => array('LEFT JOIN', 'ipb_by=u2.user_id')));
|
|
$this->addFields(array('ipb_reason', 'u2.user_name blocker_name'));
|
|
}
|
|
|
|
$data = array();
|
|
$res = $this->select(__METHOD__);
|
|
while(($r = $db->fetchObject($res))) {
|
|
$data[$r->user_name]['name'] = $r->user_name;
|
|
if(isset($this->prop['editcount']))
|
|
$data[$r->user_name]['editcount'] = $r->user_editcount;
|
|
if(isset($this->prop['registration']))
|
|
$data[$r->user_name]['registration'] = wfTimestampOrNull(TS_ISO_8601, $r->user_registration);
|
|
if(isset($this->prop['groups']))
|
|
// This row contains only one group, others will be added from other rows
|
|
if(!is_null($r->ug_group))
|
|
$data[$r->user_name]['groups'][] = $r->ug_group;
|
|
if(isset($this->prop['blockinfo']))
|
|
if(!is_null($r->blocker_name)) {
|
|
$data[$r->user_name]['blockedby'] = $r->blocker_name;
|
|
$data[$r->user_name]['blockreason'] = $r->ipb_reason;
|
|
}
|
|
}
|
|
}
|
|
// Second pass: add result data to $retval
|
|
foreach($goodNames as $u) {
|
|
if(!isset($data[$u]))
|
|
$retval[] = array('name' => $u, 'missing' => '');
|
|
else {
|
|
if(isset($this->prop['groups']) && isset($data[$u]['groups']))
|
|
$this->getResult()->setIndexedTagName($data[$u]['groups'], 'g');
|
|
$retval[] = $data[$u];
|
|
}
|
|
$done[] = $u;
|
|
}
|
|
return $this->getResult()->setIndexedTagName_internal(array('query', $this->getModuleName()), 'user');
|
|
}
|
|
|
|
public function getAllowedParams() {
|
|
return array (
|
|
'prop' => array (
|
|
ApiBase :: PARAM_DFLT => NULL,
|
|
ApiBase :: PARAM_ISMULTI => true,
|
|
ApiBase :: PARAM_TYPE => array (
|
|
'blockinfo',
|
|
'groups',
|
|
'editcount',
|
|
'registration',
|
|
'emailable',
|
|
)
|
|
),
|
|
'users' => array(
|
|
ApiBase :: PARAM_ISMULTI => true
|
|
)
|
|
);
|
|
}
|
|
|
|
public function getParamDescription() {
|
|
return array (
|
|
'prop' => array(
|
|
'What pieces of information to include',
|
|
' blockinfo - tags if the user is blocked, by whom, and for what reason',
|
|
' groups - lists all the groups the user belongs to',
|
|
' editcount - adds the user\'s edit count',
|
|
' registration - adds the user\'s registration timestamp',
|
|
' emailable - tags if the user can and wants to receive e-mail through [[Special:Emailuser]]',
|
|
),
|
|
'users' => 'A list of users to obtain the same information for'
|
|
);
|
|
}
|
|
|
|
public function getDescription() {
|
|
return 'Get information about a list of users';
|
|
}
|
|
|
|
protected function getExamples() {
|
|
return 'api.php?action=query&list=users&ususers=brion|TimStarling&usprop=groups|editcount';
|
|
}
|
|
|
|
public function getVersion() {
|
|
return __CLASS__ . ': $Id$';
|
|
}
|
|
}
|