Avoid IDEA warning about $keys being both a parameter and loop variable
[mediawiki.git] / includes / api / ApiQueryUserInfo.php
blob60e122cdd142419ab3226fd74d9a16f387555211
1 <?php
2 /**
5 * Created on July 30, 2007
7 * Copyright © 2007 Yuri Astrakhan "<Firstname><Lastname>@gmail.com"
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 * http://www.gnu.org/copyleft/gpl.html
24 * @file
27 use MediaWiki\MediaWikiServices;
29 /**
30 * Query module to get information about the currently logged-in user
32 * @ingroup API
34 class ApiQueryUserInfo extends ApiQueryBase {
36 const WL_UNREAD_LIMIT = 1000;
38 private $params = [];
39 private $prop = [];
41 public function __construct( ApiQuery $query, $moduleName ) {
42 parent::__construct( $query, $moduleName, 'ui' );
45 public function execute() {
46 $this->params = $this->extractRequestParams();
47 $result = $this->getResult();
49 if ( !is_null( $this->params['prop'] ) ) {
50 $this->prop = array_flip( $this->params['prop'] );
53 $r = $this->getCurrentUserInfo();
54 $result->addValue( 'query', $this->getModuleName(), $r );
57 /**
58 * Get basic info about a given block
59 * @param Block $block
60 * @return array Array containing several keys:
61 * - blockid - ID of the block
62 * - blockedby - username of the blocker
63 * - blockedbyid - user ID of the blocker
64 * - blockreason - reason provided for the block
65 * - blockedtimestamp - timestamp for when the block was placed/modified
66 * - blockexpiry - expiry time of the block
67 * - systemblocktype - system block type, if any
69 public static function getBlockInfo( Block $block ) {
70 global $wgContLang;
71 $vals = [];
72 $vals['blockid'] = $block->getId();
73 $vals['blockedby'] = $block->getByName();
74 $vals['blockedbyid'] = $block->getBy();
75 $vals['blockreason'] = $block->mReason;
76 $vals['blockedtimestamp'] = wfTimestamp( TS_ISO_8601, $block->mTimestamp );
77 $vals['blockexpiry'] = $wgContLang->formatExpiry(
78 $block->getExpiry(), TS_ISO_8601, 'infinite'
80 if ( $block->getSystemBlockType() !== null ) {
81 $vals['systemblocktype'] = $block->getSystemBlockType();
83 return $vals;
86 /**
87 * Get central user info
88 * @param Config $config
89 * @param User $user
90 * @param string|null $attachedWiki
91 * @return array Central user info
92 * - centralids: Array mapping non-local Central ID provider names to IDs
93 * - attachedlocal: Array mapping Central ID provider names to booleans
94 * indicating whether the local user is attached.
95 * - attachedwiki: Array mapping Central ID provider names to booleans
96 * indicating whether the user is attached to $attachedWiki.
98 public static function getCentralUserInfo( Config $config, User $user, $attachedWiki = null ) {
99 $providerIds = array_keys( $config->get( 'CentralIdLookupProviders' ) );
101 $ret = [
102 'centralids' => [],
103 'attachedlocal' => [],
105 ApiResult::setArrayType( $ret['centralids'], 'assoc' );
106 ApiResult::setArrayType( $ret['attachedlocal'], 'assoc' );
107 if ( $attachedWiki ) {
108 $ret['attachedwiki'] = [];
109 ApiResult::setArrayType( $ret['attachedwiki'], 'assoc' );
112 $name = $user->getName();
113 foreach ( $providerIds as $providerId ) {
114 $provider = CentralIdLookup::factory( $providerId );
115 $ret['centralids'][$providerId] = $provider->centralIdFromName( $name );
116 $ret['attachedlocal'][$providerId] = $provider->isAttached( $user );
117 if ( $attachedWiki ) {
118 $ret['attachedwiki'][$providerId] = $provider->isAttached( $user, $attachedWiki );
122 return $ret;
125 protected function getCurrentUserInfo() {
126 $user = $this->getUser();
127 $vals = [];
128 $vals['id'] = intval( $user->getId() );
129 $vals['name'] = $user->getName();
131 if ( $user->isAnon() ) {
132 $vals['anon'] = true;
135 if ( isset( $this->prop['blockinfo'] ) && $user->isBlocked() ) {
136 $vals = array_merge( $vals, self::getBlockInfo( $user->getBlock() ) );
139 if ( isset( $this->prop['hasmsg'] ) ) {
140 $vals['messages'] = $user->getNewtalk();
143 if ( isset( $this->prop['groups'] ) ) {
144 $vals['groups'] = $user->getEffectiveGroups();
145 ApiResult::setArrayType( $vals['groups'], 'array' ); // even if empty
146 ApiResult::setIndexedTagName( $vals['groups'], 'g' ); // even if empty
149 if ( isset( $this->prop['implicitgroups'] ) ) {
150 $vals['implicitgroups'] = $user->getAutomaticGroups();
151 ApiResult::setArrayType( $vals['implicitgroups'], 'array' ); // even if empty
152 ApiResult::setIndexedTagName( $vals['implicitgroups'], 'g' ); // even if empty
155 if ( isset( $this->prop['rights'] ) ) {
156 // User::getRights() may return duplicate values, strip them
157 $vals['rights'] = array_values( array_unique( $user->getRights() ) );
158 ApiResult::setArrayType( $vals['rights'], 'array' ); // even if empty
159 ApiResult::setIndexedTagName( $vals['rights'], 'r' ); // even if empty
162 if ( isset( $this->prop['changeablegroups'] ) ) {
163 $vals['changeablegroups'] = $user->changeableGroups();
164 ApiResult::setIndexedTagName( $vals['changeablegroups']['add'], 'g' );
165 ApiResult::setIndexedTagName( $vals['changeablegroups']['remove'], 'g' );
166 ApiResult::setIndexedTagName( $vals['changeablegroups']['add-self'], 'g' );
167 ApiResult::setIndexedTagName( $vals['changeablegroups']['remove-self'], 'g' );
170 if ( isset( $this->prop['options'] ) ) {
171 $vals['options'] = $user->getOptions();
172 $vals['options'][ApiResult::META_BC_BOOLS] = array_keys( $vals['options'] );
175 if ( isset( $this->prop['preferencestoken'] ) ) {
176 $p = $this->getModulePrefix();
177 $this->addDeprecation(
179 'apiwarn-deprecation-withreplacement',
180 "{$p}prop=preferencestoken",
181 'action=query&meta=tokens',
183 "meta=userinfo&{$p}prop=preferencestoken"
186 if ( isset( $this->prop['preferencestoken'] ) &&
187 !$this->lacksSameOriginSecurity() &&
188 $user->isAllowed( 'editmyoptions' )
190 $vals['preferencestoken'] = $user->getEditToken( '', $this->getMain()->getRequest() );
193 if ( isset( $this->prop['editcount'] ) ) {
194 // use intval to prevent null if a non-logged-in user calls
195 // api.php?format=jsonfm&action=query&meta=userinfo&uiprop=editcount
196 $vals['editcount'] = intval( $user->getEditCount() );
199 if ( isset( $this->prop['ratelimits'] ) ) {
200 $vals['ratelimits'] = $this->getRateLimits();
203 if ( isset( $this->prop['realname'] ) &&
204 !in_array( 'realname', $this->getConfig()->get( 'HiddenPrefs' ) )
206 $vals['realname'] = $user->getRealName();
209 if ( $user->isAllowed( 'viewmyprivateinfo' ) ) {
210 if ( isset( $this->prop['email'] ) ) {
211 $vals['email'] = $user->getEmail();
212 $auth = $user->getEmailAuthenticationTimestamp();
213 if ( !is_null( $auth ) ) {
214 $vals['emailauthenticated'] = wfTimestamp( TS_ISO_8601, $auth );
219 if ( isset( $this->prop['registrationdate'] ) ) {
220 $regDate = $user->getRegistration();
221 if ( $regDate !== false ) {
222 $vals['registrationdate'] = wfTimestamp( TS_ISO_8601, $regDate );
226 if ( isset( $this->prop['acceptlang'] ) ) {
227 $langs = $this->getRequest()->getAcceptLang();
228 $acceptLang = [];
229 foreach ( $langs as $lang => $val ) {
230 $r = [ 'q' => $val ];
231 ApiResult::setContentValue( $r, 'code', $lang );
232 $acceptLang[] = $r;
234 ApiResult::setIndexedTagName( $acceptLang, 'lang' );
235 $vals['acceptlang'] = $acceptLang;
238 if ( isset( $this->prop['unreadcount'] ) ) {
239 $store = MediaWikiServices::getInstance()->getWatchedItemStore();
240 $unreadNotifications = $store->countUnreadNotifications(
241 $user,
242 self::WL_UNREAD_LIMIT
245 if ( $unreadNotifications === true ) {
246 $vals['unreadcount'] = self::WL_UNREAD_LIMIT . '+';
247 } else {
248 $vals['unreadcount'] = $unreadNotifications;
252 if ( isset( $this->prop['centralids'] ) ) {
253 $vals += self::getCentralUserInfo(
254 $this->getConfig(), $this->getUser(), $this->params['attachedwiki']
258 return $vals;
261 protected function getRateLimits() {
262 $retval = [
263 ApiResult::META_TYPE => 'assoc',
266 $user = $this->getUser();
267 if ( !$user->isPingLimitable() ) {
268 return $retval; // No limits
271 // Find out which categories we belong to
272 $categories = [];
273 if ( $user->isAnon() ) {
274 $categories[] = 'anon';
275 } else {
276 $categories[] = 'user';
278 if ( $user->isNewbie() ) {
279 $categories[] = 'ip';
280 $categories[] = 'subnet';
281 if ( !$user->isAnon() ) {
282 $categories[] = 'newbie';
285 $categories = array_merge( $categories, $user->getGroups() );
287 // Now get the actual limits
288 foreach ( $this->getConfig()->get( 'RateLimits' ) as $action => $limits ) {
289 foreach ( $categories as $cat ) {
290 if ( isset( $limits[$cat] ) && !is_null( $limits[$cat] ) ) {
291 $retval[$action][$cat]['hits'] = intval( $limits[$cat][0] );
292 $retval[$action][$cat]['seconds'] = intval( $limits[$cat][1] );
297 return $retval;
300 public function getAllowedParams() {
301 return [
302 'prop' => [
303 ApiBase::PARAM_ISMULTI => true,
304 ApiBase::PARAM_TYPE => [
305 'blockinfo',
306 'hasmsg',
307 'groups',
308 'implicitgroups',
309 'rights',
310 'changeablegroups',
311 'options',
312 'preferencestoken',
313 'editcount',
314 'ratelimits',
315 'email',
316 'realname',
317 'acceptlang',
318 'registrationdate',
319 'unreadcount',
320 'centralids',
322 ApiBase::PARAM_HELP_MSG_PER_VALUE => [
323 'unreadcount' => [
324 'apihelp-query+userinfo-paramvalue-prop-unreadcount',
325 self::WL_UNREAD_LIMIT - 1,
326 self::WL_UNREAD_LIMIT . '+',
330 'attachedwiki' => null,
334 protected function getExamplesMessages() {
335 return [
336 'action=query&meta=userinfo'
337 => 'apihelp-query+userinfo-example-simple',
338 'action=query&meta=userinfo&uiprop=blockinfo|groups|rights|hasmsg'
339 => 'apihelp-query+userinfo-example-data',
343 public function getHelpUrls() {
344 return 'https://www.mediawiki.org/wiki/API:Userinfo';