MediaWiki  1.34.0
ApiQueryUserInfo.php
Go to the documentation of this file.
1 <?php
25 
32 
33  use ApiBlockInfoTrait;
34 
35  const WL_UNREAD_LIMIT = 1000;
36 
38  private $params = [];
40  private $prop = [];
41 
42  public function __construct( ApiQuery $query, $moduleName ) {
43  parent::__construct( $query, $moduleName, 'ui' );
44  }
45 
46  public function execute() {
47  $this->params = $this->extractRequestParams();
48  $result = $this->getResult();
49 
50  if ( !is_null( $this->params['prop'] ) ) {
51  $this->prop = array_flip( $this->params['prop'] );
52  }
53 
54  $r = $this->getCurrentUserInfo();
55  $result->addValue( 'query', $this->getModuleName(), $r );
56  }
57 
65  public static function getBlockInfo( AbstractBlock $block ) {
66  wfDeprecated( __METHOD__, '1.34' );
67 
68  // Hack to access a private method from a trait:
69  $dummy = new class {
70  use ApiBlockInfoTrait {
71  getBlockDetails as public;
72  }
73  };
74 
75  return $dummy->getBlockDetails( $block );
76  }
77 
90  public static function getCentralUserInfo( Config $config, User $user, $attachedWiki = null ) {
91  $providerIds = array_keys( $config->get( 'CentralIdLookupProviders' ) );
92 
93  $ret = [
94  'centralids' => [],
95  'attachedlocal' => [],
96  ];
97  ApiResult::setArrayType( $ret['centralids'], 'assoc' );
98  ApiResult::setArrayType( $ret['attachedlocal'], 'assoc' );
99  if ( $attachedWiki ) {
100  $ret['attachedwiki'] = [];
101  ApiResult::setArrayType( $ret['attachedwiki'], 'assoc' );
102  }
103 
104  $name = $user->getName();
105  foreach ( $providerIds as $providerId ) {
106  $provider = CentralIdLookup::factory( $providerId );
107  $ret['centralids'][$providerId] = $provider->centralIdFromName( $name );
108  $ret['attachedlocal'][$providerId] = $provider->isAttached( $user );
109  if ( $attachedWiki ) {
110  $ret['attachedwiki'][$providerId] = $provider->isAttached( $user, $attachedWiki );
111  }
112  }
113 
114  return $ret;
115  }
116 
117  protected function getCurrentUserInfo() {
118  $user = $this->getUser();
119  $vals = [];
120  $vals['id'] = (int)$user->getId();
121  $vals['name'] = $user->getName();
122 
123  if ( $user->isAnon() ) {
124  $vals['anon'] = true;
125  }
126 
127  if ( isset( $this->prop['blockinfo'] ) ) {
128  $block = $user->getBlock();
129  if ( $block ) {
130  $vals = array_merge( $vals, $this->getBlockDetails( $block ) );
131  }
132  }
133 
134  if ( isset( $this->prop['hasmsg'] ) ) {
135  $vals['messages'] = $user->getNewtalk();
136  }
137 
138  if ( isset( $this->prop['groups'] ) ) {
139  $vals['groups'] = $user->getEffectiveGroups();
140  ApiResult::setArrayType( $vals['groups'], 'array' ); // even if empty
141  ApiResult::setIndexedTagName( $vals['groups'], 'g' ); // even if empty
142  }
143 
144  if ( isset( $this->prop['groupmemberships'] ) ) {
145  $ugms = $user->getGroupMemberships();
146  $vals['groupmemberships'] = [];
147  foreach ( $ugms as $group => $ugm ) {
148  $vals['groupmemberships'][] = [
149  'group' => $group,
150  'expiry' => ApiResult::formatExpiry( $ugm->getExpiry() ),
151  ];
152  }
153  ApiResult::setArrayType( $vals['groupmemberships'], 'array' ); // even if empty
154  ApiResult::setIndexedTagName( $vals['groupmemberships'], 'groupmembership' ); // even if empty
155  }
156 
157  if ( isset( $this->prop['implicitgroups'] ) ) {
158  $vals['implicitgroups'] = $user->getAutomaticGroups();
159  ApiResult::setArrayType( $vals['implicitgroups'], 'array' ); // even if empty
160  ApiResult::setIndexedTagName( $vals['implicitgroups'], 'g' ); // even if empty
161  }
162 
163  if ( isset( $this->prop['rights'] ) ) {
164  $vals['rights'] = $this->getPermissionManager()->getUserPermissions( $user );
165  ApiResult::setArrayType( $vals['rights'], 'array' ); // even if empty
166  ApiResult::setIndexedTagName( $vals['rights'], 'r' ); // even if empty
167  }
168 
169  if ( isset( $this->prop['changeablegroups'] ) ) {
170  $vals['changeablegroups'] = $user->changeableGroups();
171  ApiResult::setIndexedTagName( $vals['changeablegroups']['add'], 'g' );
172  ApiResult::setIndexedTagName( $vals['changeablegroups']['remove'], 'g' );
173  ApiResult::setIndexedTagName( $vals['changeablegroups']['add-self'], 'g' );
174  ApiResult::setIndexedTagName( $vals['changeablegroups']['remove-self'], 'g' );
175  }
176 
177  if ( isset( $this->prop['options'] ) ) {
178  $vals['options'] = $user->getOptions();
179  $vals['options'][ApiResult::META_BC_BOOLS] = array_keys( $vals['options'] );
180  }
181 
182  if ( isset( $this->prop['preferencestoken'] ) &&
183  !$this->lacksSameOriginSecurity() &&
184  $this->getPermissionManager()->userHasRight( $user, 'editmyoptions' )
185  ) {
186  $vals['preferencestoken'] = $user->getEditToken( '', $this->getMain()->getRequest() );
187  }
188 
189  if ( isset( $this->prop['editcount'] ) ) {
190  // use intval to prevent null if a non-logged-in user calls
191  // api.php?format=jsonfm&action=query&meta=userinfo&uiprop=editcount
192  $vals['editcount'] = (int)$user->getEditCount();
193  }
194 
195  if ( isset( $this->prop['ratelimits'] ) ) {
196  $vals['ratelimits'] = $this->getRateLimits();
197  }
198 
199  if ( isset( $this->prop['realname'] ) &&
200  !in_array( 'realname', $this->getConfig()->get( 'HiddenPrefs' ) )
201  ) {
202  $vals['realname'] = $user->getRealName();
203  }
204 
205  if ( $this->getPermissionManager()->userHasRight( $user, 'viewmyprivateinfo' ) &&
206  isset( $this->prop['email'] ) ) {
207  $vals['email'] = $user->getEmail();
208  $auth = $user->getEmailAuthenticationTimestamp();
209  if ( $auth !== null ) {
210  $vals['emailauthenticated'] = wfTimestamp( TS_ISO_8601, $auth );
211  }
212  }
213 
214  if ( isset( $this->prop['registrationdate'] ) ) {
215  $regDate = $user->getRegistration();
216  if ( $regDate !== false ) {
217  $vals['registrationdate'] = wfTimestamp( TS_ISO_8601, $regDate );
218  }
219  }
220 
221  if ( isset( $this->prop['acceptlang'] ) ) {
222  $langs = $this->getRequest()->getAcceptLang();
223  $acceptLang = [];
224  foreach ( $langs as $lang => $val ) {
225  $r = [ 'q' => $val ];
226  ApiResult::setContentValue( $r, 'code', $lang );
227  $acceptLang[] = $r;
228  }
229  ApiResult::setIndexedTagName( $acceptLang, 'lang' );
230  $vals['acceptlang'] = $acceptLang;
231  }
232 
233  if ( isset( $this->prop['unreadcount'] ) ) {
234  $store = MediaWikiServices::getInstance()->getWatchedItemStore();
235  $unreadNotifications = $store->countUnreadNotifications(
236  $user,
237  self::WL_UNREAD_LIMIT
238  );
239 
240  if ( $unreadNotifications === true ) {
241  $vals['unreadcount'] = self::WL_UNREAD_LIMIT . '+';
242  } else {
243  $vals['unreadcount'] = $unreadNotifications;
244  }
245  }
246 
247  if ( isset( $this->prop['centralids'] ) ) {
248  $vals += self::getCentralUserInfo(
249  $this->getConfig(), $this->getUser(), $this->params['attachedwiki']
250  );
251  }
252 
253  if ( isset( $this->prop['latestcontrib'] ) ) {
254  $ts = $this->getLatestContributionTime();
255  if ( $ts !== null ) {
256  $vals['latestcontrib'] = $ts;
257  }
258  }
259 
260  return $vals;
261  }
262 
263  protected function getRateLimits() {
264  $retval = [
265  ApiResult::META_TYPE => 'assoc',
266  ];
267 
268  $user = $this->getUser();
269  if ( !$user->isPingLimitable() ) {
270  return $retval; // No limits
271  }
272 
273  // Find out which categories we belong to
274  $categories = [];
275  if ( $user->isAnon() ) {
276  $categories[] = 'anon';
277  } else {
278  $categories[] = 'user';
279  }
280  if ( $user->isNewbie() ) {
281  $categories[] = 'ip';
282  $categories[] = 'subnet';
283  if ( !$user->isAnon() ) {
284  $categories[] = 'newbie';
285  }
286  }
287  $categories = array_merge( $categories, $user->getGroups() );
288 
289  // Now get the actual limits
290  foreach ( $this->getConfig()->get( 'RateLimits' ) as $action => $limits ) {
291  foreach ( $categories as $cat ) {
292  if ( isset( $limits[$cat] ) && !is_null( $limits[$cat] ) ) {
293  $retval[$action][$cat]['hits'] = (int)$limits[$cat][0];
294  $retval[$action][$cat]['seconds'] = (int)$limits[$cat][1];
295  }
296  }
297  }
298 
299  return $retval;
300  }
301 
305  protected function getLatestContributionTime() {
306  $user = $this->getUser();
307  $dbr = $this->getDB();
308 
309  if ( $user->getActorId() === null ) {
310  return null;
311  }
312  $res = $dbr->selectField( 'revision_actor_temp',
313  'MAX(revactor_timestamp)',
314  [ 'revactor_actor' => $user->getActorId() ],
315  __METHOD__
316  );
317 
318  return $res ? wfTimestamp( TS_ISO_8601, $res ) : null;
319  }
320 
321  public function getAllowedParams() {
322  return [
323  'prop' => [
324  ApiBase::PARAM_ISMULTI => true,
326  'blockinfo',
327  'hasmsg',
328  'groups',
329  'groupmemberships',
330  'implicitgroups',
331  'rights',
332  'changeablegroups',
333  'options',
334  'editcount',
335  'ratelimits',
336  'email',
337  'realname',
338  'acceptlang',
339  'registrationdate',
340  'unreadcount',
341  'centralids',
342  'preferencestoken',
343  'latestcontrib',
344  ],
346  'unreadcount' => [
347  'apihelp-query+userinfo-paramvalue-prop-unreadcount',
348  self::WL_UNREAD_LIMIT - 1,
349  self::WL_UNREAD_LIMIT . '+',
350  ],
351  ],
353  'preferencestoken' => [
354  'apiwarn-deprecation-withreplacement',
355  $this->getModulePrefix() . "prop=preferencestoken",
356  'action=query&meta=tokens',
357  ]
358  ],
359  ],
360  'attachedwiki' => null,
361  ];
362  }
363 
364  protected function getExamplesMessages() {
365  return [
366  'action=query&meta=userinfo'
367  => 'apihelp-query+userinfo-example-simple',
368  'action=query&meta=userinfo&uiprop=blockinfo|groups|rights|hasmsg'
369  => 'apihelp-query+userinfo-example-data',
370  ];
371  }
372 
373  public function getHelpUrls() {
374  return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Userinfo';
375  }
376 }
ContextSource\getConfig
getConfig()
Definition: ContextSource.php:63
ApiQuery
This is the main query class.
Definition: ApiQuery.php:37
ApiQueryUserInfo\getLatestContributionTime
getLatestContributionTime()
Definition: ApiQueryUserInfo.php:305
ApiQueryUserInfo\$params
array $params
Definition: ApiQueryUserInfo.php:38
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:117
$lang
if(!isset( $args[0])) $lang
Definition: testCompression.php:33
ApiResult\META_TYPE
const META_TYPE
Key for the 'type' metadata item.
Definition: ApiResult.php:110
wfTimestamp
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
Definition: GlobalFunctions.php:1869
ApiQueryUserInfo
Query module to get information about the currently logged-in user.
Definition: ApiQueryUserInfo.php:31
ApiBase\PARAM_TYPE
const PARAM_TYPE
(string|string[]) Either an array of allowed value strings, or a string type as described below.
Definition: ApiBase.php:94
ApiBase\getResult
getResult()
Get the result object.
Definition: ApiBase.php:640
ApiQueryUserInfo\WL_UNREAD_LIMIT
const WL_UNREAD_LIMIT
Definition: ApiQueryUserInfo.php:35
ContextSource\getRequest
getRequest()
Definition: ContextSource.php:71
$res
$res
Definition: testCompression.php:52
ContextSource\getUser
getUser()
Definition: ContextSource.php:120
ApiBase\PARAM_DEPRECATED_VALUES
const PARAM_DEPRECATED_VALUES
(array) When PARAM_TYPE is an array, this indicates which of the values are deprecated.
Definition: ApiBase.php:209
ApiBase\lacksSameOriginSecurity
lacksSameOriginSecurity()
Returns true if the current request breaks the same-origin policy.
Definition: ApiBase.php:568
$dbr
$dbr
Definition: testCompression.php:50
ApiResult\setContentValue
static setContentValue(array &$arr, $name, $value, $flags=0)
Add an output value to the array by name and mark as META_CONTENT.
Definition: ApiResult.php:478
Config
Interface for configuration instances.
Definition: Config.php:28
ApiQueryUserInfo\getAllowedParams
getAllowedParams()
Returns an array of allowed parameters (parameter name) => (default value) or (parameter name) => (ar...
Definition: ApiQueryUserInfo.php:321
ApiResult\setArrayType
static setArrayType(array &$arr, $type, $kvpKeyName=null)
Set the array data type.
Definition: ApiResult.php:728
wfDeprecated
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Throws a warning that $function is deprecated.
Definition: GlobalFunctions.php:1044
ApiQueryUserInfo\getExamplesMessages
getExamplesMessages()
Returns usage examples for this module.
Definition: ApiQueryUserInfo.php:364
Config\get
get( $name)
Get a configuration variable such as "Sitename" or "UploadMaintenance.".
ApiQueryBase
This is a base class for all Query modules.
Definition: ApiQueryBase.php:34
ApiQueryBase\getDB
getDB()
Get the Query database connection (read-only)
Definition: ApiQueryBase.php:107
ApiResult\META_BC_BOOLS
const META_BC_BOOLS
Key for the 'BC bools' metadata item.
Definition: ApiResult.php:136
ApiQueryUserInfo\$prop
array $prop
Definition: ApiQueryUserInfo.php:40
ApiBase\extractRequestParams
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition: ApiBase.php:761
ApiBase\getModulePrefix
getModulePrefix()
Get parameter prefix (usually two letters or an empty string).
Definition: ApiBase.php:528
ApiResult\setIndexedTagName
static setIndexedTagName(array &$arr, $tag)
Set the tag name for numeric-keyed values in XML format.
Definition: ApiResult.php:616
ApiBase\getPermissionManager
getPermissionManager()
Obtain a PermissionManager instance that subclasses may use in their authorization checks.
Definition: ApiBase.php:710
ApiQueryUserInfo\getCurrentUserInfo
getCurrentUserInfo()
Definition: ApiQueryUserInfo.php:117
ApiQueryUserInfo\__construct
__construct(ApiQuery $query, $moduleName)
Definition: ApiQueryUserInfo.php:42
ApiQueryUserInfo\execute
execute()
Evaluates the parameters, performs the requested query, and sets up the result.
Definition: ApiQueryUserInfo.php:46
ApiBase\getModuleName
getModuleName()
Get the name of the module being executed by this instance.
Definition: ApiBase.php:520
ApiBase\PARAM_ISMULTI
const PARAM_ISMULTI
(boolean) Accept multiple pipe-separated values for this parameter (e.g.
Definition: ApiBase.php:58
ApiResult\formatExpiry
static formatExpiry( $expiry, $infinity='infinity')
Format an expiry timestamp for API output.
Definition: ApiResult.php:1205
ApiBase\getMain
getMain()
Get the main module.
Definition: ApiBase.php:536
MediaWiki\Block\AbstractBlock
Definition: AbstractBlock.php:34
ApiQueryUserInfo\getCentralUserInfo
static getCentralUserInfo(Config $config, User $user, $attachedWiki=null)
Get central user info.
Definition: ApiQueryUserInfo.php:90
ApiQueryUserInfo\getRateLimits
getRateLimits()
Definition: ApiQueryUserInfo.php:263
CentralIdLookup\factory
static factory( $providerId=null)
Fetch a CentralIdLookup.
Definition: CentralIdLookup.php:46
ApiBase\PARAM_HELP_MSG_PER_VALUE
const PARAM_HELP_MSG_PER_VALUE
((string|array|Message)[]) When PARAM_TYPE is an array, this is an array mapping those values to $msg...
Definition: ApiBase.php:164
User
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition: User.php:51
ApiQueryUserInfo\getHelpUrls
getHelpUrls()
Return links to more detailed help pages about the module.
Definition: ApiQueryUserInfo.php:373
User\getName
getName()
Get the user name, or the IP of an anonymous user.
Definition: User.php:2232
ApiQueryUserInfo\getBlockInfo
static getBlockInfo(AbstractBlock $block)
Get basic info about a given block.
Definition: ApiQueryUserInfo.php:65