Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 369 |
|
0.00% |
0 / 6 |
CRAP | |
0.00% |
0 / 1 |
ApiQueryDeletedrevs | |
0.00% |
0 / 368 |
|
0.00% |
0 / 6 |
7656 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
2 | |||
execute | |
0.00% |
0 / 254 |
|
0.00% |
0 / 1 |
6480 | |||
isDeprecated | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getAllowedParams | |
0.00% |
0 / 86 |
|
0.00% |
0 / 1 |
6 | |||
getExamplesMessages | |
0.00% |
0 / 19 |
|
0.00% |
0 / 1 |
6 | |||
getHelpUrls | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | /** |
3 | * Copyright © 2007 Roan Kattouw <roan.kattouw@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 MediaWiki\Cache\LinkBatchFactory; |
26 | use MediaWiki\ChangeTags\ChangeTagsStore; |
27 | use MediaWiki\CommentFormatter\RowCommentFormatter; |
28 | use MediaWiki\CommentStore\CommentStore; |
29 | use MediaWiki\ParamValidator\TypeDef\UserDef; |
30 | use MediaWiki\Revision\RevisionRecord; |
31 | use MediaWiki\Revision\RevisionStore; |
32 | use MediaWiki\Revision\SlotRecord; |
33 | use MediaWiki\Storage\NameTableAccessException; |
34 | use MediaWiki\Storage\NameTableStore; |
35 | use MediaWiki\Title\Title; |
36 | use Wikimedia\ParamValidator\ParamValidator; |
37 | use Wikimedia\ParamValidator\TypeDef\EnumDef; |
38 | use Wikimedia\ParamValidator\TypeDef\IntegerDef; |
39 | use Wikimedia\Rdbms\IExpression; |
40 | use Wikimedia\Rdbms\LikeValue; |
41 | |
42 | /** |
43 | * Query module to enumerate all deleted revisions. |
44 | * |
45 | * @ingroup API |
46 | * @deprecated since 1.25 |
47 | */ |
48 | class ApiQueryDeletedrevs extends ApiQueryBase { |
49 | |
50 | private CommentStore $commentStore; |
51 | private RowCommentFormatter $commentFormatter; |
52 | private RevisionStore $revisionStore; |
53 | private NameTableStore $changeTagDefStore; |
54 | private ChangeTagsStore $changeTagsStore; |
55 | private LinkBatchFactory $linkBatchFactory; |
56 | |
57 | public function __construct( |
58 | ApiQuery $query, |
59 | string $moduleName, |
60 | CommentStore $commentStore, |
61 | RowCommentFormatter $commentFormatter, |
62 | RevisionStore $revisionStore, |
63 | NameTableStore $changeTagDefStore, |
64 | ChangeTagsStore $changeTagsStore, |
65 | LinkBatchFactory $linkBatchFactory |
66 | ) { |
67 | parent::__construct( $query, $moduleName, 'dr' ); |
68 | $this->commentStore = $commentStore; |
69 | $this->commentFormatter = $commentFormatter; |
70 | $this->revisionStore = $revisionStore; |
71 | $this->changeTagDefStore = $changeTagDefStore; |
72 | $this->changeTagsStore = $changeTagsStore; |
73 | $this->linkBatchFactory = $linkBatchFactory; |
74 | } |
75 | |
76 | public function execute() { |
77 | // Before doing anything at all, let's check permissions |
78 | $this->checkUserRightsAny( 'deletedhistory' ); |
79 | |
80 | $this->addDeprecation( 'apiwarn-deprecation-deletedrevs', 'action=query&list=deletedrevs' ); |
81 | |
82 | $user = $this->getUser(); |
83 | $db = $this->getDB(); |
84 | $params = $this->extractRequestParams( false ); |
85 | $prop = array_fill_keys( $params['prop'], true ); |
86 | $fld_parentid = isset( $prop['parentid'] ); |
87 | $fld_revid = isset( $prop['revid'] ); |
88 | $fld_user = isset( $prop['user'] ); |
89 | $fld_userid = isset( $prop['userid'] ); |
90 | $fld_comment = isset( $prop['comment'] ); |
91 | $fld_parsedcomment = isset( $prop['parsedcomment'] ); |
92 | $fld_minor = isset( $prop['minor'] ); |
93 | $fld_len = isset( $prop['len'] ); |
94 | $fld_sha1 = isset( $prop['sha1'] ); |
95 | $fld_content = isset( $prop['content'] ); |
96 | $fld_token = isset( $prop['token'] ); |
97 | $fld_tags = isset( $prop['tags'] ); |
98 | |
99 | // If we're in a mode that breaks the same-origin policy, no tokens can |
100 | // be obtained |
101 | if ( $this->lacksSameOriginSecurity() || |
102 | // If user can't undelete, no tokens |
103 | !$this->getAuthority()->isAllowed( 'undelete' ) |
104 | ) { |
105 | $fld_token = false; |
106 | } |
107 | |
108 | $result = $this->getResult(); |
109 | $pageSet = $this->getPageSet(); |
110 | $titles = $pageSet->getPages(); |
111 | |
112 | // This module operates in three modes: |
113 | // 'revs': List deleted revs for certain titles (1) |
114 | // 'user': List deleted revs by a certain user (2) |
115 | // 'all': List all deleted revs in NS (3) |
116 | $mode = 'all'; |
117 | if ( count( $titles ) > 0 ) { |
118 | $mode = 'revs'; |
119 | } elseif ( $params['user'] !== null ) { |
120 | $mode = 'user'; |
121 | } |
122 | |
123 | if ( $mode == 'revs' || $mode == 'user' ) { |
124 | // Ignore namespace and unique due to inability to know whether they were purposely set |
125 | foreach ( [ 'from', 'to', 'prefix', /*'namespace', 'unique'*/ ] as $p ) { |
126 | if ( $params[$p] !== null ) { |
127 | $this->dieWithError( [ 'apierror-deletedrevs-param-not-1-2', $p ], 'badparams' ); |
128 | } |
129 | } |
130 | } else { |
131 | foreach ( [ 'start', 'end' ] as $p ) { |
132 | if ( $params[$p] !== null ) { |
133 | $this->dieWithError( [ 'apierror-deletedrevs-param-not-3', $p ], 'badparams' ); |
134 | } |
135 | } |
136 | } |
137 | |
138 | if ( $params['user'] !== null && $params['excludeuser'] !== null ) { |
139 | $this->dieWithError( 'user and excludeuser cannot be used together', 'badparams' ); |
140 | } |
141 | |
142 | $arQuery = $this->revisionStore->getArchiveQueryInfo(); |
143 | $this->addTables( $arQuery['tables'] ); |
144 | $this->addFields( $arQuery['fields'] ); |
145 | $this->addJoinConds( $arQuery['joins'] ); |
146 | $this->addFields( [ 'ar_title', 'ar_namespace' ] ); |
147 | |
148 | if ( $fld_tags ) { |
149 | $this->addFields( [ |
150 | 'ts_tags' => $this->changeTagsStore->makeTagSummarySubquery( 'archive' ) |
151 | ] ); |
152 | } |
153 | |
154 | if ( $params['tag'] !== null ) { |
155 | $this->addTables( 'change_tag' ); |
156 | $this->addJoinConds( |
157 | [ 'change_tag' => [ 'JOIN', [ 'ar_rev_id=ct_rev_id' ] ] ] |
158 | ); |
159 | try { |
160 | $this->addWhereFld( 'ct_tag_id', $this->changeTagDefStore->getId( $params['tag'] ) ); |
161 | } catch ( NameTableAccessException ) { |
162 | // Return nothing. |
163 | $this->addWhere( '1=0' ); |
164 | } |
165 | } |
166 | |
167 | // This means stricter restrictions |
168 | if ( $fld_content ) { |
169 | $this->checkUserRightsAny( [ 'deletedtext', 'undelete' ] ); |
170 | } |
171 | // Check limits |
172 | $userMax = $fld_content ? ApiBase::LIMIT_SML1 : ApiBase::LIMIT_BIG1; |
173 | $botMax = $fld_content ? ApiBase::LIMIT_SML2 : ApiBase::LIMIT_BIG2; |
174 | |
175 | $limit = $params['limit']; |
176 | |
177 | if ( $limit == 'max' ) { |
178 | $limit = $this->getMain()->canApiHighLimits() ? $botMax : $userMax; |
179 | $this->getResult()->addParsedLimit( $this->getModuleName(), $limit ); |
180 | } |
181 | |
182 | $limit = $this->getMain()->getParamValidator()->validateValue( |
183 | $this, 'limit', $limit, [ |
184 | ParamValidator::PARAM_TYPE => 'limit', |
185 | IntegerDef::PARAM_MIN => 1, |
186 | IntegerDef::PARAM_MAX => $userMax, |
187 | IntegerDef::PARAM_MAX2 => $botMax, |
188 | IntegerDef::PARAM_IGNORE_RANGE => true, |
189 | ] |
190 | ); |
191 | |
192 | if ( $fld_token ) { |
193 | // Undelete tokens are identical for all pages, so we cache one here |
194 | $token = $user->getEditToken( '', $this->getMain()->getRequest() ); |
195 | } |
196 | |
197 | $dir = $params['dir']; |
198 | |
199 | // We need a custom WHERE clause that matches all titles. |
200 | if ( $mode == 'revs' ) { |
201 | $lb = $this->linkBatchFactory->newLinkBatch( $titles ); |
202 | $where = $lb->constructSet( 'ar', $db ); |
203 | $this->addWhere( $where ); |
204 | } elseif ( $mode == 'all' ) { |
205 | $this->addWhereFld( 'ar_namespace', $params['namespace'] ); |
206 | |
207 | $from = $params['from'] === null |
208 | ? null |
209 | : $this->titlePartToKey( $params['from'], $params['namespace'] ); |
210 | $to = $params['to'] === null |
211 | ? null |
212 | : $this->titlePartToKey( $params['to'], $params['namespace'] ); |
213 | $this->addWhereRange( 'ar_title', $dir, $from, $to ); |
214 | |
215 | if ( isset( $params['prefix'] ) ) { |
216 | $this->addWhere( |
217 | $db->expr( |
218 | 'ar_title', |
219 | IExpression::LIKE, |
220 | new LikeValue( |
221 | $this->titlePartToKey( $params['prefix'], $params['namespace'] ), |
222 | $db->anyString() |
223 | ) |
224 | ) |
225 | ); |
226 | } |
227 | } |
228 | |
229 | if ( $params['user'] !== null ) { |
230 | // We already join on actor due to getArchiveQueryInfo() |
231 | $this->addWhereFld( 'actor_name', $params['user'] ); |
232 | } elseif ( $params['excludeuser'] !== null ) { |
233 | $this->addWhere( $db->expr( 'actor_name', '!=', $params['excludeuser'] ) ); |
234 | } |
235 | |
236 | if ( $params['user'] !== null || $params['excludeuser'] !== null ) { |
237 | // Paranoia: avoid brute force searches (T19342) |
238 | // (shouldn't be able to get here without 'deletedhistory', but |
239 | // check it again just in case) |
240 | if ( !$this->getAuthority()->isAllowed( 'deletedhistory' ) ) { |
241 | $bitmask = RevisionRecord::DELETED_USER; |
242 | } elseif ( !$this->getAuthority()->isAllowedAny( 'suppressrevision', 'viewsuppressed' ) ) { |
243 | $bitmask = RevisionRecord::DELETED_USER | RevisionRecord::DELETED_RESTRICTED; |
244 | } else { |
245 | $bitmask = 0; |
246 | } |
247 | if ( $bitmask ) { |
248 | $this->addWhere( $db->bitAnd( 'ar_deleted', $bitmask ) . " != $bitmask" ); |
249 | } |
250 | } |
251 | |
252 | if ( $params['continue'] !== null ) { |
253 | $op = ( $dir == 'newer' ? '>=' : '<=' ); |
254 | if ( $mode == 'all' || $mode == 'revs' ) { |
255 | $cont = $this->parseContinueParamOrDie( $params['continue'], [ 'int', 'string', 'timestamp', 'int' ] ); |
256 | $this->addWhere( $db->buildComparison( $op, [ |
257 | 'ar_namespace' => $cont[0], |
258 | 'ar_title' => $cont[1], |
259 | 'ar_timestamp' => $db->timestamp( $cont[2] ), |
260 | 'ar_id' => $cont[3], |
261 | ] ) ); |
262 | } else { |
263 | $cont = $this->parseContinueParamOrDie( $params['continue'], [ 'timestamp', 'int' ] ); |
264 | $this->addWhere( $db->buildComparison( $op, [ |
265 | 'ar_timestamp' => $db->timestamp( $cont[0] ), |
266 | 'ar_id' => $cont[1], |
267 | ] ) ); |
268 | } |
269 | } |
270 | |
271 | $this->addOption( 'LIMIT', $limit + 1 ); |
272 | if ( $mode == 'all' ) { |
273 | if ( $params['unique'] ) { |
274 | // @todo Does this work on non-MySQL? |
275 | $this->addOption( 'GROUP BY', 'ar_title' ); |
276 | } else { |
277 | $sort = ( $dir == 'newer' ? '' : ' DESC' ); |
278 | $this->addOption( 'ORDER BY', [ |
279 | 'ar_title' . $sort, |
280 | 'ar_timestamp' . $sort, |
281 | 'ar_id' . $sort, |
282 | ] ); |
283 | } |
284 | } else { |
285 | if ( $mode == 'revs' ) { |
286 | // Sort by ns and title in the same order as timestamp for efficiency |
287 | $this->addWhereRange( 'ar_namespace', $dir, null, null ); |
288 | $this->addWhereRange( 'ar_title', $dir, null, null ); |
289 | } |
290 | $this->addTimestampWhereRange( 'ar_timestamp', $dir, $params['start'], $params['end'] ); |
291 | // Include in ORDER BY for uniqueness |
292 | $this->addWhereRange( 'ar_id', $dir, null, null ); |
293 | } |
294 | $res = $this->select( __METHOD__ ); |
295 | |
296 | $formattedComments = []; |
297 | if ( $fld_parsedcomment ) { |
298 | $formattedComments = $this->commentFormatter->formatItems( |
299 | $this->commentFormatter->rows( $res ) |
300 | ->indexField( 'ar_id' ) |
301 | ->commentKey( 'ar_comment' ) |
302 | ->namespaceField( 'ar_namespace' ) |
303 | ->titleField( 'ar_title' ) |
304 | ); |
305 | } |
306 | |
307 | $pageMap = []; // Maps ns&title to (fake) pageid |
308 | $count = 0; |
309 | $newPageID = 0; |
310 | foreach ( $res as $row ) { |
311 | if ( ++$count > $limit ) { |
312 | // We've had enough |
313 | if ( $mode == 'all' || $mode == 'revs' ) { |
314 | $this->setContinueEnumParameter( 'continue', |
315 | "$row->ar_namespace|$row->ar_title|$row->ar_timestamp|$row->ar_id" |
316 | ); |
317 | } else { |
318 | $this->setContinueEnumParameter( 'continue', "$row->ar_timestamp|$row->ar_id" ); |
319 | } |
320 | break; |
321 | } |
322 | |
323 | $rev = []; |
324 | $anyHidden = false; |
325 | |
326 | $rev['timestamp'] = wfTimestamp( TS_ISO_8601, $row->ar_timestamp ); |
327 | if ( $fld_revid ) { |
328 | $rev['revid'] = (int)$row->ar_rev_id; |
329 | } |
330 | if ( $fld_parentid && $row->ar_parent_id !== null ) { |
331 | $rev['parentid'] = (int)$row->ar_parent_id; |
332 | } |
333 | if ( $fld_user || $fld_userid ) { |
334 | if ( $row->ar_deleted & RevisionRecord::DELETED_USER ) { |
335 | $rev['userhidden'] = true; |
336 | $anyHidden = true; |
337 | } |
338 | if ( RevisionRecord::userCanBitfield( |
339 | $row->ar_deleted, |
340 | RevisionRecord::DELETED_USER, |
341 | $user |
342 | ) ) { |
343 | if ( $fld_user ) { |
344 | $rev['user'] = $row->ar_user_text; |
345 | } |
346 | if ( $fld_userid ) { |
347 | $rev['userid'] = (int)$row->ar_user; |
348 | } |
349 | } |
350 | } |
351 | |
352 | if ( $fld_comment || $fld_parsedcomment ) { |
353 | if ( $row->ar_deleted & RevisionRecord::DELETED_COMMENT ) { |
354 | $rev['commenthidden'] = true; |
355 | $anyHidden = true; |
356 | } |
357 | if ( RevisionRecord::userCanBitfield( |
358 | $row->ar_deleted, |
359 | RevisionRecord::DELETED_COMMENT, |
360 | $user |
361 | ) ) { |
362 | $comment = $this->commentStore->getComment( 'ar_comment', $row )->text; |
363 | if ( $fld_comment ) { |
364 | $rev['comment'] = $comment; |
365 | } |
366 | if ( $fld_parsedcomment ) { |
367 | $rev['parsedcomment'] = $formattedComments[$row->ar_id]; |
368 | } |
369 | } |
370 | } |
371 | |
372 | if ( $fld_minor ) { |
373 | $rev['minor'] = $row->ar_minor_edit == 1; |
374 | } |
375 | if ( $fld_len ) { |
376 | $rev['len'] = $row->ar_len; |
377 | } |
378 | if ( $fld_sha1 ) { |
379 | if ( $row->ar_deleted & RevisionRecord::DELETED_TEXT ) { |
380 | $rev['sha1hidden'] = true; |
381 | $anyHidden = true; |
382 | } |
383 | if ( RevisionRecord::userCanBitfield( |
384 | $row->ar_deleted, |
385 | RevisionRecord::DELETED_TEXT, |
386 | $user |
387 | ) ) { |
388 | if ( $row->ar_sha1 != '' ) { |
389 | $rev['sha1'] = \Wikimedia\base_convert( $row->ar_sha1, 36, 16, 40 ); |
390 | } else { |
391 | $rev['sha1'] = ''; |
392 | } |
393 | } |
394 | } |
395 | if ( $fld_content ) { |
396 | if ( $row->ar_deleted & RevisionRecord::DELETED_TEXT ) { |
397 | $rev['texthidden'] = true; |
398 | $anyHidden = true; |
399 | } |
400 | if ( RevisionRecord::userCanBitfield( |
401 | $row->ar_deleted, |
402 | RevisionRecord::DELETED_TEXT, |
403 | $user |
404 | ) ) { |
405 | ApiResult::setContentValue( $rev, 'text', |
406 | $this->revisionStore->newRevisionFromArchiveRow( $row ) |
407 | ->getContent( SlotRecord::MAIN )->serialize() ); |
408 | } |
409 | } |
410 | |
411 | if ( $fld_tags ) { |
412 | if ( $row->ts_tags ) { |
413 | $tags = explode( ',', $row->ts_tags ); |
414 | ApiResult::setIndexedTagName( $tags, 'tag' ); |
415 | $rev['tags'] = $tags; |
416 | } else { |
417 | $rev['tags'] = []; |
418 | } |
419 | } |
420 | |
421 | if ( $anyHidden && ( $row->ar_deleted & RevisionRecord::DELETED_RESTRICTED ) ) { |
422 | $rev['suppressed'] = true; |
423 | } |
424 | |
425 | if ( !isset( $pageMap[$row->ar_namespace][$row->ar_title] ) ) { |
426 | $pageID = $newPageID++; |
427 | $pageMap[$row->ar_namespace][$row->ar_title] = $pageID; |
428 | $a = [ 'revisions' => [ $rev ] ]; |
429 | ApiResult::setIndexedTagName( $a['revisions'], 'rev' ); |
430 | $title = Title::makeTitle( $row->ar_namespace, $row->ar_title ); |
431 | ApiQueryBase::addTitleInfo( $a, $title ); |
432 | if ( $fld_token ) { |
433 | // @phan-suppress-next-line PhanPossiblyUndeclaredVariable token is set when used |
434 | $a['token'] = $token; |
435 | } |
436 | $fit = $result->addValue( [ 'query', $this->getModuleName() ], $pageID, $a ); |
437 | } else { |
438 | $pageID = $pageMap[$row->ar_namespace][$row->ar_title]; |
439 | $fit = $result->addValue( |
440 | [ 'query', $this->getModuleName(), $pageID, 'revisions' ], |
441 | null, $rev ); |
442 | } |
443 | if ( !$fit ) { |
444 | if ( $mode == 'all' || $mode == 'revs' ) { |
445 | $this->setContinueEnumParameter( 'continue', |
446 | "$row->ar_namespace|$row->ar_title|$row->ar_timestamp|$row->ar_id" |
447 | ); |
448 | } else { |
449 | $this->setContinueEnumParameter( 'continue', "$row->ar_timestamp|$row->ar_id" ); |
450 | } |
451 | break; |
452 | } |
453 | } |
454 | $result->addIndexedTagName( [ 'query', $this->getModuleName() ], 'page' ); |
455 | } |
456 | |
457 | public function isDeprecated() { |
458 | return true; |
459 | } |
460 | |
461 | public function getAllowedParams() { |
462 | $smallLimit = $this->getMain()->canApiHighLimits() ? ApiBase::LIMIT_SML2 : ApiBase::LIMIT_SML1; |
463 | return [ |
464 | 'start' => [ |
465 | ParamValidator::PARAM_TYPE => 'timestamp', |
466 | ApiBase::PARAM_HELP_MSG_INFO => [ [ 'modes', 1, 2 ] ], |
467 | ], |
468 | 'end' => [ |
469 | ParamValidator::PARAM_TYPE => 'timestamp', |
470 | ApiBase::PARAM_HELP_MSG_INFO => [ [ 'modes', 1, 2 ] ], |
471 | ], |
472 | 'dir' => [ |
473 | ParamValidator::PARAM_TYPE => [ |
474 | 'newer', |
475 | 'older' |
476 | ], |
477 | ParamValidator::PARAM_DEFAULT => 'older', |
478 | ApiBase::PARAM_HELP_MSG => 'api-help-param-direction', |
479 | ApiBase::PARAM_HELP_MSG_PER_VALUE => [ |
480 | 'newer' => 'api-help-paramvalue-direction-newer', |
481 | 'older' => 'api-help-paramvalue-direction-older', |
482 | ], |
483 | ApiBase::PARAM_HELP_MSG_INFO => [ [ 'modes', 1, 3 ] ], |
484 | ], |
485 | 'from' => [ |
486 | ApiBase::PARAM_HELP_MSG_INFO => [ [ 'modes', 3 ] ], |
487 | ], |
488 | 'to' => [ |
489 | ApiBase::PARAM_HELP_MSG_INFO => [ [ 'modes', 3 ] ], |
490 | ], |
491 | 'prefix' => [ |
492 | ApiBase::PARAM_HELP_MSG_INFO => [ [ 'modes', 3 ] ], |
493 | ], |
494 | 'unique' => [ |
495 | ParamValidator::PARAM_DEFAULT => false, |
496 | ApiBase::PARAM_HELP_MSG_INFO => [ [ 'modes', 3 ] ], |
497 | ], |
498 | 'namespace' => [ |
499 | ParamValidator::PARAM_TYPE => 'namespace', |
500 | ParamValidator::PARAM_DEFAULT => NS_MAIN, |
501 | ApiBase::PARAM_HELP_MSG_INFO => [ [ 'modes', 3 ] ], |
502 | ], |
503 | 'tag' => null, |
504 | 'user' => [ |
505 | ParamValidator::PARAM_TYPE => 'user', |
506 | UserDef::PARAM_ALLOWED_USER_TYPES => [ 'name', 'ip', 'temp', 'id', 'interwiki' ], |
507 | ], |
508 | 'excludeuser' => [ |
509 | ParamValidator::PARAM_TYPE => 'user', |
510 | UserDef::PARAM_ALLOWED_USER_TYPES => [ 'name', 'ip', 'temp', 'id', 'interwiki' ], |
511 | ], |
512 | 'prop' => [ |
513 | ParamValidator::PARAM_DEFAULT => 'user|comment', |
514 | ParamValidator::PARAM_TYPE => [ |
515 | 'revid', |
516 | 'parentid', |
517 | 'user', |
518 | 'userid', |
519 | 'comment', |
520 | 'parsedcomment', |
521 | 'minor', |
522 | 'len', |
523 | 'sha1', |
524 | 'content', |
525 | 'token', |
526 | 'tags' |
527 | ], |
528 | ParamValidator::PARAM_ISMULTI => true, |
529 | ApiBase::PARAM_HELP_MSG_PER_VALUE => [ |
530 | 'content' => [ 'apihelp-query+deletedrevs-paramvalue-prop-content', $smallLimit ], |
531 | ], |
532 | EnumDef::PARAM_DEPRECATED_VALUES => [ |
533 | 'token' => true, |
534 | ], |
535 | ], |
536 | 'limit' => [ |
537 | ParamValidator::PARAM_DEFAULT => 10, |
538 | ParamValidator::PARAM_TYPE => 'limit', |
539 | IntegerDef::PARAM_MIN => 1, |
540 | IntegerDef::PARAM_MAX => ApiBase::LIMIT_BIG1, |
541 | IntegerDef::PARAM_MAX2 => ApiBase::LIMIT_BIG2, |
542 | ApiBase::PARAM_HELP_MSG => [ 'apihelp-query+deletedrevs-param-limit', $smallLimit ], |
543 | ], |
544 | 'continue' => [ |
545 | ApiBase::PARAM_HELP_MSG => 'api-help-param-continue', |
546 | ], |
547 | ]; |
548 | } |
549 | |
550 | protected function getExamplesMessages() { |
551 | $title = Title::newMainPage(); |
552 | $talkTitle = $title->getTalkPageIfDefined(); |
553 | $examples = []; |
554 | |
555 | if ( $talkTitle ) { |
556 | $title = rawurlencode( $title->getPrefixedText() ); |
557 | $talkTitle = rawurlencode( $talkTitle->getPrefixedText() ); |
558 | $examples = [ |
559 | "action=query&list=deletedrevs&titles={$title}|{$talkTitle}&" . |
560 | 'drprop=user|comment|content' |
561 | => 'apihelp-query+deletedrevs-example-mode1', |
562 | ]; |
563 | } |
564 | |
565 | return array_merge( $examples, [ |
566 | 'action=query&list=deletedrevs&druser=Bob&drlimit=50' |
567 | => 'apihelp-query+deletedrevs-example-mode2', |
568 | 'action=query&list=deletedrevs&drdir=newer&drlimit=50' |
569 | => 'apihelp-query+deletedrevs-example-mode3-main', |
570 | 'action=query&list=deletedrevs&drdir=newer&drlimit=50&drnamespace=1&drunique=' |
571 | => 'apihelp-query+deletedrevs-example-mode3-talk', |
572 | ] ); |
573 | } |
574 | |
575 | public function getHelpUrls() { |
576 | return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Deletedrevs'; |
577 | } |
578 | } |
579 | |
580 | /** @deprecated class alias since 1.43 */ |
581 | class_alias( ApiQueryDeletedrevs::class, 'ApiQueryDeletedrevs' ); |