MediaWiki 1.40.4
ApiQueryUserInfo.php
Go to the documentation of this file.
1<?php
32
39
41
42 private const WL_UNREAD_LIMIT = 1000;
43
45 private $params = [];
46
48 private $prop = [];
49
53 private $talkPageNotificationManager;
54
58 private $watchedItemStore;
59
63 private $userEditTracker;
64
68 private $userOptionsLookup;
69
71 private $userGroupManager;
72
82 public function __construct(
83 ApiQuery $query,
84 $moduleName,
85 TalkPageNotificationManager $talkPageNotificationManager,
86 WatchedItemStore $watchedItemStore,
87 UserEditTracker $userEditTracker,
88 UserOptionsLookup $userOptionsLookup,
89 UserGroupManager $userGroupManager
90 ) {
91 parent::__construct( $query, $moduleName, 'ui' );
92 $this->talkPageNotificationManager = $talkPageNotificationManager;
93 $this->watchedItemStore = $watchedItemStore;
94 $this->userEditTracker = $userEditTracker;
95 $this->userOptionsLookup = $userOptionsLookup;
96 $this->userGroupManager = $userGroupManager;
97 }
98
99 public function execute() {
100 $this->params = $this->extractRequestParams();
101 $result = $this->getResult();
102
103 if ( $this->params['prop'] !== null ) {
104 $this->prop = array_fill_keys( $this->params['prop'], true );
105 }
106
107 $r = $this->getCurrentUserInfo();
108 $result->addValue( 'query', $this->getModuleName(), $r );
109 }
110
123 public static function getCentralUserInfo(
124 Config $config,
125 UserIdentity $user,
126 $attachedWiki = UserIdentity::LOCAL
127 ) {
128 $providerIds = array_keys( $config->get( MainConfigNames::CentralIdLookupProviders ) );
129
130 $ret = [
131 'centralids' => [],
132 'attachedlocal' => [],
133 ];
134 ApiResult::setArrayType( $ret['centralids'], 'assoc' );
135 ApiResult::setArrayType( $ret['attachedlocal'], 'assoc' );
136 if ( $attachedWiki ) {
137 $ret['attachedwiki'] = [];
138 ApiResult::setArrayType( $ret['attachedwiki'], 'assoc' );
139 }
140
141 $name = $user->getName();
142 $centralIdLookupFactory = MediaWikiServices::getInstance()
143 ->getCentralIdLookupFactory();
144 foreach ( $providerIds as $providerId ) {
145 $provider = $centralIdLookupFactory->getLookup( $providerId );
146 $ret['centralids'][$providerId] = $provider->centralIdFromName( $name );
147 $ret['attachedlocal'][$providerId] = $provider->isAttached( $user );
148 if ( $attachedWiki ) {
149 $ret['attachedwiki'][$providerId] = $provider->isAttached( $user, $attachedWiki );
150 }
151 }
152
153 return $ret;
154 }
155
156 protected function getCurrentUserInfo() {
157 $user = $this->getUser();
158 $vals = [];
159 $vals['id'] = $user->getId();
160 $vals['name'] = $user->getName();
161
162 if ( !$user->isRegistered() ) {
163 $vals['anon'] = true;
164 }
165
166 if ( isset( $this->prop['blockinfo'] ) ) {
167 $block = $user->getBlock();
168 if ( $block ) {
169 $vals = array_merge( $vals, $this->getBlockDetails( $block ) );
170 }
171 }
172
173 if ( isset( $this->prop['hasmsg'] ) ) {
174 $vals['messages'] = $this->talkPageNotificationManager->userHasNewMessages( $user );
175 }
176
177 if ( isset( $this->prop['groups'] ) ) {
178 $vals['groups'] = $this->userGroupManager->getUserEffectiveGroups( $user );
179 ApiResult::setArrayType( $vals['groups'], 'array' ); // even if empty
180 ApiResult::setIndexedTagName( $vals['groups'], 'g' ); // even if empty
181 }
182
183 if ( isset( $this->prop['groupmemberships'] ) ) {
184 $ugms = $this->userGroupManager->getUserGroupMemberships( $user );
185 $vals['groupmemberships'] = [];
186 foreach ( $ugms as $group => $ugm ) {
187 $vals['groupmemberships'][] = [
188 'group' => $group,
189 'expiry' => ApiResult::formatExpiry( $ugm->getExpiry() ),
190 ];
191 }
192 ApiResult::setArrayType( $vals['groupmemberships'], 'array' ); // even if empty
193 ApiResult::setIndexedTagName( $vals['groupmemberships'], 'groupmembership' ); // even if empty
194 }
195
196 if ( isset( $this->prop['implicitgroups'] ) ) {
197 $vals['implicitgroups'] = $this->userGroupManager->getUserImplicitGroups( $user );
198 ApiResult::setArrayType( $vals['implicitgroups'], 'array' ); // even if empty
199 ApiResult::setIndexedTagName( $vals['implicitgroups'], 'g' ); // even if empty
200 }
201
202 if ( isset( $this->prop['rights'] ) ) {
203 $vals['rights'] = $this->getPermissionManager()->getUserPermissions( $user );
204 ApiResult::setArrayType( $vals['rights'], 'array' ); // even if empty
205 ApiResult::setIndexedTagName( $vals['rights'], 'r' ); // even if empty
206 }
207
208 if ( isset( $this->prop['changeablegroups'] ) ) {
209 $vals['changeablegroups'] = $this->userGroupManager->getGroupsChangeableBy( $this->getAuthority() );
210 ApiResult::setIndexedTagName( $vals['changeablegroups']['add'], 'g' );
211 ApiResult::setIndexedTagName( $vals['changeablegroups']['remove'], 'g' );
212 ApiResult::setIndexedTagName( $vals['changeablegroups']['add-self'], 'g' );
213 ApiResult::setIndexedTagName( $vals['changeablegroups']['remove-self'], 'g' );
214 }
215
216 if ( isset( $this->prop['options'] ) ) {
217 $vals['options'] = $this->userOptionsLookup->getOptions( $user );
218 $vals['options'][ApiResult::META_BC_BOOLS] = array_keys( $vals['options'] );
219 }
220
221 if ( isset( $this->prop['editcount'] ) ) {
222 // use intval to prevent null if a non-logged-in user calls
223 // api.php?format=jsonfm&action=query&meta=userinfo&uiprop=editcount
224 $vals['editcount'] = (int)$user->getEditCount();
225 }
226
227 if ( isset( $this->prop['ratelimits'] ) ) {
228 // true = real rate limits, taking User::isPingLimitable into account
229 $vals['ratelimits'] = $this->getRateLimits( true );
230 }
231 if ( isset( $this->prop['theoreticalratelimits'] ) ) {
232 // false = ignore User::isPingLimitable
233 $vals['theoreticalratelimits'] = $this->getRateLimits( false );
234 }
235
236 if ( isset( $this->prop['realname'] ) &&
237 !in_array( 'realname', $this->getConfig()->get( MainConfigNames::HiddenPrefs ) )
238 ) {
239 $vals['realname'] = $user->getRealName();
240 }
241
242 if ( $this->getAuthority()->isAllowed( 'viewmyprivateinfo' ) && isset( $this->prop['email'] ) ) {
243 $vals['email'] = $user->getEmail();
244 $auth = $user->getEmailAuthenticationTimestamp();
245 if ( $auth !== null ) {
246 $vals['emailauthenticated'] = wfTimestamp( TS_ISO_8601, $auth );
247 }
248 }
249
250 if ( isset( $this->prop['registrationdate'] ) ) {
251 $regDate = $user->getRegistration();
252 if ( $regDate !== false ) {
253 $vals['registrationdate'] = wfTimestamp( TS_ISO_8601, $regDate );
254 }
255 }
256
257 if ( isset( $this->prop['acceptlang'] ) ) {
258 $langs = $this->getRequest()->getAcceptLang();
259 $acceptLang = [];
260 foreach ( $langs as $lang => $val ) {
261 $r = [ 'q' => $val ];
262 ApiResult::setContentValue( $r, 'code', $lang );
263 $acceptLang[] = $r;
264 }
265 ApiResult::setIndexedTagName( $acceptLang, 'lang' );
266 $vals['acceptlang'] = $acceptLang;
267 }
268
269 if ( isset( $this->prop['unreadcount'] ) ) {
270 $unreadNotifications = $this->watchedItemStore->countUnreadNotifications(
271 $user,
272 self::WL_UNREAD_LIMIT
273 );
274
275 if ( $unreadNotifications === true ) {
276 $vals['unreadcount'] = self::WL_UNREAD_LIMIT . '+';
277 } else {
278 $vals['unreadcount'] = $unreadNotifications;
279 }
280 }
281
282 if ( isset( $this->prop['centralids'] ) ) {
284 $this->getConfig(), $this->getUser(), $this->params['attachedwiki']
285 );
286 }
287
288 if ( isset( $this->prop['latestcontrib'] ) ) {
289 $ts = $this->getLatestContributionTime();
290 if ( $ts !== null ) {
291 $vals['latestcontrib'] = $ts;
292 }
293 }
294
295 if ( isset( $this->prop['cancreateaccount'] ) ) {
296 $status = PermissionStatus::newEmpty();
297 $vals['cancreateaccount'] = $user->definitelyCan( 'createaccount',
298 SpecialPage::getTitleFor( 'CreateAccount' ), $status );
299 if ( !$status->isGood() ) {
300 $vals['cancreateaccounterror'] = $this->getErrorFormatter()->arrayFromStatus( $status );
301 }
302 }
303
304 return $vals;
305 }
306
314 protected function getRateLimits( bool $applyNoRateLimit ) {
315 $retval = [
316 ApiResult::META_TYPE => 'assoc',
317 ];
318
319 $user = $this->getUser();
320 if ( $applyNoRateLimit && !$user->isPingLimitable() ) {
321 return $retval; // No limits
322 }
323
324 // Find out which categories we belong to
325 $categories = [];
326 if ( !$user->isRegistered() ) {
327 $categories[] = 'anon';
328 } else {
329 $categories[] = 'user';
330 }
331 if ( $user->isNewbie() ) {
332 $categories[] = 'ip';
333 $categories[] = 'subnet';
334 if ( $user->isRegistered() ) {
335 $categories[] = 'newbie';
336 }
337 }
338 $categories = array_merge( $categories, $this->userGroupManager->getUserGroups( $user ) );
339
340 // Now get the actual limits
341 foreach ( $this->getConfig()->get( MainConfigNames::RateLimits ) as $action => $limits ) {
342 foreach ( $categories as $cat ) {
343 if ( isset( $limits[$cat] ) ) {
344 $retval[$action][$cat]['hits'] = (int)$limits[$cat][0];
345 $retval[$action][$cat]['seconds'] = (int)$limits[$cat][1];
346 }
347 }
348 }
349
350 return $retval;
351 }
352
356 protected function getLatestContributionTime() {
357 $timestamp = $this->userEditTracker->getLatestEditTimestamp( $this->getUser() );
358 if ( $timestamp === false ) {
359 return null;
360 }
361 return MWTimestamp::convert( TS_ISO_8601, $timestamp );
362 }
363
364 public function getAllowedParams() {
365 return [
366 'prop' => [
367 ParamValidator::PARAM_ISMULTI => true,
368 ParamValidator::PARAM_ALL => true,
369 ParamValidator::PARAM_TYPE => [
370 'blockinfo',
371 'hasmsg',
372 'groups',
373 'groupmemberships',
374 'implicitgroups',
375 'rights',
376 'changeablegroups',
377 'options',
378 'editcount',
379 'ratelimits',
380 'theoreticalratelimits',
381 'email',
382 'realname',
383 'acceptlang',
384 'registrationdate',
385 'unreadcount',
386 'centralids',
387 'latestcontrib',
388 'cancreateaccount',
389 ],
391 'unreadcount' => [
392 'apihelp-query+userinfo-paramvalue-prop-unreadcount',
393 self::WL_UNREAD_LIMIT - 1,
394 self::WL_UNREAD_LIMIT . '+',
395 ],
396 ],
397 ],
398 'attachedwiki' => null,
399 ];
400 }
401
402 protected function getExamplesMessages() {
403 return [
404 'action=query&meta=userinfo'
405 => 'apihelp-query+userinfo-example-simple',
406 'action=query&meta=userinfo&uiprop=blockinfo|groups|rights|hasmsg'
407 => 'apihelp-query+userinfo-example-data',
408 ];
409 }
410
411 public function getHelpUrls() {
412 return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Userinfo';
413 }
414}
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
getErrorFormatter()
Definition ApiBase.php:648
getPermissionManager()
Obtain a PermissionManager instance that subclasses may use in their authorization checks.
Definition ApiBase.php:694
const PARAM_HELP_MSG_PER_VALUE
((string|array|Message)[]) When PARAM_TYPE is an array, or 'string' with PARAM_ISMULTI,...
Definition ApiBase.php:204
getResult()
Get the result object.
Definition ApiBase.php:637
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition ApiBase.php:773
getModuleName()
Get the name of the module being executed by this instance.
Definition ApiBase.php:506
This is a base class for all Query modules.
Query module to get information about the currently logged-in user.
getExamplesMessages()
Returns usage examples for this module.
static getCentralUserInfo(Config $config, UserIdentity $user, $attachedWiki=UserIdentity::LOCAL)
Get central user info.
getHelpUrls()
Return links to more detailed help pages about the module.
getAllowedParams()
Returns an array of allowed parameters (parameter name) => (default value) or (parameter name) => (ar...
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...
execute()
Evaluates the parameters, performs the requested query, and sets up the result.
__construct(ApiQuery $query, $moduleName, TalkPageNotificationManager $talkPageNotificationManager, WatchedItemStore $watchedItemStore, UserEditTracker $userEditTracker, UserOptionsLookup $userOptionsLookup, UserGroupManager $userGroupManager)
This is the main query class.
Definition ApiQuery.php:42
A class containing constants representing the names of configuration variables.
Service locator for MediaWiki core services.
A StatusValue for permission errors.
Track info about user edit counts and timings.
Provides access to user options.
static getTitleFor( $name, $subpage=false, $fragment='')
Get a localised Title object for a specified special page name If you don't need a full Title object,...
Storage layer class for WatchedItems.
Service for formatting and validating API parameters.
trait ApiBlockInfoTrait
Interface for configuration instances.
Definition Config.php:30
get( $name)
Get a configuration variable such as "Sitename" or "UploadMaintenance.".
Interface for objects representing user identity.
if(!isset( $args[0])) $lang