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