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