MediaWiki fundraising/REL1_35
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 $vals['ratelimits'] = $this->getRateLimits();
177 }
178
179 if ( isset( $this->prop['realname'] ) &&
180 !in_array( 'realname', $this->getConfig()->get( 'HiddenPrefs' ) )
181 ) {
182 $vals['realname'] = $user->getRealName();
183 }
184
185 if ( $this->getPermissionManager()->userHasRight( $user, 'viewmyprivateinfo' ) &&
186 isset( $this->prop['email'] ) ) {
187 $vals['email'] = $user->getEmail();
188 $auth = $user->getEmailAuthenticationTimestamp();
189 if ( $auth !== null ) {
190 $vals['emailauthenticated'] = wfTimestamp( TS_ISO_8601, $auth );
191 }
192 }
193
194 if ( isset( $this->prop['registrationdate'] ) ) {
195 $regDate = $user->getRegistration();
196 if ( $regDate !== false ) {
197 $vals['registrationdate'] = wfTimestamp( TS_ISO_8601, $regDate );
198 }
199 }
200
201 if ( isset( $this->prop['acceptlang'] ) ) {
202 $langs = $this->getRequest()->getAcceptLang();
203 $acceptLang = [];
204 foreach ( $langs as $lang => $val ) {
205 $r = [ 'q' => $val ];
206 ApiResult::setContentValue( $r, 'code', $lang );
207 $acceptLang[] = $r;
208 }
209 ApiResult::setIndexedTagName( $acceptLang, 'lang' );
210 $vals['acceptlang'] = $acceptLang;
211 }
212
213 if ( isset( $this->prop['unreadcount'] ) ) {
214 $store = MediaWikiServices::getInstance()->getWatchedItemStore();
215 $unreadNotifications = $store->countUnreadNotifications(
216 $user,
217 self::WL_UNREAD_LIMIT
218 );
219
220 if ( $unreadNotifications === true ) {
221 $vals['unreadcount'] = self::WL_UNREAD_LIMIT . '+';
222 } else {
223 $vals['unreadcount'] = $unreadNotifications;
224 }
225 }
226
227 if ( isset( $this->prop['centralids'] ) ) {
229 $this->getConfig(), $this->getUser(), $this->params['attachedwiki']
230 );
231 }
232
233 if ( isset( $this->prop['latestcontrib'] ) ) {
234 $ts = $this->getLatestContributionTime();
235 if ( $ts !== null ) {
236 $vals['latestcontrib'] = $ts;
237 }
238 }
239
240 return $vals;
241 }
242
243 protected function getRateLimits() {
244 $retval = [
245 ApiResult::META_TYPE => 'assoc',
246 ];
247
248 $user = $this->getUser();
249 if ( !$user->isPingLimitable() ) {
250 return $retval; // No limits
251 }
252
253 // Find out which categories we belong to
254 $categories = [];
255 if ( $user->isAnon() ) {
256 $categories[] = 'anon';
257 } else {
258 $categories[] = 'user';
259 }
260 if ( $user->isNewbie() ) {
261 $categories[] = 'ip';
262 $categories[] = 'subnet';
263 if ( !$user->isAnon() ) {
264 $categories[] = 'newbie';
265 }
266 }
267 $categories = array_merge( $categories, $user->getGroups() );
268
269 // Now get the actual limits
270 foreach ( $this->getConfig()->get( 'RateLimits' ) as $action => $limits ) {
271 foreach ( $categories as $cat ) {
272 if ( isset( $limits[$cat] ) ) {
273 $retval[$action][$cat]['hits'] = (int)$limits[$cat][0];
274 $retval[$action][$cat]['seconds'] = (int)$limits[$cat][1];
275 }
276 }
277 }
278
279 return $retval;
280 }
281
285 protected function getLatestContributionTime() {
286 $user = $this->getUser();
287 $dbr = $this->getDB();
288
289 if ( $user->getActorId() === null ) {
290 return null;
291 }
292 $res = $dbr->selectField( 'revision_actor_temp',
293 'MAX(revactor_timestamp)',
294 [ 'revactor_actor' => $user->getActorId() ],
295 __METHOD__
296 );
297
298 return $res ? wfTimestamp( TS_ISO_8601, $res ) : null;
299 }
300
301 public function getAllowedParams() {
302 return [
303 'prop' => [
305 ApiBase::PARAM_ALL => true,
307 'blockinfo',
308 'hasmsg',
309 'groups',
310 'groupmemberships',
311 'implicitgroups',
312 'rights',
313 'changeablegroups',
314 'options',
315 'editcount',
316 'ratelimits',
317 'email',
318 'realname',
319 'acceptlang',
320 'registrationdate',
321 'unreadcount',
322 'centralids',
323 'preferencestoken',
324 'latestcontrib',
325 ],
327 'unreadcount' => [
328 'apihelp-query+userinfo-paramvalue-prop-unreadcount',
329 self::WL_UNREAD_LIMIT - 1,
330 self::WL_UNREAD_LIMIT . '+',
331 ],
332 ],
334 'preferencestoken' => [
335 'apiwarn-deprecation-withreplacement',
336 $this->getModulePrefix() . "prop=preferencestoken",
337 'action=query&meta=tokens',
338 ]
339 ],
340 ],
341 'attachedwiki' => null,
342 ];
343 }
344
345 protected function getExamplesMessages() {
346 return [
347 'action=query&meta=userinfo'
348 => 'apihelp-query+userinfo-example-simple',
349 'action=query&meta=userinfo&uiprop=blockinfo|groups|rights|hasmsg'
350 => 'apihelp-query+userinfo-example-data',
351 ];
352 }
353
354 public function getHelpUrls() {
355 return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Userinfo';
356 }
357}
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
getModulePrefix()
Get parameter prefix (usually two letters or an empty string).
Definition ApiBase.php:507
const PARAM_DEPRECATED_VALUES
Definition ApiBase.php:126
getMain()
Get the main module.
Definition ApiBase.php:515
const PARAM_TYPE
Definition ApiBase.php:78
getPermissionManager()
Obtain a PermissionManager instance that subclasses may use in their authorization checks.
Definition ApiBase.php:692
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:620
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition ApiBase.php:772
const PARAM_ALL
Definition ApiBase.php:114
getModuleName()
Get the name of the module being executed by this instance.
Definition ApiBase.php:499
const PARAM_ISMULTI
Definition ApiBase.php:74
lacksSameOriginSecurity()
Returns true if the current request breaks the same-origin policy.
Definition ApiBase.php:548
This is a base class for all Query modules.
getDB()
Get the Query database connection (read-only) Stable to override.
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.
__construct(ApiQuery $query, $moduleName)
This is the main query class.
Definition ApiQuery.php:37
getUser()
Stable to override.
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:60
getName()
Get the user name, or the IP of an anonymous user.
Definition User.php:2150
trait ApiBlockInfoTrait
Interface for configuration instances.
Definition Config.php:29
get( $name)
Get a configuration variable such as "Sitename" or "UploadMaintenance.".
if(!isset( $args[0])) $lang