Add tests for WikiMap and WikiReference
[lhc/web/wiklou.git] / includes / api / ApiQueryUserInfo.php
1 <?php
2 /**
3 *
4 *
5 * Created on July 30, 2007
6 *
7 * Copyright © 2007 Yuri Astrakhan "<Firstname><Lastname>@gmail.com"
8 *
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.
13 *
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.
18 *
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
23 *
24 * @file
25 */
26
27 /**
28 * Query module to get information about the currently logged-in user
29 *
30 * @ingroup API
31 */
32 class ApiQueryUserInfo extends ApiQueryBase {
33
34 const WL_UNREAD_LIMIT = 1000;
35
36 private $prop = array();
37
38 public function __construct( ApiQuery $query, $moduleName ) {
39 parent::__construct( $query, $moduleName, 'ui' );
40 }
41
42 public function execute() {
43 $params = $this->extractRequestParams();
44 $result = $this->getResult();
45
46 if ( !is_null( $params['prop'] ) ) {
47 $this->prop = array_flip( $params['prop'] );
48 }
49
50 $r = $this->getCurrentUserInfo();
51 $result->addValue( 'query', $this->getModuleName(), $r );
52 }
53
54 /**
55 * Get basic info about a given block
56 * @param Block $block
57 * @return array Array containing several keys:
58 * - blockid - ID of the block
59 * - blockedby - username of the blocker
60 * - blockedbyid - user ID of the blocker
61 * - blockreason - reason provided for the block
62 * - blockedtimestamp - timestamp for when the block was placed/modified
63 * - blockexpiry - expiry time of the block
64 */
65 public static function getBlockInfo( Block $block ) {
66 global $wgContLang;
67 $vals = array();
68 $vals['blockid'] = $block->getId();
69 $vals['blockedby'] = $block->getByName();
70 $vals['blockedbyid'] = $block->getBy();
71 $vals['blockreason'] = $block->mReason;
72 $vals['blockedtimestamp'] = wfTimestamp( TS_ISO_8601, $block->mTimestamp );
73 $vals['blockexpiry'] = $wgContLang->formatExpiry(
74 $block->getExpiry(), TS_ISO_8601, 'infinite'
75 );
76 return $vals;
77 }
78
79 protected function getCurrentUserInfo() {
80 $user = $this->getUser();
81 $result = $this->getResult();
82 $vals = array();
83 $vals['id'] = intval( $user->getId() );
84 $vals['name'] = $user->getName();
85
86 if ( $user->isAnon() ) {
87 $vals['anon'] = true;
88 }
89
90 if ( isset( $this->prop['blockinfo'] ) && $user->isBlocked() ) {
91 $vals = array_merge( $vals, self::getBlockInfo( $user->getBlock() ) );
92 }
93
94 if ( isset( $this->prop['hasmsg'] ) ) {
95 $vals['messages'] = $user->getNewtalk();
96 }
97
98 if ( isset( $this->prop['groups'] ) ) {
99 $vals['groups'] = $user->getEffectiveGroups();
100 ApiResult::setArrayType( $vals['groups'], 'array' ); // even if empty
101 ApiResult::setIndexedTagName( $vals['groups'], 'g' ); // even if empty
102 }
103
104 if ( isset( $this->prop['implicitgroups'] ) ) {
105 $vals['implicitgroups'] = $user->getAutomaticGroups();
106 ApiResult::setArrayType( $vals['implicitgroups'], 'array' ); // even if empty
107 ApiResult::setIndexedTagName( $vals['implicitgroups'], 'g' ); // even if empty
108 }
109
110 if ( isset( $this->prop['rights'] ) ) {
111 // User::getRights() may return duplicate values, strip them
112 $vals['rights'] = array_values( array_unique( $user->getRights() ) );
113 ApiResult::setArrayType( $vals['rights'], 'array' ); // even if empty
114 ApiResult::setIndexedTagName( $vals['rights'], 'r' ); // even if empty
115 }
116
117 if ( isset( $this->prop['changeablegroups'] ) ) {
118 $vals['changeablegroups'] = $user->changeableGroups();
119 ApiResult::setIndexedTagName( $vals['changeablegroups']['add'], 'g' );
120 ApiResult::setIndexedTagName( $vals['changeablegroups']['remove'], 'g' );
121 ApiResult::setIndexedTagName( $vals['changeablegroups']['add-self'], 'g' );
122 ApiResult::setIndexedTagName( $vals['changeablegroups']['remove-self'], 'g' );
123 }
124
125 if ( isset( $this->prop['options'] ) ) {
126 $vals['options'] = $user->getOptions();
127 $vals['options'][ApiResult::META_BC_BOOLS] = array_keys( $vals['options'] );
128 }
129
130 if ( isset( $this->prop['preferencestoken'] ) ) {
131 $p = $this->getModulePrefix();
132 $this->setWarning(
133 "{$p}prop=preferencestoken has been deprecated. Please use action=query&meta=tokens instead."
134 );
135 }
136 if ( isset( $this->prop['preferencestoken'] ) &&
137 !$this->lacksSameOriginSecurity() &&
138 $user->isAllowed( 'editmyoptions' )
139 ) {
140 $vals['preferencestoken'] = $user->getEditToken( '', $this->getMain()->getRequest() );
141 }
142
143 if ( isset( $this->prop['editcount'] ) ) {
144 // use intval to prevent null if a non-logged-in user calls
145 // api.php?format=jsonfm&action=query&meta=userinfo&uiprop=editcount
146 $vals['editcount'] = intval( $user->getEditCount() );
147 }
148
149 if ( isset( $this->prop['ratelimits'] ) ) {
150 $vals['ratelimits'] = $this->getRateLimits();
151 }
152
153 if ( isset( $this->prop['realname'] ) && !in_array( 'realname', $this->getConfig()->get( 'HiddenPrefs' ) ) ) {
154 $vals['realname'] = $user->getRealName();
155 }
156
157 if ( $user->isAllowed( 'viewmyprivateinfo' ) ) {
158 if ( isset( $this->prop['email'] ) ) {
159 $vals['email'] = $user->getEmail();
160 $auth = $user->getEmailAuthenticationTimestamp();
161 if ( !is_null( $auth ) ) {
162 $vals['emailauthenticated'] = wfTimestamp( TS_ISO_8601, $auth );
163 }
164 }
165 }
166
167 if ( isset( $this->prop['registrationdate'] ) ) {
168 $regDate = $user->getRegistration();
169 if ( $regDate !== false ) {
170 $vals['registrationdate'] = wfTimestamp( TS_ISO_8601, $regDate );
171 }
172 }
173
174 if ( isset( $this->prop['acceptlang'] ) ) {
175 $langs = $this->getRequest()->getAcceptLang();
176 $acceptLang = array();
177 foreach ( $langs as $lang => $val ) {
178 $r = array( 'q' => $val );
179 ApiResult::setContentValue( $r, 'code', $lang );
180 $acceptLang[] = $r;
181 }
182 ApiResult::setIndexedTagName( $acceptLang, 'lang' );
183 $vals['acceptlang'] = $acceptLang;
184 }
185
186 if ( isset( $this->prop['unreadcount'] ) ) {
187 $dbr = $this->getQuery()->getNamedDB( 'watchlist', DB_SLAVE, 'watchlist' );
188
189 $count = $dbr->selectRowCount(
190 'watchlist',
191 '1',
192 array(
193 'wl_user' => $user->getId(),
194 'wl_notificationtimestamp IS NOT NULL',
195 ),
196 __METHOD__,
197 array( 'LIMIT' => self::WL_UNREAD_LIMIT )
198 );
199
200 if ( $count >= self::WL_UNREAD_LIMIT ) {
201 $vals['unreadcount'] = self::WL_UNREAD_LIMIT . '+';
202 } else {
203 $vals['unreadcount'] = $count;
204 }
205 }
206
207 return $vals;
208 }
209
210 protected function getRateLimits() {
211 $retval = array(
212 ApiResult::META_TYPE => 'assoc',
213 );
214
215 $user = $this->getUser();
216 if ( !$user->isPingLimitable() ) {
217 return $retval; // No limits
218 }
219
220 // Find out which categories we belong to
221 $categories = array();
222 if ( $user->isAnon() ) {
223 $categories[] = 'anon';
224 } else {
225 $categories[] = 'user';
226 }
227 if ( $user->isNewbie() ) {
228 $categories[] = 'ip';
229 $categories[] = 'subnet';
230 if ( !$user->isAnon() ) {
231 $categories[] = 'newbie';
232 }
233 }
234 $categories = array_merge( $categories, $user->getGroups() );
235
236 // Now get the actual limits
237 foreach ( $this->getConfig()->get( 'RateLimits' ) as $action => $limits ) {
238 foreach ( $categories as $cat ) {
239 if ( isset( $limits[$cat] ) && !is_null( $limits[$cat] ) ) {
240 $retval[$action][$cat]['hits'] = intval( $limits[$cat][0] );
241 $retval[$action][$cat]['seconds'] = intval( $limits[$cat][1] );
242 }
243 }
244 }
245
246 return $retval;
247 }
248
249 public function getAllowedParams() {
250 return array(
251 'prop' => array(
252 ApiBase::PARAM_DFLT => null,
253 ApiBase::PARAM_ISMULTI => true,
254 ApiBase::PARAM_TYPE => array(
255 'blockinfo',
256 'hasmsg',
257 'groups',
258 'implicitgroups',
259 'rights',
260 'changeablegroups',
261 'options',
262 'preferencestoken',
263 'editcount',
264 'ratelimits',
265 'email',
266 'realname',
267 'acceptlang',
268 'registrationdate',
269 'unreadcount',
270 ),
271 ApiBase::PARAM_HELP_MSG_PER_VALUE => array(
272 'unreadcount' => array(
273 'apihelp-query+userinfo-paramvalue-prop-unreadcount',
274 self::WL_UNREAD_LIMIT - 1,
275 self::WL_UNREAD_LIMIT . '+',
276 ),
277 ),
278 )
279 );
280 }
281
282 protected function getExamplesMessages() {
283 return array(
284 'action=query&meta=userinfo'
285 => 'apihelp-query+userinfo-example-simple',
286 'action=query&meta=userinfo&uiprop=blockinfo|groups|rights|hasmsg'
287 => 'apihelp-query+userinfo-example-data',
288 );
289 }
290
291 public function getHelpUrls() {
292 return 'https://www.mediawiki.org/wiki/API:Userinfo';
293 }
294 }