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