]> scripts.mit.edu Git - autoinstalls/mediawiki.git/blob - includes/api/ApiQueryUsers.php
MediaWiki 1.17.4
[autoinstalls/mediawiki.git] / includes / api / ApiQueryUsers.php
1 <?php
2 /**
3  * API for MediaWiki 1.8+
4  *
5  * Created on July 30, 2007
6  *
7  * Copyright © 2007 Roan Kattouw <Firstname>.<Lastname>@home.nl
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22  * http://www.gnu.org/copyleft/gpl.html
23  *
24  * @file
25  */
26
27 if ( !defined( 'MEDIAWIKI' ) ) {
28         // Eclipse helper - will be ignored in production
29         require_once( 'ApiQueryBase.php' );
30 }
31
32 /**
33  * Query module to get information about a list of users
34  *
35  * @ingroup API
36  */
37  class ApiQueryUsers extends ApiQueryBase {
38
39         private $tokenFunctions, $prop;
40
41         public function __construct( $query, $moduleName ) {
42                 parent::__construct( $query, $moduleName, 'us' );
43         }
44
45         /**
46          * Get an array mapping token names to their handler functions.
47          * The prototype for a token function is func($user)
48          * it should return a token or false (permission denied)
49          * @return Array tokenname => function
50          */
51         protected function getTokenFunctions() {
52                 // Don't call the hooks twice
53                 if ( isset( $this->tokenFunctions ) ) {
54                         return $this->tokenFunctions;
55                 }
56
57                 // If we're in JSON callback mode, no tokens can be obtained
58                 if ( !is_null( $this->getMain()->getRequest()->getVal( 'callback' ) ) ) {
59                         return array();
60                 }
61
62                 $this->tokenFunctions = array(
63                         'userrights' => array( 'ApiQueryUsers', 'getUserrightsToken' ),
64                 );
65                 wfRunHooks( 'APIQueryUsersTokens', array( &$this->tokenFunctions ) );
66                 return $this->tokenFunctions;
67         }
68
69         public static function getUserrightsToken( $user ) {
70                 global $wgUser;
71                 // Since the permissions check for userrights is non-trivial,
72                 // don't bother with it here
73                 return $wgUser->editToken( $user->getName() );
74         }
75
76         public function execute() {
77                 $params = $this->extractRequestParams();
78
79                 if ( !is_null( $params['prop'] ) ) {
80                         $this->prop = array_flip( $params['prop'] );
81                 } else {
82                         $this->prop = array();
83                 }
84
85                 $users = (array)$params['users'];
86                 $goodNames = $done = array();
87                 $result = $this->getResult();
88                 // Canonicalize user names
89                 foreach ( $users as $u ) {
90                         $n = User::getCanonicalName( $u );
91                         if ( $n === false || $n === '' ) {
92                                 $vals = array( 'name' => $u, 'invalid' => '' );
93                                 $fit = $result->addValue( array( 'query', $this->getModuleName() ),
94                                                 null, $vals );
95                                 if ( !$fit ) {
96                                         $this->setContinueEnumParameter( 'users',
97                                                         implode( '|', array_diff( $users, $done ) ) );
98                                         $goodNames = array();
99                                         break;
100                                 }
101                                 $done[] = $u;
102                         } else {
103                                 $goodNames[] = $n;
104                         }
105                 }
106
107                 if ( count( $goodNames ) ) {
108                         $this->addTables( 'user', 'u1' );
109                         $this->addFields( 'u1.*' );
110                         $this->addWhereFld( 'u1.user_name', $goodNames );
111
112                         if ( isset( $this->prop['groups'] ) ) {
113                                 $this->addTables( 'user_groups' );
114                                 $this->addJoinConds( array( 'user_groups' => array( 'LEFT JOIN', 'ug_user=u1.user_id' ) ) );
115                                 $this->addFields( 'ug_group' );
116                         }
117
118                         $this->showHiddenUsersAddBlockInfo( isset( $this->prop['blockinfo'] ) );
119
120                         $data = array();
121                         $res = $this->select( __METHOD__ );
122                         foreach ( $res as $row ) {
123                                 $user = User::newFromRow( $row );
124                                 $name = $user->getName();
125                                 $data[$name]['name'] = $name;
126
127                                 if ( isset( $this->prop['editcount'] ) ) {
128                                         $data[$name]['editcount'] = intval( $user->getEditCount() );
129                                 }
130
131                                 if ( isset( $this->prop['registration'] ) ) {
132                                         $data[$name]['registration'] = wfTimestampOrNull( TS_ISO_8601, $user->getRegistration() );
133                                 }
134
135                                 if ( isset( $this->prop['groups'] ) && !is_null( $row->ug_group ) ) {
136                                         // This row contains only one group, others will be added from other rows
137                                         $data[$name]['groups'][] = $row->ug_group;
138                                 }
139
140                                 if ( isset( $this->prop['rights'] ) && !is_null( $row->ug_group ) ) {
141                                         if ( !isset( $data[$name]['rights'] ) ) {
142                                                 $data[$name]['rights'] = User::getGroupPermissions( User::getImplicitGroups() );
143                                         }
144
145                                         $data[$name]['rights'] = array_unique( array_merge( $data[$name]['rights'],
146                                                 User::getGroupPermissions( array( $row->ug_group ) ) ) );
147                                         $result->setIndexedTagName( $data[$name]['rights'], 'r' );
148                                 }
149                                 if ( $row->ipb_deleted ) {
150                                         $data[$name]['hidden'] = '';
151                                 }
152                                 if ( isset( $this->prop['blockinfo'] ) && !is_null( $row->ipb_by_text ) ) {
153                                         $data[$name]['blockedby'] = $row->ipb_by_text;
154                                         $data[$name]['blockreason'] = $row->ipb_reason;
155                                         $data[$name]['blockexpiry'] = $row->ipb_expiry;
156                                 }
157
158                                 if ( isset( $this->prop['emailable'] ) && $user->canReceiveEmail() ) {
159                                         $data[$name]['emailable'] = '';
160                                 }
161
162                                 if ( isset( $this->prop['gender'] ) ) {
163                                         $gender = $user->getOption( 'gender' );
164                                         if ( strval( $gender ) === '' ) {
165                                                 $gender = 'unknown';
166                                         }
167                                         $data[$name]['gender'] = $gender;
168                                 }
169
170                                 if ( !is_null( $params['token'] ) ) {
171                                         $tokenFunctions = $this->getTokenFunctions();
172                                         foreach ( $params['token'] as $t ) {
173                                                 $val = call_user_func( $tokenFunctions[$t], $user );
174                                                 if ( $val === false ) {
175                                                         $this->setWarning( "Action '$t' is not allowed for the current user" );
176                                                 } else {
177                                                         $data[$name][$t . 'token'] = $val;
178                                                 }
179                                         }
180                                 }
181                         }
182                 }
183                 // Second pass: add result data to $retval
184                 foreach ( $goodNames as $u ) {
185                         if ( !isset( $data[$u] ) ) {
186                                 $data[$u] = array( 'name' => $u );
187                                 $urPage = new UserrightsPage;
188                                 $iwUser = $urPage->fetchUser( $u );
189
190                                 if ( $iwUser instanceof UserRightsProxy ) {
191                                         $data[$u]['interwiki'] = '';
192
193                                         if ( !is_null( $params['token'] ) ) {
194                                                 $tokenFunctions = $this->getTokenFunctions();
195
196                                                 foreach ( $params['token'] as $t ) {
197                                                         $val = call_user_func( $tokenFunctions[$t], $iwUser );
198                                                         if ( $val === false ) {
199                                                                 $this->setWarning( "Action '$t' is not allowed for the current user" );
200                                                         } else {
201                                                                 $data[$u][$t . 'token'] = $val;
202                                                         }
203                                                 }
204                                         }
205                                 } else {
206                                         $data[$u]['missing'] = '';
207                                 }
208                         } else {
209                                 if ( isset( $this->prop['groups'] ) && isset( $data[$u]['groups'] ) ) {
210                                         $autolist = ApiQueryUsers::getAutoGroups( User::newFromName( $u ) );
211
212                                         $data[$u]['groups'] = array_merge( $autolist, $data[$u]['groups'] );
213
214                                         $this->getResult()->setIndexedTagName( $data[$u]['groups'], 'g' );
215                                 }
216                         }
217                         $fit = $result->addValue( array( 'query', $this->getModuleName() ),
218                                         null, $data[$u] );
219                         if ( !$fit ) {
220                                 $this->setContinueEnumParameter( 'users',
221                                                 implode( '|', array_diff( $users, $done ) ) );
222                                 break;
223                         }
224                         $done[] = $u;
225                 }
226                 return $this->getResult()->setIndexedTagName_internal( array( 'query', $this->getModuleName() ), 'user' );
227         }
228
229         /**
230         * Gets all the groups that a user is automatically a member of
231         * @return array
232         */
233         public static function getAutoGroups( $user ) {
234                 $groups = array( '*' );
235
236                 if ( !$user->isAnon() ) {
237                         $groups[] = 'user';
238                 }
239
240                 return array_merge( $groups, Autopromote::getAutopromoteGroups( $user ) );
241         }
242
243         public function getCacheMode( $params ) {
244                 if ( isset( $params['token'] ) ) {
245                         return 'private';
246                 } else {
247                         return 'anon-public-user-private';
248                 }
249         }
250
251         public function getAllowedParams() {
252                 return array(
253                         'prop' => array(
254                                 ApiBase::PARAM_DFLT => null,
255                                 ApiBase::PARAM_ISMULTI => true,
256                                 ApiBase::PARAM_TYPE => array(
257                                         'blockinfo',
258                                         'groups',
259                                         'editcount',
260                                         'registration',
261                                         'emailable',
262                                         'gender',
263                                 )
264                         ),
265                         'users' => array(
266                                 ApiBase::PARAM_ISMULTI => true
267                         ),
268                         'token' => array(
269                                 ApiBase::PARAM_TYPE => array_keys( $this->getTokenFunctions() ),
270                                 ApiBase::PARAM_ISMULTI => true
271                         ),
272                 );
273         }
274
275         public function getParamDescription() {
276                 return array(
277                         'prop' => array(
278                                 'What pieces of information to include',
279                                 '  blockinfo    - Tags if the user is blocked, by whom, and for what reason',
280                                 '  groups       - Lists all the groups the user(s) belongs to',
281                                 '  rights       - Lists all the rights the user(s) has',
282                                 '  editcount    - Adds the user\'s edit count',
283                                 '  registration - Adds the user\'s registration timestamp',
284                                 '  emailable    - Tags if the user can and wants to receive e-mail through [[Special:Emailuser]]',
285                                 '  gender       - Tags the gender of the user. Returns "male", "female", or "unknown"',
286                         ),
287                         'users' => 'A list of users to obtain the same information for',
288                         'token' => 'Which tokens to obtain for each user',
289                 );
290         }
291
292         public function getDescription() {
293                 return 'Get information about a list of users';
294         }
295
296         protected function getExamples() {
297                 return 'api.php?action=query&list=users&ususers=brion|TimStarling&usprop=groups|editcount|gender';
298         }
299
300         public function getVersion() {
301                 return __CLASS__ . ': $Id$';
302         }
303 }