MediaWiki  REL1_22
ApiQueryUsers.php
Go to the documentation of this file.
00001 <?php
00032 class ApiQueryUsers extends ApiQueryBase {
00033 
00034     private $tokenFunctions, $prop;
00035 
00036     public function __construct( $query, $moduleName ) {
00037         parent::__construct( $query, $moduleName, 'us' );
00038     }
00039 
00046     protected function getTokenFunctions() {
00047         // Don't call the hooks twice
00048         if ( isset( $this->tokenFunctions ) ) {
00049             return $this->tokenFunctions;
00050         }
00051 
00052         // If we're in JSON callback mode, no tokens can be obtained
00053         if ( !is_null( $this->getMain()->getRequest()->getVal( 'callback' ) ) ) {
00054             return array();
00055         }
00056 
00057         $this->tokenFunctions = array(
00058             'userrights' => array( 'ApiQueryUsers', 'getUserrightsToken' ),
00059         );
00060         wfRunHooks( 'APIQueryUsersTokens', array( &$this->tokenFunctions ) );
00061         return $this->tokenFunctions;
00062     }
00063 
00068     public static function getUserrightsToken( $user ) {
00069         global $wgUser;
00070         // Since the permissions check for userrights is non-trivial,
00071         // don't bother with it here
00072         return $wgUser->getEditToken( $user->getName() );
00073     }
00074 
00075     public function execute() {
00076         $params = $this->extractRequestParams();
00077 
00078         if ( !is_null( $params['prop'] ) ) {
00079             $this->prop = array_flip( $params['prop'] );
00080         } else {
00081             $this->prop = array();
00082         }
00083 
00084         $users = (array)$params['users'];
00085         $goodNames = $done = array();
00086         $result = $this->getResult();
00087         // Canonicalize user names
00088         foreach ( $users as $u ) {
00089             $n = User::getCanonicalName( $u );
00090             if ( $n === false || $n === '' ) {
00091                 $vals = array( 'name' => $u, 'invalid' => '' );
00092                 $fit = $result->addValue( array( 'query', $this->getModuleName() ),
00093                         null, $vals );
00094                 if ( !$fit ) {
00095                     $this->setContinueEnumParameter( 'users',
00096                             implode( '|', array_diff( $users, $done ) ) );
00097                     $goodNames = array();
00098                     break;
00099                 }
00100                 $done[] = $u;
00101             } else {
00102                 $goodNames[] = $n;
00103             }
00104         }
00105 
00106         $result = $this->getResult();
00107 
00108         if ( count( $goodNames ) ) {
00109             $this->addTables( 'user' );
00110             $this->addFields( User::selectFields() );
00111             $this->addWhereFld( 'user_name', $goodNames );
00112 
00113             $this->showHiddenUsersAddBlockInfo( isset( $this->prop['blockinfo'] ) );
00114 
00115             $data = array();
00116             $res = $this->select( __METHOD__ );
00117             $this->resetQueryParams();
00118 
00119             // get user groups if needed
00120             if ( isset( $this->prop['groups'] ) || isset( $this->prop['rights'] ) ) {
00121                 $userGroups = array();
00122 
00123                 $this->addTables( 'user' );
00124                 $this->addWhereFld( 'user_name', $goodNames );
00125                 $this->addTables( 'user_groups' );
00126                 $this->addJoinConds( array( 'user_groups' => array( 'INNER JOIN', 'ug_user=user_id' ) ) );
00127                 $this->addFields( array( 'user_name', 'ug_group' ) );
00128                 $userGroupsRes = $this->select( __METHOD__ );
00129 
00130                 foreach ( $userGroupsRes as $row ) {
00131                     $userGroups[$row->user_name][] = $row->ug_group;
00132                 }
00133             }
00134 
00135             foreach ( $res as $row ) {
00136                 // create user object and pass along $userGroups if set
00137                 // that reduces the number of database queries needed in User dramatically
00138                 if ( !isset( $userGroups ) ) {
00139                     $user = User::newFromRow( $row );
00140                 } else {
00141                     if ( !isset( $userGroups[$row->user_name] ) || !is_array( $userGroups[$row->user_name] ) ) {
00142                         $userGroups[$row->user_name] = array();
00143                     }
00144                     $user = User::newFromRow( $row, array( 'user_groups' => $userGroups[$row->user_name] ) );
00145                 }
00146                 $name = $user->getName();
00147 
00148                 $data[$name]['userid'] = $user->getId();
00149                 $data[$name]['name'] = $name;
00150 
00151                 if ( isset( $this->prop['editcount'] ) ) {
00152                     $data[$name]['editcount'] = $user->getEditCount();
00153                 }
00154 
00155                 if ( isset( $this->prop['registration'] ) ) {
00156                     $data[$name]['registration'] = wfTimestampOrNull( TS_ISO_8601, $user->getRegistration() );
00157                 }
00158 
00159                 if ( isset( $this->prop['groups'] ) ) {
00160                     $data[$name]['groups'] = $user->getEffectiveGroups();
00161                 }
00162 
00163                 if ( isset( $this->prop['implicitgroups'] ) ) {
00164                     $data[$name]['implicitgroups'] = $user->getAutomaticGroups();
00165                 }
00166 
00167                 if ( isset( $this->prop['rights'] ) ) {
00168                     $data[$name]['rights'] = $user->getRights();
00169                 }
00170                 if ( $row->ipb_deleted ) {
00171                     $data[$name]['hidden'] = '';
00172                 }
00173                 if ( isset( $this->prop['blockinfo'] ) && !is_null( $row->ipb_by_text ) ) {
00174                     $data[$name]['blockid'] = $row->ipb_id;
00175                     $data[$name]['blockedby'] = $row->ipb_by_text;
00176                     $data[$name]['blockedbyid'] = $row->ipb_by;
00177                     $data[$name]['blockreason'] = $row->ipb_reason;
00178                     $data[$name]['blockexpiry'] = $row->ipb_expiry;
00179                 }
00180 
00181                 if ( isset( $this->prop['emailable'] ) && $user->canReceiveEmail() ) {
00182                     $data[$name]['emailable'] = '';
00183                 }
00184 
00185                 if ( isset( $this->prop['gender'] ) ) {
00186                     $gender = $user->getOption( 'gender' );
00187                     if ( strval( $gender ) === '' ) {
00188                         $gender = 'unknown';
00189                     }
00190                     $data[$name]['gender'] = $gender;
00191                 }
00192 
00193                 if ( !is_null( $params['token'] ) ) {
00194                     $tokenFunctions = $this->getTokenFunctions();
00195                     foreach ( $params['token'] as $t ) {
00196                         $val = call_user_func( $tokenFunctions[$t], $user );
00197                         if ( $val === false ) {
00198                             $this->setWarning( "Action '$t' is not allowed for the current user" );
00199                         } else {
00200                             $data[$name][$t . 'token'] = $val;
00201                         }
00202                     }
00203                 }
00204             }
00205         }
00206 
00207         $context = $this->getContext();
00208         // Second pass: add result data to $retval
00209         foreach ( $goodNames as $u ) {
00210             if ( !isset( $data[$u] ) ) {
00211                 $data[$u] = array( 'name' => $u );
00212                 $urPage = new UserrightsPage;
00213                 $urPage->setContext( $context );
00214                 $iwUser = $urPage->fetchUser( $u );
00215 
00216                 if ( $iwUser instanceof UserRightsProxy ) {
00217                     $data[$u]['interwiki'] = '';
00218 
00219                     if ( !is_null( $params['token'] ) ) {
00220                         $tokenFunctions = $this->getTokenFunctions();
00221 
00222                         foreach ( $params['token'] as $t ) {
00223                             $val = call_user_func( $tokenFunctions[$t], $iwUser );
00224                             if ( $val === false ) {
00225                                 $this->setWarning( "Action '$t' is not allowed for the current user" );
00226                             } else {
00227                                 $data[$u][$t . 'token'] = $val;
00228                             }
00229                         }
00230                     }
00231                 } else {
00232                     $data[$u]['missing'] = '';
00233                 }
00234             } else {
00235                 if ( isset( $this->prop['groups'] ) && isset( $data[$u]['groups'] ) ) {
00236                     $result->setIndexedTagName( $data[$u]['groups'], 'g' );
00237                 }
00238                 if ( isset( $this->prop['implicitgroups'] ) && isset( $data[$u]['implicitgroups'] ) ) {
00239                     $result->setIndexedTagName( $data[$u]['implicitgroups'], 'g' );
00240                 }
00241                 if ( isset( $this->prop['rights'] ) && isset( $data[$u]['rights'] ) ) {
00242                     $result->setIndexedTagName( $data[$u]['rights'], 'r' );
00243                 }
00244             }
00245 
00246             $fit = $result->addValue( array( 'query', $this->getModuleName() ),
00247                     null, $data[$u] );
00248             if ( !$fit ) {
00249                 $this->setContinueEnumParameter( 'users',
00250                         implode( '|', array_diff( $users, $done ) ) );
00251                 break;
00252             }
00253             $done[] = $u;
00254         }
00255         $result->setIndexedTagName_internal( array( 'query', $this->getModuleName() ), 'user' );
00256     }
00257 
00265     public static function getAutoGroups( $user ) {
00266         wfDeprecated( __METHOD__, '1.20' );
00267 
00268         return $user->getAutomaticGroups();
00269     }
00270 
00271     public function getCacheMode( $params ) {
00272         if ( isset( $params['token'] ) ) {
00273             return 'private';
00274         } else {
00275             return 'anon-public-user-private';
00276         }
00277     }
00278 
00279     public function getAllowedParams() {
00280         return array(
00281             'prop' => array(
00282                 ApiBase::PARAM_DFLT => null,
00283                 ApiBase::PARAM_ISMULTI => true,
00284                 ApiBase::PARAM_TYPE => array(
00285                     'blockinfo',
00286                     'groups',
00287                     'implicitgroups',
00288                     'rights',
00289                     'editcount',
00290                     'registration',
00291                     'emailable',
00292                     'gender',
00293                 )
00294             ),
00295             'users' => array(
00296                 ApiBase::PARAM_ISMULTI => true
00297             ),
00298             'token' => array(
00299                 ApiBase::PARAM_TYPE => array_keys( $this->getTokenFunctions() ),
00300                 ApiBase::PARAM_ISMULTI => true
00301             ),
00302         );
00303     }
00304 
00305     public function getParamDescription() {
00306         return array(
00307             'prop' => array(
00308                 'What pieces of information to include',
00309                 '  blockinfo      - Tags if the user is blocked, by whom, and for what reason',
00310                 '  groups         - Lists all the groups the user(s) belongs to',
00311                 '  implicitgroups - Lists all the groups a user is automatically a member of',
00312                 '  rights         - Lists all the rights the user(s) has',
00313                 '  editcount      - Adds the user\'s edit count',
00314                 '  registration   - Adds the user\'s registration timestamp',
00315                 '  emailable      - Tags if the user can and wants to receive email through [[Special:Emailuser]]',
00316                 '  gender         - Tags the gender of the user. Returns "male", "female", or "unknown"',
00317             ),
00318             'users' => 'A list of users to obtain the same information for',
00319             'token' => 'Which tokens to obtain for each user',
00320         );
00321     }
00322 
00323     public function getResultProperties() {
00324         $props = array(
00325             '' => array(
00326                 'userid' => array(
00327                     ApiBase::PROP_TYPE => 'integer',
00328                     ApiBase::PROP_NULLABLE => true
00329                 ),
00330                 'name' => 'string',
00331                 'invalid' => 'boolean',
00332                 'hidden' => 'boolean',
00333                 'interwiki' => 'boolean',
00334                 'missing' => 'boolean'
00335             ),
00336             'editcount' => array(
00337                 'editcount' => array(
00338                     ApiBase::PROP_TYPE => 'integer',
00339                     ApiBase::PROP_NULLABLE => true
00340                 )
00341             ),
00342             'registration' => array(
00343                 'registration' => array(
00344                     ApiBase::PROP_TYPE => 'timestamp',
00345                     ApiBase::PROP_NULLABLE => true
00346                 )
00347             ),
00348             'blockinfo' => array(
00349                 'blockid' => array(
00350                     ApiBase::PROP_TYPE => 'integer',
00351                     ApiBase::PROP_NULLABLE => true
00352                 ),
00353                 'blockedby' => array(
00354                     ApiBase::PROP_TYPE => 'string',
00355                     ApiBase::PROP_NULLABLE => true
00356                 ),
00357                 'blockedbyid' => array(
00358                     ApiBase::PROP_TYPE => 'integer',
00359                     ApiBase::PROP_NULLABLE => true
00360                 ),
00361                 'blockedreason' => array(
00362                     ApiBase::PROP_TYPE => 'string',
00363                     ApiBase::PROP_NULLABLE => true
00364                 ),
00365                 'blockedexpiry' => array(
00366                     ApiBase::PROP_TYPE => 'timestamp',
00367                     ApiBase::PROP_NULLABLE => true
00368                 )
00369             ),
00370             'emailable' => array(
00371                 'emailable' => 'boolean'
00372             ),
00373             'gender' => array(
00374                 'gender' => array(
00375                     ApiBase::PROP_TYPE => array(
00376                         'male',
00377                         'female',
00378                         'unknown'
00379                     ),
00380                     ApiBase::PROP_NULLABLE => true
00381                 )
00382             )
00383         );
00384 
00385         self::addTokenProperties( $props, $this->getTokenFunctions() );
00386 
00387         return $props;
00388     }
00389 
00390     public function getDescription() {
00391         return 'Get information about a list of users';
00392     }
00393 
00394     public function getExamples() {
00395         return 'api.php?action=query&list=users&ususers=brion|TimStarling&usprop=groups|editcount|gender';
00396     }
00397 
00398     public function getHelpUrls() {
00399         return 'https://www.mediawiki.org/wiki/API:Users';
00400     }
00401 }