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