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['editcount'] ) ) {
219  // use intval to prevent null if a non-logged-in user calls
220  // api.php?format=jsonfm&action=query&meta=userinfo&uiprop=editcount
221  $vals['editcount'] = (int)$user->getEditCount();
222  }
223 
224  if ( isset( $this->prop['ratelimits'] ) ) {
225  // true = real rate limits, taking User::isPingLimitable into account
226  $vals['ratelimits'] = $this->getRateLimits( true );
227  }
228  if ( isset( $this->prop['theoreticalratelimits'] ) ) {
229  // false = ignore User::isPingLimitable
230  $vals['theoreticalratelimits'] = $this->getRateLimits( false );
231  }
232 
233  if ( isset( $this->prop['realname'] ) &&
234  !in_array( 'realname', $this->getConfig()->get( 'HiddenPrefs' ) )
235  ) {
236  $vals['realname'] = $user->getRealName();
237  }
238 
239  if ( $this->getAuthority()->isAllowed( 'viewmyprivateinfo' ) && isset( $this->prop['email'] ) ) {
240  $vals['email'] = $user->getEmail();
241  $auth = $user->getEmailAuthenticationTimestamp();
242  if ( $auth !== null ) {
243  $vals['emailauthenticated'] = wfTimestamp( TS_ISO_8601, $auth );
244  }
245  }
246 
247  if ( isset( $this->prop['registrationdate'] ) ) {
248  $regDate = $user->getRegistration();
249  if ( $regDate !== false ) {
250  $vals['registrationdate'] = wfTimestamp( TS_ISO_8601, $regDate );
251  }
252  }
253 
254  if ( isset( $this->prop['acceptlang'] ) ) {
255  $langs = $this->getRequest()->getAcceptLang();
256  $acceptLang = [];
257  foreach ( $langs as $lang => $val ) {
258  $r = [ 'q' => $val ];
259  ApiResult::setContentValue( $r, 'code', $lang );
260  $acceptLang[] = $r;
261  }
262  ApiResult::setIndexedTagName( $acceptLang, 'lang' );
263  $vals['acceptlang'] = $acceptLang;
264  }
265 
266  if ( isset( $this->prop['unreadcount'] ) ) {
267  $unreadNotifications = $this->watchedItemStore->countUnreadNotifications(
268  $user,
269  self::WL_UNREAD_LIMIT
270  );
271 
272  if ( $unreadNotifications === true ) {
273  $vals['unreadcount'] = self::WL_UNREAD_LIMIT . '+';
274  } else {
275  $vals['unreadcount'] = $unreadNotifications;
276  }
277  }
278 
279  if ( isset( $this->prop['centralids'] ) ) {
280  $vals += self::getCentralUserInfo(
281  $this->getConfig(), $this->getUser(), $this->params['attachedwiki']
282  );
283  }
284 
285  if ( isset( $this->prop['latestcontrib'] ) ) {
286  $ts = $this->getLatestContributionTime();
287  if ( $ts !== null ) {
288  $vals['latestcontrib'] = $ts;
289  }
290  }
291 
292  return $vals;
293  }
294 
302  protected function getRateLimits( bool $applyNoRateLimit ) {
303  $retval = [
304  ApiResult::META_TYPE => 'assoc',
305  ];
306 
307  $user = $this->getUser();
308  if ( $applyNoRateLimit && !$user->isPingLimitable() ) {
309  return $retval; // No limits
310  }
311 
312  // Find out which categories we belong to
313  $categories = [];
314  if ( !$user->isRegistered() ) {
315  $categories[] = 'anon';
316  } else {
317  $categories[] = 'user';
318  }
319  if ( $user->isNewbie() ) {
320  $categories[] = 'ip';
321  $categories[] = 'subnet';
322  if ( $user->isRegistered() ) {
323  $categories[] = 'newbie';
324  }
325  }
326  $categories = array_merge( $categories, $this->userGroupManager->getUserGroups( $user ) );
327 
328  // Now get the actual limits
329  foreach ( $this->getConfig()->get( 'RateLimits' ) as $action => $limits ) {
330  foreach ( $categories as $cat ) {
331  if ( isset( $limits[$cat] ) ) {
332  $retval[$action][$cat]['hits'] = (int)$limits[$cat][0];
333  $retval[$action][$cat]['seconds'] = (int)$limits[$cat][1];
334  }
335  }
336  }
337 
338  return $retval;
339  }
340 
344  protected function getLatestContributionTime() {
345  $timestamp = $this->userEditTracker->getLatestEditTimestamp( $this->getUser() );
346  if ( $timestamp === false ) {
347  return null;
348  }
349  return MWTimestamp::convert( TS_ISO_8601, $timestamp );
350  }
351 
352  public function getAllowedParams() {
353  return [
354  'prop' => [
355  ApiBase::PARAM_ISMULTI => true,
356  ApiBase::PARAM_ALL => true,
358  'blockinfo',
359  'hasmsg',
360  'groups',
361  'groupmemberships',
362  'implicitgroups',
363  'rights',
364  'changeablegroups',
365  'options',
366  'editcount',
367  'ratelimits',
368  'theoreticalratelimits',
369  'email',
370  'realname',
371  'acceptlang',
372  'registrationdate',
373  'unreadcount',
374  'centralids',
375  'latestcontrib',
376  ],
378  'unreadcount' => [
379  'apihelp-query+userinfo-paramvalue-prop-unreadcount',
380  self::WL_UNREAD_LIMIT - 1,
381  self::WL_UNREAD_LIMIT . '+',
382  ],
383  ],
384  ],
385  'attachedwiki' => null,
386  ];
387  }
388 
389  protected function getExamplesMessages() {
390  return [
391  'action=query&meta=userinfo'
392  => 'apihelp-query+userinfo-example-simple',
393  'action=query&meta=userinfo&uiprop=blockinfo|groups|rights|hasmsg'
394  => 'apihelp-query+userinfo-example-data',
395  ];
396  }
397 
398  public function getHelpUrls() {
399  return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Userinfo';
400  }
401 }
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:39
ApiQueryUserInfo\getLatestContributionTime
getLatestContributionTime()
Definition: ApiQueryUserInfo.php:344
ApiQueryUserInfo\$params
array $params
Definition: ApiQueryUserInfo.php:42
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:200
$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:117
wfTimestamp
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
Definition: GlobalFunctions.php:1657
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:81
ApiBase\getResult
getResult()
Get the result object.
Definition: ApiBase.php:628
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
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:466
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:352
ApiResult\setArrayType
static setArrayType(array &$arr, $type, $kvpKeyName=null)
Set the array data type.
Definition: ApiResult.php:715
ApiQueryUserInfo\getExamplesMessages
getExamplesMessages()
Returns usage examples for this module.
Definition: ApiQueryUserInfo.php:389
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:764
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:302
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
ApiResult\setIndexedTagName
static setIndexedTagName(array &$arr, $tag)
Set the tag name for numeric-keyed values in XML format.
Definition: ApiResult.php:603
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
ApiBase\getPermissionManager
getPermissionManager()
Obtain a PermissionManager instance that subclasses may use in their authorization checks.
Definition: ApiBase.php:685
MediaWiki\User\UserOptionsLookup
Provides access to user options.
Definition: UserOptionsLookup.php:29
WatchedItemStore
Storage layer class for WatchedItems.
Definition: WatchedItemStore.php:26
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:497
ApiBase\PARAM_ISMULTI
const PARAM_ISMULTI
Definition: ApiBase.php:77
ApiResult\formatExpiry
static formatExpiry( $expiry, $infinity='infinity')
Format an expiry timestamp for API output.
Definition: ApiResult.php:1194
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:195
ApiQueryUserInfo\getHelpUrls
getHelpUrls()
Return links to more detailed help pages about the module.
Definition: ApiQueryUserInfo.php:398