MediaWiki  master
ApiQueryUserInfo.php
Go to the documentation of this file.
1 <?php
29 
36 
38 
39  private const WL_UNREAD_LIMIT = 1000;
40 
42  private $params = [];
43 
45  private $prop = [];
46 
51 
56 
61 
66 
69 
79  public function __construct(
80  ApiQuery $query,
81  $moduleName,
87  ) {
88  parent::__construct( $query, $moduleName, 'ui' );
89  $this->talkPageNotificationManager = $talkPageNotificationManager;
90  $this->watchedItemStore = $watchedItemStore;
91  $this->userEditTracker = $userEditTracker;
92  $this->userOptionsLookup = $userOptionsLookup;
93  $this->userGroupManager = $userGroupManager;
94  }
95 
96  public function execute() {
97  $this->params = $this->extractRequestParams();
98  $result = $this->getResult();
99 
100  if ( $this->params['prop'] !== null ) {
101  $this->prop = array_fill_keys( $this->params['prop'], true );
102  }
103 
104  $r = $this->getCurrentUserInfo();
105  $result->addValue( 'query', $this->getModuleName(), $r );
106  }
107 
120  public static function getCentralUserInfo(
121  Config $config,
122  UserIdentity $user,
123  $attachedWiki = UserIdentity::LOCAL
124  ) {
125  $providerIds = array_keys( $config->get( 'CentralIdLookupProviders' ) );
126 
127  $ret = [
128  'centralids' => [],
129  'attachedlocal' => [],
130  ];
131  ApiResult::setArrayType( $ret['centralids'], 'assoc' );
132  ApiResult::setArrayType( $ret['attachedlocal'], 'assoc' );
133  if ( $attachedWiki ) {
134  $ret['attachedwiki'] = [];
135  ApiResult::setArrayType( $ret['attachedwiki'], 'assoc' );
136  }
137 
138  $name = $user->getName();
139  $centralIdLookupFactory = MediaWikiServices::getInstance()
140  ->getCentralIdLookupFactory();
141  foreach ( $providerIds as $providerId ) {
142  $provider = $centralIdLookupFactory->getLookup( $providerId );
143  $ret['centralids'][$providerId] = $provider->centralIdFromName( $name );
144  $ret['attachedlocal'][$providerId] = $provider->isAttached( $user );
145  if ( $attachedWiki ) {
146  $ret['attachedwiki'][$providerId] = $provider->isAttached( $user, $attachedWiki );
147  }
148  }
149 
150  return $ret;
151  }
152 
153  protected function getCurrentUserInfo() {
154  $user = $this->getUser();
155  $vals = [];
156  $vals['id'] = $user->getId();
157  $vals['name'] = $user->getName();
158 
159  if ( !$user->isRegistered() ) {
160  $vals['anon'] = true;
161  }
162 
163  if ( isset( $this->prop['blockinfo'] ) ) {
164  $block = $user->getBlock();
165  if ( $block ) {
166  $vals = array_merge( $vals, $this->getBlockDetails( $block ) );
167  }
168  }
169 
170  if ( isset( $this->prop['hasmsg'] ) ) {
171  $vals['messages'] = $this->talkPageNotificationManager->userHasNewMessages( $user );
172  }
173 
174  if ( isset( $this->prop['groups'] ) ) {
175  $vals['groups'] = $this->userGroupManager->getUserEffectiveGroups( $user );
176  ApiResult::setArrayType( $vals['groups'], 'array' ); // even if empty
177  ApiResult::setIndexedTagName( $vals['groups'], 'g' ); // even if empty
178  }
179 
180  if ( isset( $this->prop['groupmemberships'] ) ) {
181  $ugms = $this->userGroupManager->getUserGroupMemberships( $user );
182  $vals['groupmemberships'] = [];
183  foreach ( $ugms as $group => $ugm ) {
184  $vals['groupmemberships'][] = [
185  'group' => $group,
186  'expiry' => ApiResult::formatExpiry( $ugm->getExpiry() ),
187  ];
188  }
189  ApiResult::setArrayType( $vals['groupmemberships'], 'array' ); // even if empty
190  ApiResult::setIndexedTagName( $vals['groupmemberships'], 'groupmembership' ); // even if empty
191  }
192 
193  if ( isset( $this->prop['implicitgroups'] ) ) {
194  $vals['implicitgroups'] = $this->userGroupManager->getUserImplicitGroups( $user );
195  ApiResult::setArrayType( $vals['implicitgroups'], 'array' ); // even if empty
196  ApiResult::setIndexedTagName( $vals['implicitgroups'], 'g' ); // even if empty
197  }
198 
199  if ( isset( $this->prop['rights'] ) ) {
200  $vals['rights'] = $this->getPermissionManager()->getUserPermissions( $user );
201  ApiResult::setArrayType( $vals['rights'], 'array' ); // even if empty
202  ApiResult::setIndexedTagName( $vals['rights'], 'r' ); // even if empty
203  }
204 
205  if ( isset( $this->prop['changeablegroups'] ) ) {
206  $vals['changeablegroups'] = $this->userGroupManager->getGroupsChangeableBy( $this->getAuthority() );
207  ApiResult::setIndexedTagName( $vals['changeablegroups']['add'], 'g' );
208  ApiResult::setIndexedTagName( $vals['changeablegroups']['remove'], 'g' );
209  ApiResult::setIndexedTagName( $vals['changeablegroups']['add-self'], 'g' );
210  ApiResult::setIndexedTagName( $vals['changeablegroups']['remove-self'], 'g' );
211  }
212 
213  if ( isset( $this->prop['options'] ) ) {
214  $vals['options'] = $this->userOptionsLookup->getOptions( $user );
215  $vals['options'][ApiResult::META_BC_BOOLS] = array_keys( $vals['options'] );
216  }
217 
218  if ( isset( $this->prop['preferencestoken'] ) &&
219  !$this->lacksSameOriginSecurity() &&
220  $this->getAuthority()->isAllowed( 'editmyoptions' )
221  ) {
222  $vals['preferencestoken'] = $this->getCsrfTokenSet()->getToken()->toString();
223  }
224 
225  if ( isset( $this->prop['editcount'] ) ) {
226  // use intval to prevent null if a non-logged-in user calls
227  // api.php?format=jsonfm&action=query&meta=userinfo&uiprop=editcount
228  $vals['editcount'] = (int)$user->getEditCount();
229  }
230 
231  if ( isset( $this->prop['ratelimits'] ) ) {
232  // true = real rate limits, taking User::isPingLimitable into account
233  $vals['ratelimits'] = $this->getRateLimits( true );
234  }
235  if ( isset( $this->prop['theoreticalratelimits'] ) ) {
236  // false = ignore User::isPingLimitable
237  $vals['theoreticalratelimits'] = $this->getRateLimits( false );
238  }
239 
240  if ( isset( $this->prop['realname'] ) &&
241  !in_array( 'realname', $this->getConfig()->get( 'HiddenPrefs' ) )
242  ) {
243  $vals['realname'] = $user->getRealName();
244  }
245 
246  if ( $this->getAuthority()->isAllowed( 'viewmyprivateinfo' ) && isset( $this->prop['email'] ) ) {
247  $vals['email'] = $user->getEmail();
248  $auth = $user->getEmailAuthenticationTimestamp();
249  if ( $auth !== null ) {
250  $vals['emailauthenticated'] = wfTimestamp( TS_ISO_8601, $auth );
251  }
252  }
253 
254  if ( isset( $this->prop['registrationdate'] ) ) {
255  $regDate = $user->getRegistration();
256  if ( $regDate !== false ) {
257  $vals['registrationdate'] = wfTimestamp( TS_ISO_8601, $regDate );
258  }
259  }
260 
261  if ( isset( $this->prop['acceptlang'] ) ) {
262  $langs = $this->getRequest()->getAcceptLang();
263  $acceptLang = [];
264  foreach ( $langs as $lang => $val ) {
265  $r = [ 'q' => $val ];
266  ApiResult::setContentValue( $r, 'code', $lang );
267  $acceptLang[] = $r;
268  }
269  ApiResult::setIndexedTagName( $acceptLang, 'lang' );
270  $vals['acceptlang'] = $acceptLang;
271  }
272 
273  if ( isset( $this->prop['unreadcount'] ) ) {
274  $unreadNotifications = $this->watchedItemStore->countUnreadNotifications(
275  $user,
276  self::WL_UNREAD_LIMIT
277  );
278 
279  if ( $unreadNotifications === true ) {
280  $vals['unreadcount'] = self::WL_UNREAD_LIMIT . '+';
281  } else {
282  $vals['unreadcount'] = $unreadNotifications;
283  }
284  }
285 
286  if ( isset( $this->prop['centralids'] ) ) {
287  $vals += self::getCentralUserInfo(
288  $this->getConfig(), $this->getUser(), $this->params['attachedwiki']
289  );
290  }
291 
292  if ( isset( $this->prop['latestcontrib'] ) ) {
293  $ts = $this->getLatestContributionTime();
294  if ( $ts !== null ) {
295  $vals['latestcontrib'] = $ts;
296  }
297  }
298 
299  return $vals;
300  }
301 
309  protected function getRateLimits( bool $applyNoRateLimit ) {
310  $retval = [
311  ApiResult::META_TYPE => 'assoc',
312  ];
313 
314  $user = $this->getUser();
315  if ( $applyNoRateLimit && !$user->isPingLimitable() ) {
316  return $retval; // No limits
317  }
318 
319  // Find out which categories we belong to
320  $categories = [];
321  if ( !$user->isRegistered() ) {
322  $categories[] = 'anon';
323  } else {
324  $categories[] = 'user';
325  }
326  if ( $user->isNewbie() ) {
327  $categories[] = 'ip';
328  $categories[] = 'subnet';
329  if ( $user->isRegistered() ) {
330  $categories[] = 'newbie';
331  }
332  }
333  $categories = array_merge( $categories, $this->userGroupManager->getUserGroups( $user ) );
334 
335  // Now get the actual limits
336  foreach ( $this->getConfig()->get( 'RateLimits' ) as $action => $limits ) {
337  foreach ( $categories as $cat ) {
338  if ( isset( $limits[$cat] ) ) {
339  $retval[$action][$cat]['hits'] = (int)$limits[$cat][0];
340  $retval[$action][$cat]['seconds'] = (int)$limits[$cat][1];
341  }
342  }
343  }
344 
345  return $retval;
346  }
347 
351  protected function getLatestContributionTime() {
352  $timestamp = $this->userEditTracker->getLatestEditTimestamp( $this->getUser() );
353  if ( $timestamp === false ) {
354  return null;
355  }
356  return MWTimestamp::convert( TS_ISO_8601, $timestamp );
357  }
358 
359  public function getAllowedParams() {
360  return [
361  'prop' => [
362  ApiBase::PARAM_ISMULTI => true,
363  ApiBase::PARAM_ALL => true,
365  'blockinfo',
366  'hasmsg',
367  'groups',
368  'groupmemberships',
369  'implicitgroups',
370  'rights',
371  'changeablegroups',
372  'options',
373  'editcount',
374  'ratelimits',
375  'theoreticalratelimits',
376  'email',
377  'realname',
378  'acceptlang',
379  'registrationdate',
380  'unreadcount',
381  'centralids',
382  'preferencestoken',
383  'latestcontrib',
384  ],
386  'unreadcount' => [
387  'apihelp-query+userinfo-paramvalue-prop-unreadcount',
388  self::WL_UNREAD_LIMIT - 1,
389  self::WL_UNREAD_LIMIT . '+',
390  ],
391  ],
393  'preferencestoken' => [
394  'apiwarn-deprecation-withreplacement',
395  $this->getModulePrefix() . "prop=preferencestoken",
396  'action=query&meta=tokens',
397  ]
398  ],
399  ],
400  'attachedwiki' => null,
401  ];
402  }
403 
404  protected function getExamplesMessages() {
405  return [
406  'action=query&meta=userinfo'
407  => 'apihelp-query+userinfo-example-simple',
408  'action=query&meta=userinfo&uiprop=blockinfo|groups|rights|hasmsg'
409  => 'apihelp-query+userinfo-example-data',
410  ];
411  }
412 
413  public function getHelpUrls() {
414  return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Userinfo';
415  }
416 }
ApiQueryUserInfo\$watchedItemStore
WatchedItemStore $watchedItemStore
Definition: ApiQueryUserInfo.php:55
ContextSource\getConfig
getConfig()
Definition: ContextSource.php:72
ApiQuery
This is the main query class.
Definition: ApiQuery.php:37
ApiQueryUserInfo\getLatestContributionTime
getLatestContributionTime()
Definition: ApiQueryUserInfo.php:351
ApiQueryUserInfo\$params
array $params
Definition: ApiQueryUserInfo.php:42
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:186
$lang
if(!isset( $args[0])) $lang
Definition: testCompression.php:37
ApiResult\META_TYPE
const META_TYPE
Key for the 'type' metadata item.
Definition: ApiResult.php:110
ApiBase\PARAM_ALL
const PARAM_ALL
Definition: ApiBase.php:81
wfTimestamp
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
Definition: GlobalFunctions.php:1692
ApiQueryUserInfo
Query module to get information about the currently logged-in user.
Definition: ApiQueryUserInfo.php:35
ApiBase\PARAM_TYPE
const PARAM_TYPE
Definition: ApiBase.php:72
ApiBase\getResult
getResult()
Get the result object.
Definition: ApiBase.php:571
ApiQueryUserInfo\WL_UNREAD_LIMIT
const WL_UNREAD_LIMIT
Definition: ApiQueryUserInfo.php:39
ContextSource\getRequest
getRequest()
Definition: ContextSource.php:81
ContextSource\getUser
getUser()
Definition: ContextSource.php:136
ApiBase\PARAM_DEPRECATED_VALUES
const PARAM_DEPRECATED_VALUES
Definition: ApiBase.php:84
ApiBase\lacksSameOriginSecurity
lacksSameOriginSecurity()
Returns true if the current request breaks the same-origin policy.
Definition: ApiBase.php:502
MediaWiki\User\UserIdentity
Interface for objects representing user identity.
Definition: UserIdentity.php:39
ApiQueryUserInfo\$userGroupManager
UserGroupManager $userGroupManager
Definition: ApiQueryUserInfo.php:68
MediaWiki\User\TalkPageNotificationManager
Manages user talk page notifications.
Definition: TalkPageNotificationManager.php:35
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:470
Config
Interface for configuration instances.
Definition: Config.php:30
MediaWiki\User\UserGroupManager
Managers user groups.
Definition: UserGroupManager.php:52
ApiQueryUserInfo\getAllowedParams
getAllowedParams()
Returns an array of allowed parameters (parameter name) => (default value) or (parameter name) => (ar...
Definition: ApiQueryUserInfo.php:359
ApiResult\setArrayType
static setArrayType(array &$arr, $type, $kvpKeyName=null)
Set the array data type.
Definition: ApiResult.php:719
ApiQueryUserInfo\getExamplesMessages
getExamplesMessages()
Returns usage examples for this module.
Definition: ApiQueryUserInfo.php:404
Config\get
get( $name)
Get a configuration variable such as "Sitename" or "UploadMaintenance.".
ApiQueryUserInfo\$userOptionsLookup
UserOptionsLookup $userOptionsLookup
Definition: ApiQueryUserInfo.php:65
ApiQueryBase
This is a base class for all Query modules.
Definition: ApiQueryBase.php:37
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:45
ApiBase\extractRequestParams
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition: ApiBase.php:707
MediaWiki\User\UserIdentity\getName
getName()
ApiQueryUserInfo\getRateLimits
getRateLimits(bool $applyNoRateLimit)
Get the rate limits that apply to the user, or the rate limits that would apply if the user didn't ha...
Definition: ApiQueryUserInfo.php:309
ApiQueryUserInfo\getCentralUserInfo
static getCentralUserInfo(Config $config, UserIdentity $user, $attachedWiki=UserIdentity::LOCAL)
Get central user info.
Definition: ApiQueryUserInfo.php:120
ApiBlockInfoTrait
trait ApiBlockInfoTrait
Definition: ApiBlockInfoTrait.php:27
ApiBase\getModulePrefix
getModulePrefix()
Get parameter prefix (usually two letters or an empty string).
Definition: ApiBase.php:448
ApiResult\setIndexedTagName
static setIndexedTagName(array &$arr, $tag)
Set the tag name for numeric-keyed values in XML format.
Definition: ApiResult.php:607
ApiQueryUserInfo\__construct
__construct(ApiQuery $query, $moduleName, TalkPageNotificationManager $talkPageNotificationManager, WatchedItemStore $watchedItemStore, UserEditTracker $userEditTracker, UserOptionsLookup $userOptionsLookup, UserGroupManager $userGroupManager)
Definition: ApiQueryUserInfo.php:79
ContextSource\getAuthority
getAuthority()
Definition: ContextSource.php:144
ContextSource\getCsrfTokenSet
getCsrfTokenSet()
Get a repository to obtain and match CSRF tokens.
Definition: ContextSource.php:219
ApiBase\getPermissionManager
getPermissionManager()
Obtain a PermissionManager instance that subclasses may use in their authorization checks.
Definition: ApiBase.php:628
MediaWiki\User\UserOptionsLookup
Provides access to user options.
Definition: UserOptionsLookup.php:29
WatchedItemStore
Storage layer class for WatchedItems.
Definition: WatchedItemStore.php:29
ApiQueryUserInfo\getCurrentUserInfo
getCurrentUserInfo()
Definition: ApiQueryUserInfo.php:153
MediaWiki\User\UserEditTracker
Track info about user edit counts and timings.
Definition: UserEditTracker.php:21
ApiQueryUserInfo\execute
execute()
Evaluates the parameters, performs the requested query, and sets up the result.
Definition: ApiQueryUserInfo.php:96
ApiQueryUserInfo\$userEditTracker
UserEditTracker $userEditTracker
Definition: ApiQueryUserInfo.php:60
ApiBase\getModuleName
getModuleName()
Get the name of the module being executed by this instance.
Definition: ApiBase.php:440
ApiBase\PARAM_ISMULTI
const PARAM_ISMULTI
Definition: ApiBase.php:71
ApiResult\formatExpiry
static formatExpiry( $expiry, $infinity='infinity')
Format an expiry timestamp for API output.
Definition: ApiResult.php:1198
ApiQueryUserInfo\$talkPageNotificationManager
TalkPageNotificationManager $talkPageNotificationManager
Definition: ApiQueryUserInfo.php:50
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:138
ApiQueryUserInfo\getHelpUrls
getHelpUrls()
Return links to more detailed help pages about the module.
Definition: ApiQueryUserInfo.php:413