Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
86.93% |
306 / 352 |
|
50.00% |
5 / 10 |
CRAP | |
0.00% |
0 / 1 |
ApiQueryWatchlist | |
86.93% |
306 / 352 |
|
50.00% |
5 / 10 |
134.03 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
1 | |||
execute | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
executeGenerator | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
run | |
88.30% |
83 / 94 |
|
0.00% |
0 / 1 |
40.31 | |||
getFieldsToInclude | |
94.74% |
18 / 19 |
|
0.00% |
0 / 1 |
13.02 | |||
showParamsConflicting | |
100.00% |
14 / 14 |
|
100.00% |
1 / 1 |
14 | |||
extractOutputData | |
83.50% |
86 / 103 |
|
0.00% |
0 / 1 |
43.16 | |||
getAllowedParams | |
100.00% |
95 / 95 |
|
100.00% |
1 / 1 |
1 | |||
getExamplesMessages | |
0.00% |
0 / 16 |
|
0.00% |
0 / 1 |
2 | |||
getHelpUrls | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | /** |
3 | * Copyright © 2006 Yuri Astrakhan "<Firstname><Lastname>@gmail.com" |
4 | * |
5 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by |
7 | * the Free Software Foundation; either version 2 of the License, or |
8 | * (at your option) any later version. |
9 | * |
10 | * This program is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | * GNU General Public License for more details. |
14 | * |
15 | * You should have received a copy of the GNU General Public License along |
16 | * with this program; if not, write to the Free Software Foundation, Inc., |
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
18 | * http://www.gnu.org/copyleft/gpl.html |
19 | * |
20 | * @file |
21 | */ |
22 | |
23 | use MediaWiki\Cache\GenderCache; |
24 | use MediaWiki\CommentFormatter\CommentFormatter; |
25 | use MediaWiki\CommentStore\CommentStore; |
26 | use MediaWiki\Linker\LinkTarget; |
27 | use MediaWiki\ParamValidator\TypeDef\UserDef; |
28 | use MediaWiki\Revision\RevisionRecord; |
29 | use MediaWiki\Title\NamespaceInfo; |
30 | use MediaWiki\Title\Title; |
31 | use MediaWiki\User\TempUser\TempUserConfig; |
32 | use Wikimedia\ParamValidator\ParamValidator; |
33 | use Wikimedia\ParamValidator\TypeDef\IntegerDef; |
34 | |
35 | /** |
36 | * This query action allows clients to retrieve a list of recently modified pages |
37 | * that are part of the logged-in user's watchlist. |
38 | * |
39 | * @ingroup API |
40 | */ |
41 | class ApiQueryWatchlist extends ApiQueryGeneratorBase { |
42 | |
43 | private CommentStore $commentStore; |
44 | private WatchedItemQueryService $watchedItemQueryService; |
45 | private Language $contentLanguage; |
46 | private NamespaceInfo $namespaceInfo; |
47 | private GenderCache $genderCache; |
48 | private CommentFormatter $commentFormatter; |
49 | private TempUserConfig $tempUserConfig; |
50 | |
51 | /** |
52 | * @param ApiQuery $query |
53 | * @param string $moduleName |
54 | * @param CommentStore $commentStore |
55 | * @param WatchedItemQueryService $watchedItemQueryService |
56 | * @param Language $contentLanguage |
57 | * @param NamespaceInfo $namespaceInfo |
58 | * @param GenderCache $genderCache |
59 | * @param CommentFormatter $commentFormatter |
60 | * @param TempUserConfig $tempUserConfig |
61 | */ |
62 | public function __construct( |
63 | ApiQuery $query, |
64 | $moduleName, |
65 | CommentStore $commentStore, |
66 | WatchedItemQueryService $watchedItemQueryService, |
67 | Language $contentLanguage, |
68 | NamespaceInfo $namespaceInfo, |
69 | GenderCache $genderCache, |
70 | CommentFormatter $commentFormatter, |
71 | TempUserConfig $tempUserConfig |
72 | ) { |
73 | parent::__construct( $query, $moduleName, 'wl' ); |
74 | $this->commentStore = $commentStore; |
75 | $this->watchedItemQueryService = $watchedItemQueryService; |
76 | $this->contentLanguage = $contentLanguage; |
77 | $this->namespaceInfo = $namespaceInfo; |
78 | $this->genderCache = $genderCache; |
79 | $this->commentFormatter = $commentFormatter; |
80 | $this->tempUserConfig = $tempUserConfig; |
81 | } |
82 | |
83 | public function execute() { |
84 | $this->run(); |
85 | } |
86 | |
87 | public function executeGenerator( $resultPageSet ) { |
88 | $this->run( $resultPageSet ); |
89 | } |
90 | |
91 | private bool $fld_ids = false; |
92 | private bool $fld_title = false; |
93 | private bool $fld_patrol = false; |
94 | private bool $fld_flags = false; |
95 | private bool $fld_timestamp = false; |
96 | private bool $fld_user = false; |
97 | private bool $fld_comment = false; |
98 | private bool $fld_parsedcomment = false; |
99 | private bool $fld_sizes = false; |
100 | private bool $fld_notificationtimestamp = false; |
101 | private bool $fld_userid = false; |
102 | private bool $fld_loginfo = false; |
103 | private bool $fld_tags = false; |
104 | private bool $fld_expiry = false; |
105 | |
106 | /** |
107 | * @param ApiPageSet|null $resultPageSet |
108 | * @return void |
109 | */ |
110 | private function run( $resultPageSet = null ) { |
111 | $params = $this->extractRequestParams(); |
112 | |
113 | $user = $this->getUser(); |
114 | $wlowner = $this->getWatchlistUser( $params ); |
115 | |
116 | if ( $params['prop'] !== null && $resultPageSet === null ) { |
117 | $prop = array_fill_keys( $params['prop'], true ); |
118 | |
119 | $this->fld_ids = isset( $prop['ids'] ); |
120 | $this->fld_title = isset( $prop['title'] ); |
121 | $this->fld_flags = isset( $prop['flags'] ); |
122 | $this->fld_user = isset( $prop['user'] ); |
123 | $this->fld_userid = isset( $prop['userid'] ); |
124 | $this->fld_comment = isset( $prop['comment'] ); |
125 | $this->fld_parsedcomment = isset( $prop['parsedcomment'] ); |
126 | $this->fld_timestamp = isset( $prop['timestamp'] ); |
127 | $this->fld_sizes = isset( $prop['sizes'] ); |
128 | $this->fld_patrol = isset( $prop['patrol'] ); |
129 | $this->fld_notificationtimestamp = isset( $prop['notificationtimestamp'] ); |
130 | $this->fld_loginfo = isset( $prop['loginfo'] ); |
131 | $this->fld_tags = isset( $prop['tags'] ); |
132 | $this->fld_expiry = isset( $prop['expiry'] ); |
133 | |
134 | if ( $this->fld_patrol && !$user->useRCPatrol() && !$user->useNPPatrol() ) { |
135 | $this->dieWithError( 'apierror-permissiondenied-patrolflag', 'patrol' ); |
136 | } |
137 | } |
138 | |
139 | $options = [ |
140 | 'dir' => $params['dir'] === 'older' |
141 | ? WatchedItemQueryService::DIR_OLDER |
142 | : WatchedItemQueryService::DIR_NEWER, |
143 | ]; |
144 | |
145 | if ( $resultPageSet === null ) { |
146 | $options['includeFields'] = $this->getFieldsToInclude(); |
147 | } else { |
148 | $options['usedInGenerator'] = true; |
149 | } |
150 | |
151 | if ( $params['start'] ) { |
152 | $options['start'] = $params['start']; |
153 | } |
154 | if ( $params['end'] ) { |
155 | $options['end'] = $params['end']; |
156 | } |
157 | |
158 | $startFrom = null; |
159 | if ( $params['continue'] !== null ) { |
160 | $cont = $this->parseContinueParamOrDie( $params['continue'], [ 'string', 'int' ] ); |
161 | $startFrom = $cont; |
162 | } |
163 | |
164 | if ( $wlowner !== $user ) { |
165 | $options['watchlistOwner'] = $wlowner; |
166 | $options['watchlistOwnerToken'] = $params['token']; |
167 | } |
168 | |
169 | if ( $params['namespace'] !== null ) { |
170 | $options['namespaceIds'] = $params['namespace']; |
171 | } |
172 | |
173 | if ( $params['allrev'] ) { |
174 | $options['allRevisions'] = true; |
175 | } |
176 | |
177 | if ( $params['show'] !== null ) { |
178 | $show = array_fill_keys( $params['show'], true ); |
179 | |
180 | /* Check for conflicting parameters. */ |
181 | if ( $this->showParamsConflicting( $show ) ) { |
182 | $this->dieWithError( 'apierror-show' ); |
183 | } |
184 | |
185 | // Check permissions. |
186 | if ( isset( $show[WatchedItemQueryService::FILTER_PATROLLED] ) |
187 | || isset( $show[WatchedItemQueryService::FILTER_NOT_PATROLLED] ) |
188 | ) { |
189 | if ( !$user->useRCPatrol() && !$user->useNPPatrol() ) { |
190 | $this->dieWithError( 'apierror-permissiondenied-patrolflag', 'permissiondenied' ); |
191 | } |
192 | } |
193 | |
194 | $options['filters'] = array_keys( $show ); |
195 | } |
196 | |
197 | if ( $params['type'] !== null ) { |
198 | $rcTypes = RecentChange::parseToRCType( $params['type'] ); |
199 | if ( $rcTypes ) { |
200 | $options['rcTypes'] = $rcTypes; |
201 | } |
202 | } |
203 | |
204 | $this->requireMaxOneParameter( $params, 'user', 'excludeuser' ); |
205 | if ( $params['user'] !== null ) { |
206 | $options['onlyByUser'] = $params['user']; |
207 | } |
208 | if ( $params['excludeuser'] !== null ) { |
209 | $options['notByUser'] = $params['excludeuser']; |
210 | } |
211 | |
212 | $options['limit'] = $params['limit']; |
213 | |
214 | $this->getHookRunner()->onApiQueryWatchlistPrepareWatchedItemQueryServiceOptions( |
215 | $this, $params, $options ); |
216 | |
217 | $ids = []; |
218 | $items = $this->watchedItemQueryService->getWatchedItemsWithRecentChangeInfo( $wlowner, $options, $startFrom ); |
219 | |
220 | // Get gender information |
221 | if ( $items !== [] && $resultPageSet === null && $this->fld_title && |
222 | $this->contentLanguage->needsGenderDistinction() |
223 | ) { |
224 | $usernames = []; |
225 | foreach ( $items as [ $watchedItem, ] ) { |
226 | /** @var WatchedItem $watchedItem */ |
227 | $linkTarget = $watchedItem->getTarget(); |
228 | if ( $this->namespaceInfo->hasGenderDistinction( $linkTarget->getNamespace() ) ) { |
229 | $usernames[] = $linkTarget->getText(); |
230 | } |
231 | } |
232 | if ( $usernames !== [] ) { |
233 | $this->genderCache->doQuery( $usernames, __METHOD__ ); |
234 | } |
235 | } |
236 | |
237 | foreach ( $items as [ $watchedItem, $recentChangeInfo ] ) { |
238 | /** @var WatchedItem $watchedItem */ |
239 | if ( $resultPageSet === null ) { |
240 | $vals = $this->extractOutputData( $watchedItem, $recentChangeInfo ); |
241 | $fit = $this->getResult()->addValue( [ 'query', $this->getModuleName() ], null, $vals ); |
242 | if ( !$fit ) { |
243 | $startFrom = [ $recentChangeInfo['rc_timestamp'], $recentChangeInfo['rc_id'] ]; |
244 | break; |
245 | } |
246 | } elseif ( $params['allrev'] ) { |
247 | $ids[] = (int)$recentChangeInfo['rc_this_oldid']; |
248 | } else { |
249 | $ids[] = (int)$recentChangeInfo['rc_cur_id']; |
250 | } |
251 | } |
252 | |
253 | if ( $startFrom !== null ) { |
254 | $this->setContinueEnumParameter( 'continue', implode( '|', $startFrom ) ); |
255 | } |
256 | |
257 | if ( $resultPageSet === null ) { |
258 | $this->getResult()->addIndexedTagName( |
259 | [ 'query', $this->getModuleName() ], |
260 | 'item' |
261 | ); |
262 | } elseif ( $params['allrev'] ) { |
263 | $resultPageSet->populateFromRevisionIDs( $ids ); |
264 | } else { |
265 | $resultPageSet->populateFromPageIDs( $ids ); |
266 | } |
267 | } |
268 | |
269 | private function getFieldsToInclude() { |
270 | $includeFields = []; |
271 | if ( $this->fld_flags ) { |
272 | $includeFields[] = WatchedItemQueryService::INCLUDE_FLAGS; |
273 | } |
274 | if ( $this->fld_user || $this->fld_userid || $this->fld_loginfo ) { |
275 | $includeFields[] = WatchedItemQueryService::INCLUDE_USER_ID; |
276 | } |
277 | if ( $this->fld_user || $this->fld_loginfo ) { |
278 | $includeFields[] = WatchedItemQueryService::INCLUDE_USER; |
279 | } |
280 | if ( $this->fld_comment || $this->fld_parsedcomment ) { |
281 | $includeFields[] = WatchedItemQueryService::INCLUDE_COMMENT; |
282 | } |
283 | if ( $this->fld_patrol ) { |
284 | $includeFields[] = WatchedItemQueryService::INCLUDE_PATROL_INFO; |
285 | $includeFields[] = WatchedItemQueryService::INCLUDE_AUTOPATROL_INFO; |
286 | } |
287 | if ( $this->fld_sizes ) { |
288 | $includeFields[] = WatchedItemQueryService::INCLUDE_SIZES; |
289 | } |
290 | if ( $this->fld_loginfo ) { |
291 | $includeFields[] = WatchedItemQueryService::INCLUDE_LOG_INFO; |
292 | } |
293 | if ( $this->fld_tags ) { |
294 | $includeFields[] = WatchedItemQueryService::INCLUDE_TAGS; |
295 | } |
296 | return $includeFields; |
297 | } |
298 | |
299 | private function showParamsConflicting( array $show ) { |
300 | return ( isset( $show[WatchedItemQueryService::FILTER_MINOR] ) |
301 | && isset( $show[WatchedItemQueryService::FILTER_NOT_MINOR] ) ) |
302 | || ( isset( $show[WatchedItemQueryService::FILTER_BOT] ) |
303 | && isset( $show[WatchedItemQueryService::FILTER_NOT_BOT] ) ) |
304 | || ( isset( $show[WatchedItemQueryService::FILTER_ANON] ) |
305 | && isset( $show[WatchedItemQueryService::FILTER_NOT_ANON] ) ) |
306 | || ( isset( $show[WatchedItemQueryService::FILTER_PATROLLED] ) |
307 | && isset( $show[WatchedItemQueryService::FILTER_NOT_PATROLLED] ) ) |
308 | || ( isset( $show[WatchedItemQueryService::FILTER_AUTOPATROLLED] ) |
309 | && isset( $show[WatchedItemQueryService::FILTER_NOT_AUTOPATROLLED] ) ) |
310 | || ( isset( $show[WatchedItemQueryService::FILTER_AUTOPATROLLED] ) |
311 | && isset( $show[WatchedItemQueryService::FILTER_NOT_PATROLLED] ) ) |
312 | || ( isset( $show[WatchedItemQueryService::FILTER_UNREAD] ) |
313 | && isset( $show[WatchedItemQueryService::FILTER_NOT_UNREAD] ) ); |
314 | } |
315 | |
316 | private function extractOutputData( WatchedItem $watchedItem, array $recentChangeInfo ) { |
317 | /* Determine the title of the page that has been changed. */ |
318 | $target = $watchedItem->getTarget(); |
319 | if ( $target instanceof LinkTarget ) { |
320 | $title = Title::newFromLinkTarget( $target ); |
321 | } else { |
322 | $title = Title::newFromPageIdentity( $target ); |
323 | } |
324 | $user = $this->getUser(); |
325 | |
326 | /* Our output data. */ |
327 | $vals = []; |
328 | $type = (int)$recentChangeInfo['rc_type']; |
329 | $vals['type'] = RecentChange::parseFromRCType( $type ); |
330 | $anyHidden = false; |
331 | |
332 | /* Create a new entry in the result for the title. */ |
333 | if ( $this->fld_title || $this->fld_ids ) { |
334 | // These should already have been filtered out of the query, but just in case. |
335 | if ( $type === RC_LOG && ( $recentChangeInfo['rc_deleted'] & LogPage::DELETED_ACTION ) ) { |
336 | $vals['actionhidden'] = true; |
337 | $anyHidden = true; |
338 | } |
339 | if ( $type !== RC_LOG || |
340 | LogEventsList::userCanBitfield( |
341 | $recentChangeInfo['rc_deleted'], |
342 | LogPage::DELETED_ACTION, |
343 | $user |
344 | ) |
345 | ) { |
346 | if ( $this->fld_title ) { |
347 | ApiQueryBase::addTitleInfo( $vals, $title ); |
348 | } |
349 | if ( $this->fld_ids ) { |
350 | $vals['pageid'] = (int)$recentChangeInfo['rc_cur_id']; |
351 | $vals['revid'] = (int)$recentChangeInfo['rc_this_oldid']; |
352 | $vals['old_revid'] = (int)$recentChangeInfo['rc_last_oldid']; |
353 | } |
354 | } |
355 | } |
356 | |
357 | if ( $this->fld_user || $this->fld_userid ) { |
358 | if ( $recentChangeInfo['rc_deleted'] & RevisionRecord::DELETED_USER ) { |
359 | $vals['userhidden'] = true; |
360 | $anyHidden = true; |
361 | } |
362 | if ( RevisionRecord::userCanBitfield( |
363 | $recentChangeInfo['rc_deleted'], |
364 | RevisionRecord::DELETED_USER, |
365 | $user |
366 | ) ) { |
367 | if ( $this->fld_userid ) { |
368 | $vals['userid'] = (int)$recentChangeInfo['rc_user']; |
369 | // for backwards compatibility |
370 | $vals['user'] = (int)$recentChangeInfo['rc_user']; |
371 | } |
372 | |
373 | if ( $this->fld_user ) { |
374 | $vals['user'] = $recentChangeInfo['rc_user_text']; |
375 | $vals['temp'] = $this->tempUserConfig->isTempName( |
376 | $recentChangeInfo['rc_user_text'] |
377 | ); |
378 | } |
379 | |
380 | // Whether the user is a logged-out user (IP user). This does |
381 | // not include temporary users, though they are grouped with IP |
382 | // users for FILTER_NOT_ANON and FILTER_ANON, to match the |
383 | // recent changes filters (T343322). |
384 | $vals['anon'] = !$recentChangeInfo['rc_user']; |
385 | |
386 | } |
387 | } |
388 | |
389 | /* Add flags, such as new, minor, bot. */ |
390 | if ( $this->fld_flags ) { |
391 | $vals['bot'] = (bool)$recentChangeInfo['rc_bot']; |
392 | $vals['new'] = $recentChangeInfo['rc_type'] == RC_NEW; |
393 | $vals['minor'] = (bool)$recentChangeInfo['rc_minor']; |
394 | } |
395 | |
396 | /* Add sizes of each revision. (Only available on 1.10+) */ |
397 | if ( $this->fld_sizes ) { |
398 | $vals['oldlen'] = (int)$recentChangeInfo['rc_old_len']; |
399 | $vals['newlen'] = (int)$recentChangeInfo['rc_new_len']; |
400 | } |
401 | |
402 | /* Add the timestamp. */ |
403 | if ( $this->fld_timestamp ) { |
404 | $vals['timestamp'] = wfTimestamp( TS_ISO_8601, $recentChangeInfo['rc_timestamp'] ); |
405 | } |
406 | |
407 | if ( $this->fld_notificationtimestamp ) { |
408 | $vals['notificationtimestamp'] = ( $watchedItem->getNotificationTimestamp() == null ) |
409 | ? '' |
410 | : wfTimestamp( TS_ISO_8601, $watchedItem->getNotificationTimestamp() ); |
411 | } |
412 | |
413 | /* Add edit summary / log summary. */ |
414 | if ( $this->fld_comment || $this->fld_parsedcomment ) { |
415 | if ( $recentChangeInfo['rc_deleted'] & RevisionRecord::DELETED_COMMENT ) { |
416 | $vals['commenthidden'] = true; |
417 | $anyHidden = true; |
418 | } |
419 | if ( RevisionRecord::userCanBitfield( |
420 | $recentChangeInfo['rc_deleted'], |
421 | RevisionRecord::DELETED_COMMENT, |
422 | $user |
423 | ) ) { |
424 | $comment = $this->commentStore->getComment( 'rc_comment', $recentChangeInfo )->text; |
425 | if ( $this->fld_comment ) { |
426 | $vals['comment'] = $comment; |
427 | } |
428 | |
429 | if ( $this->fld_parsedcomment ) { |
430 | $vals['parsedcomment'] = $this->commentFormatter->format( $comment, $title ); |
431 | } |
432 | } |
433 | } |
434 | |
435 | /* Add the patrolled flag */ |
436 | if ( $this->fld_patrol ) { |
437 | $vals['patrolled'] = $recentChangeInfo['rc_patrolled'] != RecentChange::PRC_UNPATROLLED; |
438 | $vals['unpatrolled'] = ChangesList::isUnpatrolled( (object)$recentChangeInfo, $user ); |
439 | $vals['autopatrolled'] = $recentChangeInfo['rc_patrolled'] == RecentChange::PRC_AUTOPATROLLED; |
440 | } |
441 | |
442 | if ( $this->fld_loginfo && $recentChangeInfo['rc_type'] == RC_LOG ) { |
443 | if ( $recentChangeInfo['rc_deleted'] & LogPage::DELETED_ACTION ) { |
444 | $vals['actionhidden'] = true; |
445 | $anyHidden = true; |
446 | } |
447 | if ( LogEventsList::userCanBitfield( |
448 | $recentChangeInfo['rc_deleted'], |
449 | LogPage::DELETED_ACTION, |
450 | $user |
451 | ) ) { |
452 | $vals['logid'] = (int)$recentChangeInfo['rc_logid']; |
453 | $vals['logtype'] = $recentChangeInfo['rc_log_type']; |
454 | $vals['logaction'] = $recentChangeInfo['rc_log_action']; |
455 | |
456 | $logFormatter = LogFormatter::newFromRow( $recentChangeInfo ); |
457 | $vals['logparams'] = $logFormatter->formatParametersForApi(); |
458 | $vals['logdisplay'] = $logFormatter->getActionText(); |
459 | } |
460 | } |
461 | |
462 | if ( $this->fld_tags ) { |
463 | if ( $recentChangeInfo['rc_tags'] ) { |
464 | $tags = explode( ',', $recentChangeInfo['rc_tags'] ); |
465 | ApiResult::setIndexedTagName( $tags, 'tag' ); |
466 | $vals['tags'] = $tags; |
467 | } else { |
468 | $vals['tags'] = []; |
469 | } |
470 | } |
471 | |
472 | if ( $this->fld_expiry ) { |
473 | // Add expiration, T263796 |
474 | $expiry = $watchedItem->getExpiry( TS_ISO_8601 ); |
475 | $vals['expiry'] = ( $expiry ?? false ); |
476 | } |
477 | |
478 | if ( $anyHidden && ( $recentChangeInfo['rc_deleted'] & RevisionRecord::DELETED_RESTRICTED ) ) { |
479 | $vals['suppressed'] = true; |
480 | } |
481 | |
482 | $this->getHookRunner()->onApiQueryWatchlistExtractOutputData( |
483 | $this, $watchedItem, $recentChangeInfo, $vals ); |
484 | |
485 | return $vals; |
486 | } |
487 | |
488 | public function getAllowedParams() { |
489 | return [ |
490 | 'allrev' => false, |
491 | 'start' => [ |
492 | ParamValidator::PARAM_TYPE => 'timestamp' |
493 | ], |
494 | 'end' => [ |
495 | ParamValidator::PARAM_TYPE => 'timestamp' |
496 | ], |
497 | 'namespace' => [ |
498 | ParamValidator::PARAM_ISMULTI => true, |
499 | ParamValidator::PARAM_TYPE => 'namespace' |
500 | ], |
501 | 'user' => [ |
502 | ParamValidator::PARAM_TYPE => 'user', |
503 | UserDef::PARAM_ALLOWED_USER_TYPES => [ 'name', 'ip', 'temp', 'id', 'interwiki' ], |
504 | ], |
505 | 'excludeuser' => [ |
506 | ParamValidator::PARAM_TYPE => 'user', |
507 | UserDef::PARAM_ALLOWED_USER_TYPES => [ 'name', 'ip', 'temp', 'id', 'interwiki' ], |
508 | ], |
509 | 'dir' => [ |
510 | ParamValidator::PARAM_DEFAULT => 'older', |
511 | ParamValidator::PARAM_TYPE => [ |
512 | 'newer', |
513 | 'older' |
514 | ], |
515 | ApiBase::PARAM_HELP_MSG => 'api-help-param-direction', |
516 | ApiBase::PARAM_HELP_MSG_PER_VALUE => [ |
517 | 'newer' => 'api-help-paramvalue-direction-newer', |
518 | 'older' => 'api-help-paramvalue-direction-older', |
519 | ], |
520 | ], |
521 | 'limit' => [ |
522 | ParamValidator::PARAM_DEFAULT => 10, |
523 | ParamValidator::PARAM_TYPE => 'limit', |
524 | IntegerDef::PARAM_MIN => 1, |
525 | IntegerDef::PARAM_MAX => ApiBase::LIMIT_BIG1, |
526 | IntegerDef::PARAM_MAX2 => ApiBase::LIMIT_BIG2 |
527 | ], |
528 | 'prop' => [ |
529 | ParamValidator::PARAM_ISMULTI => true, |
530 | ParamValidator::PARAM_DEFAULT => 'ids|title|flags', |
531 | ApiBase::PARAM_HELP_MSG_PER_VALUE => [], |
532 | ParamValidator::PARAM_TYPE => [ |
533 | 'ids', |
534 | 'title', |
535 | 'flags', |
536 | 'user', |
537 | 'userid', |
538 | 'comment', |
539 | 'parsedcomment', |
540 | 'timestamp', |
541 | 'patrol', |
542 | 'sizes', |
543 | 'notificationtimestamp', |
544 | 'loginfo', |
545 | 'tags', |
546 | 'expiry', |
547 | ] |
548 | ], |
549 | 'show' => [ |
550 | ParamValidator::PARAM_ISMULTI => true, |
551 | ParamValidator::PARAM_TYPE => [ |
552 | WatchedItemQueryService::FILTER_MINOR, |
553 | WatchedItemQueryService::FILTER_NOT_MINOR, |
554 | WatchedItemQueryService::FILTER_BOT, |
555 | WatchedItemQueryService::FILTER_NOT_BOT, |
556 | WatchedItemQueryService::FILTER_ANON, |
557 | WatchedItemQueryService::FILTER_NOT_ANON, |
558 | WatchedItemQueryService::FILTER_PATROLLED, |
559 | WatchedItemQueryService::FILTER_NOT_PATROLLED, |
560 | WatchedItemQueryService::FILTER_AUTOPATROLLED, |
561 | WatchedItemQueryService::FILTER_NOT_AUTOPATROLLED, |
562 | WatchedItemQueryService::FILTER_UNREAD, |
563 | WatchedItemQueryService::FILTER_NOT_UNREAD, |
564 | ] |
565 | ], |
566 | 'type' => [ |
567 | ParamValidator::PARAM_DEFAULT => 'edit|new|log|categorize', |
568 | ParamValidator::PARAM_ISMULTI => true, |
569 | ApiBase::PARAM_HELP_MSG_PER_VALUE => [], |
570 | ParamValidator::PARAM_TYPE => RecentChange::getChangeTypes() |
571 | ], |
572 | 'owner' => [ |
573 | ParamValidator::PARAM_TYPE => 'user', |
574 | UserDef::PARAM_ALLOWED_USER_TYPES => [ 'name' ], |
575 | ], |
576 | 'token' => [ |
577 | ParamValidator::PARAM_TYPE => 'string', |
578 | ParamValidator::PARAM_SENSITIVE => true, |
579 | ], |
580 | 'continue' => [ |
581 | ApiBase::PARAM_HELP_MSG => 'api-help-param-continue', |
582 | ], |
583 | ]; |
584 | } |
585 | |
586 | protected function getExamplesMessages() { |
587 | return [ |
588 | 'action=query&list=watchlist' |
589 | => 'apihelp-query+watchlist-example-simple', |
590 | 'action=query&list=watchlist&wlprop=ids|title|timestamp|user|comment' |
591 | => 'apihelp-query+watchlist-example-props', |
592 | 'action=query&list=watchlist&wlprop=ids|title|timestamp|user|comment|expiry' |
593 | => 'apihelp-query+watchlist-example-expiry', |
594 | 'action=query&list=watchlist&wlallrev=&wlprop=ids|title|timestamp|user|comment' |
595 | => 'apihelp-query+watchlist-example-allrev', |
596 | 'action=query&generator=watchlist&prop=info' |
597 | => 'apihelp-query+watchlist-example-generator', |
598 | 'action=query&generator=watchlist&gwlallrev=&prop=revisions&rvprop=timestamp|user' |
599 | => 'apihelp-query+watchlist-example-generator-rev', |
600 | 'action=query&list=watchlist&wlowner=Example&wltoken=123ABC' |
601 | => 'apihelp-query+watchlist-example-wlowner', |
602 | ]; |
603 | } |
604 | |
605 | public function getHelpUrls() { |
606 | return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Watchlist'; |
607 | } |
608 | } |