MediaWiki REL1_37
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'] ) ) {
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' => [
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}
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
const PARAM_TYPE
Definition ApiBase.php:81
getPermissionManager()
Obtain a PermissionManager instance that subclasses may use in their authorization checks.
Definition ApiBase.php:685
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
getResult()
Get the result object.
Definition ApiBase.php:628
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition ApiBase.php:764
const PARAM_ALL
Definition ApiBase.php:117
getModuleName()
Get the name of the module being executed by this instance.
Definition ApiBase.php:497
const PARAM_ISMULTI
Definition ApiBase.php:77
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.
UserGroupManager $userGroupManager
static getCentralUserInfo(Config $config, UserIdentity $user, $attachedWiki=UserIdentity::LOCAL)
Get central user info.
getHelpUrls()
Return links to more detailed help pages about the module.
UserOptionsLookup $userOptionsLookup
UserEditTracker $userEditTracker
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.
TalkPageNotificationManager $talkPageNotificationManager
__construct(ApiQuery $query, $moduleName, TalkPageNotificationManager $talkPageNotificationManager, WatchedItemStore $watchedItemStore, UserEditTracker $userEditTracker, UserOptionsLookup $userOptionsLookup, UserGroupManager $userGroupManager)
WatchedItemStore $watchedItemStore
This is the main query class.
Definition ApiQuery.php:37
MediaWikiServices is the service locator for the application scope of MediaWiki.
Track info about user edit counts and timings.
Provides access to user options.
Storage layer class for WatchedItems.
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