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