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