Remove Revision::getRevisionText from ApiQueryDeletedrevs
[lhc/web/wiklou.git] / includes / api / ApiQueryRevisionsBase.php
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\Logger\LoggerFactory;
24 use MediaWiki\Revision\RevisionAccessException;
25 use MediaWiki\Revision\RevisionRecord;
26 use MediaWiki\Revision\SlotRecord;
27 use MediaWiki\MediaWikiServices;
28
29 /**
30 * A base class for functions common to producing a list of revisions.
31 *
32 * @ingroup API
33 */
34 abstract class ApiQueryRevisionsBase extends ApiQueryGeneratorBase {
35
36 /**
37 * @name Constants for internal use. Don't use externally.
38 * @{
39 */
40
41 // Bits to indicate the results of the revdel permission check on a revision,
42 // see self::checkRevDel()
43 const IS_DELETED = 1; // Whether the field is revision-deleted
44 const CANNOT_VIEW = 2; // Whether the user cannot view the field due to revdel
45
46 /** @} */
47
48 protected $limit, $diffto, $difftotext, $difftotextpst, $expandTemplates, $generateXML,
49 $section, $parseContent, $fetchContent, $contentFormat, $setParsedLimit = true,
50 $slotRoles = null, $needSlots;
51
52 protected $fld_ids = false, $fld_flags = false, $fld_timestamp = false,
53 $fld_size = false, $fld_slotsize = false, $fld_sha1 = false, $fld_slotsha1 = false,
54 $fld_comment = false, $fld_parsedcomment = false, $fld_user = false, $fld_userid = false,
55 $fld_content = false, $fld_tags = false, $fld_contentmodel = false, $fld_roles = false,
56 $fld_parsetree = false;
57
58 public function execute() {
59 $this->run();
60 }
61
62 public function executeGenerator( $resultPageSet ) {
63 $this->run( $resultPageSet );
64 }
65
66 /**
67 * @param ApiPageSet|null $resultPageSet
68 * @return void
69 */
70 abstract protected function run( ApiPageSet $resultPageSet = null );
71
72 /**
73 * Parse the parameters into the various instance fields.
74 *
75 * @param array $params
76 */
77 protected function parseParameters( $params ) {
78 $prop = array_flip( $params['prop'] );
79
80 $this->fld_ids = isset( $prop['ids'] );
81 $this->fld_flags = isset( $prop['flags'] );
82 $this->fld_timestamp = isset( $prop['timestamp'] );
83 $this->fld_comment = isset( $prop['comment'] );
84 $this->fld_parsedcomment = isset( $prop['parsedcomment'] );
85 $this->fld_size = isset( $prop['size'] );
86 $this->fld_slotsize = isset( $prop['slotsize'] );
87 $this->fld_sha1 = isset( $prop['sha1'] );
88 $this->fld_slotsha1 = isset( $prop['slotsha1'] );
89 $this->fld_content = isset( $prop['content'] );
90 $this->fld_contentmodel = isset( $prop['contentmodel'] );
91 $this->fld_userid = isset( $prop['userid'] );
92 $this->fld_user = isset( $prop['user'] );
93 $this->fld_tags = isset( $prop['tags'] );
94 $this->fld_roles = isset( $prop['roles'] );
95 $this->fld_parsetree = isset( $prop['parsetree'] );
96
97 $this->slotRoles = $params['slots'];
98
99 if ( $this->slotRoles !== null ) {
100 if ( $this->fld_parsetree ) {
101 $this->dieWithError( [
102 'apierror-invalidparammix-cannotusewith',
103 $this->encodeParamName( 'prop=parsetree' ),
104 $this->encodeParamName( 'slots' ),
105 ], 'invalidparammix' );
106 }
107 foreach ( [
108 'expandtemplates', 'generatexml', 'parse', 'diffto', 'difftotext', 'difftotextpst',
109 'contentformat'
110 ] as $p ) {
111 if ( $params[$p] !== null && $params[$p] !== false ) {
112 $this->dieWithError( [
113 'apierror-invalidparammix-cannotusewith',
114 $this->encodeParamName( $p ),
115 $this->encodeParamName( 'slots' ),
116 ], 'invalidparammix' );
117 }
118 }
119 }
120
121 if ( !empty( $params['contentformat'] ) ) {
122 $this->contentFormat = $params['contentformat'];
123 }
124
125 $this->limit = $params['limit'];
126
127 if ( !is_null( $params['difftotext'] ) ) {
128 $this->difftotext = $params['difftotext'];
129 $this->difftotextpst = $params['difftotextpst'];
130 } elseif ( !is_null( $params['diffto'] ) ) {
131 if ( $params['diffto'] == 'cur' ) {
132 $params['diffto'] = 0;
133 }
134 if ( ( !ctype_digit( $params['diffto'] ) || $params['diffto'] < 0 )
135 && $params['diffto'] != 'prev' && $params['diffto'] != 'next'
136 ) {
137 $p = $this->getModulePrefix();
138 $this->dieWithError( [ 'apierror-baddiffto', $p ], 'diffto' );
139 }
140 // Check whether the revision exists and is readable,
141 // DifferenceEngine returns a rather ambiguous empty
142 // string if that's not the case
143 if ( $params['diffto'] != 0 ) {
144 $difftoRev = MediaWikiServices::getInstance()->getRevisionStore()
145 ->getRevisionById( $params['diffto'] );
146 if ( !$difftoRev ) {
147 $this->dieWithError( [ 'apierror-nosuchrevid', $params['diffto'] ] );
148 }
149 $revDel = $this->checkRevDel( $difftoRev, RevisionRecord::DELETED_TEXT );
150 if ( $revDel & self::CANNOT_VIEW ) {
151 $this->addWarning( [ 'apiwarn-difftohidden', $difftoRev->getId() ] );
152 $params['diffto'] = null;
153 }
154 }
155 $this->diffto = $params['diffto'];
156 }
157
158 $this->fetchContent = $this->fld_content || !is_null( $this->diffto )
159 || !is_null( $this->difftotext ) || $this->fld_parsetree;
160
161 $smallLimit = false;
162 if ( $this->fetchContent ) {
163 $smallLimit = true;
164 $this->expandTemplates = $params['expandtemplates'];
165 $this->generateXML = $params['generatexml'];
166 $this->parseContent = $params['parse'];
167 if ( $this->parseContent ) {
168 // Must manually initialize unset limit
169 if ( is_null( $this->limit ) ) {
170 $this->limit = 1;
171 }
172 }
173 $this->section = $params['section'] ?? false;
174 }
175
176 $userMax = $this->parseContent ? 1 : ( $smallLimit ? ApiBase::LIMIT_SML1 : ApiBase::LIMIT_BIG1 );
177 $botMax = $this->parseContent ? 1 : ( $smallLimit ? ApiBase::LIMIT_SML2 : ApiBase::LIMIT_BIG2 );
178 if ( $this->limit == 'max' ) {
179 $this->limit = $this->getMain()->canApiHighLimits() ? $botMax : $userMax;
180 if ( $this->setParsedLimit ) {
181 $this->getResult()->addParsedLimit( $this->getModuleName(), $this->limit );
182 }
183 }
184
185 if ( is_null( $this->limit ) ) {
186 $this->limit = 10;
187 }
188 $this->validateLimit( 'limit', $this->limit, 1, $userMax, $botMax );
189
190 $this->needSlots = $this->fetchContent || $this->fld_contentmodel ||
191 $this->fld_slotsize || $this->fld_slotsha1;
192 if ( $this->needSlots && $this->slotRoles === null ) {
193 $encParam = $this->encodeParamName( 'slots' );
194 $name = $this->getModuleName();
195 $parent = $this->getParent();
196 $parentParam = $parent->encodeParamName( $parent->getModuleManager()->getModuleGroup( $name ) );
197 $this->addDeprecation(
198 [ 'apiwarn-deprecation-missingparam', $encParam ],
199 "action=query&{$parentParam}={$name}&!{$encParam}"
200 );
201 }
202 }
203
204 /**
205 * Test revision deletion status
206 * @param RevisionRecord $revision Revision to check
207 * @param int $field One of the RevisionRecord::DELETED_* constants
208 * @return int Revision deletion status flags. Bitwise OR of
209 * self::IS_DELETED and self::CANNOT_VIEW, as appropriate.
210 */
211 private function checkRevDel( RevisionRecord $revision, $field ) {
212 $ret = $revision->isDeleted( $field ) ? self::IS_DELETED : 0;
213 if ( $ret ) {
214 $canSee = $revision->audienceCan( $field, RevisionRecord::FOR_THIS_USER, $this->getUser() );
215 $ret = $ret | ( $canSee ? 0 : self::CANNOT_VIEW );
216 }
217 return $ret;
218 }
219
220 /**
221 * Extract information from the RevisionRecord
222 *
223 * @since 1.32, takes a RevisionRecord instead of a Revision
224 * @param RevisionRecord $revision Revision
225 * @param object $row Should have a field 'ts_tags' if $this->fld_tags is set
226 * @return array
227 */
228 protected function extractRevisionInfo( RevisionRecord $revision, $row ) {
229 $vals = [];
230 $anyHidden = false;
231
232 if ( $this->fld_ids ) {
233 $vals['revid'] = (int)$revision->getId();
234 if ( !is_null( $revision->getParentId() ) ) {
235 $vals['parentid'] = (int)$revision->getParentId();
236 }
237 }
238
239 if ( $this->fld_flags ) {
240 $vals['minor'] = $revision->isMinor();
241 }
242
243 if ( $this->fld_user || $this->fld_userid ) {
244 $revDel = $this->checkRevDel( $revision, RevisionRecord::DELETED_USER );
245 if ( ( $revDel & self::IS_DELETED ) ) {
246 $vals['userhidden'] = true;
247 $anyHidden = true;
248 }
249 if ( !( $revDel & self::CANNOT_VIEW ) ) {
250 $u = $revision->getUser( RevisionRecord::RAW );
251 if ( $this->fld_user ) {
252 $vals['user'] = $u->getName();
253 }
254 $userid = $u->getId();
255 if ( !$userid ) {
256 $vals['anon'] = true;
257 }
258
259 if ( $this->fld_userid ) {
260 $vals['userid'] = $userid;
261 }
262 }
263 }
264
265 if ( $this->fld_timestamp ) {
266 $vals['timestamp'] = wfTimestamp( TS_ISO_8601, $revision->getTimestamp() );
267 }
268
269 if ( $this->fld_size ) {
270 try {
271 $vals['size'] = (int)$revision->getSize();
272 } catch ( RevisionAccessException $e ) {
273 // Back compat: If there's no size, return 0.
274 // @todo: Gergő says to mention T198099 as a "todo" here.
275 $vals['size'] = 0;
276 }
277 }
278
279 if ( $this->fld_sha1 ) {
280 $revDel = $this->checkRevDel( $revision, RevisionRecord::DELETED_TEXT );
281 if ( ( $revDel & self::IS_DELETED ) ) {
282 $vals['sha1hidden'] = true;
283 $anyHidden = true;
284 }
285 if ( !( $revDel & self::CANNOT_VIEW ) ) {
286 try {
287 $vals['sha1'] = Wikimedia\base_convert( $revision->getSha1(), 36, 16, 40 );
288 } catch ( RevisionAccessException $e ) {
289 // Back compat: If there's no sha1, return emtpy string.
290 // @todo: Gergő says to mention T198099 as a "todo" here.
291 $vals['sha1'] = '';
292 }
293 }
294 }
295
296 try {
297 if ( $this->fld_roles ) {
298 $vals['roles'] = $revision->getSlotRoles();
299 }
300
301 if ( $this->needSlots ) {
302 $revDel = $this->checkRevDel( $revision, RevisionRecord::DELETED_TEXT );
303 if ( ( $this->fld_slotsha1 || $this->fetchContent ) && ( $revDel & self::IS_DELETED ) ) {
304 $anyHidden = true;
305 }
306 $vals = array_merge( $vals, $this->extractAllSlotInfo( $revision, $revDel ) );
307 }
308 } catch ( RevisionAccessException $ex ) {
309 // This is here so T212428 doesn't spam the log.
310 // TODO: find out why T212428 happens in the first place!
311 $vals['slotsmissing'] = true;
312
313 LoggerFactory::getInstance( 'api-warning' )->error(
314 'Failed to access revision slots',
315 [ 'revision' => $revision->getId(), 'exception' => $ex, ]
316 );
317 }
318
319 if ( $this->fld_comment || $this->fld_parsedcomment ) {
320 $revDel = $this->checkRevDel( $revision, RevisionRecord::DELETED_COMMENT );
321 if ( ( $revDel & self::IS_DELETED ) ) {
322 $vals['commenthidden'] = true;
323 $anyHidden = true;
324 }
325 if ( !( $revDel & self::CANNOT_VIEW ) ) {
326 $comment = $revision->getComment( RevisionRecord::RAW );
327 $comment = $comment ? $comment->text : '';
328
329 if ( $this->fld_comment ) {
330 $vals['comment'] = $comment;
331 }
332
333 if ( $this->fld_parsedcomment ) {
334 $vals['parsedcomment'] = Linker::formatComment(
335 $comment, Title::newFromLinkTarget( $revision->getPageAsLinkTarget() )
336 );
337 }
338 }
339 }
340
341 if ( $this->fld_tags ) {
342 if ( $row->ts_tags ) {
343 $tags = explode( ',', $row->ts_tags );
344 ApiResult::setIndexedTagName( $tags, 'tag' );
345 $vals['tags'] = $tags;
346 } else {
347 $vals['tags'] = [];
348 }
349 }
350
351 if ( $anyHidden && $revision->isDeleted( RevisionRecord::DELETED_RESTRICTED ) ) {
352 $vals['suppressed'] = true;
353 }
354
355 return $vals;
356 }
357
358 /**
359 * Extracts information about all relevant slots.
360 *
361 * @param RevisionRecord $revision
362 * @param int $revDel
363 *
364 * @return array
365 * @throws ApiUsageException
366 */
367 private function extractAllSlotInfo( RevisionRecord $revision, $revDel ): array {
368 $vals = [];
369
370 if ( $this->slotRoles === null ) {
371 try {
372 $slot = $revision->getSlot( SlotRecord::MAIN, RevisionRecord::RAW );
373 } catch ( RevisionAccessException $e ) {
374 // Back compat: If there's no slot, there's no content, so set 'textmissing'
375 // @todo: Gergő says to mention T198099 as a "todo" here.
376 $vals['textmissing'] = true;
377 $slot = null;
378 }
379
380 if ( $slot ) {
381 $content = null;
382 $vals += $this->extractSlotInfo( $slot, $revDel, $content );
383 if ( !empty( $vals['nosuchsection'] ) ) {
384 $this->dieWithError(
385 [
386 'apierror-nosuchsection-what',
387 wfEscapeWikiText( $this->section ),
388 $this->msg( 'revid', $revision->getId() )
389 ],
390 'nosuchsection'
391 );
392 }
393 if ( $content ) {
394 $vals += $this->extractDeprecatedContent( $content, $revision );
395 }
396 }
397 } else {
398 $roles = array_intersect( $this->slotRoles, $revision->getSlotRoles() );
399 $vals['slots'] = [
400 ApiResult::META_KVP_MERGE => true,
401 ];
402 foreach ( $roles as $role ) {
403 try {
404 $slot = $revision->getSlot( $role, RevisionRecord::RAW );
405 } catch ( RevisionAccessException $e ) {
406 // Don't error out here so the client can still process other slots/revisions.
407 // @todo: Gergő says to mention T198099 as a "todo" here.
408 $vals['slots'][$role]['missing'] = true;
409 continue;
410 }
411 $content = null;
412 $vals['slots'][$role] = $this->extractSlotInfo( $slot, $revDel, $content );
413 // @todo Move this into extractSlotInfo() (and remove its $content parameter)
414 // when extractDeprecatedContent() is no more.
415 if ( $content ) {
416 $vals['slots'][$role]['contentmodel'] = $content->getModel();
417 $vals['slots'][$role]['contentformat'] = $content->getDefaultFormat();
418 ApiResult::setContentValue(
419 $vals['slots'][$role],
420 'content',
421 $content->serialize()
422 );
423 }
424 }
425 ApiResult::setArrayType( $vals['slots'], 'kvp', 'role' );
426 ApiResult::setIndexedTagName( $vals['slots'], 'slot' );
427 }
428 return $vals;
429 }
430
431 /**
432 * Extract information from the SlotRecord
433 *
434 * @param SlotRecord $slot
435 * @param int $revDel Revdel status flags, from self::checkRevDel()
436 * @param Content|null &$content Set to the slot's content, if available
437 * and $this->fetchContent is true
438 * @return array
439 */
440 private function extractSlotInfo( SlotRecord $slot, $revDel, &$content = null ) {
441 $vals = [];
442 ApiResult::setArrayType( $vals, 'assoc' );
443
444 if ( $this->fld_slotsize ) {
445 $vals['size'] = (int)$slot->getSize();
446 }
447
448 if ( $this->fld_slotsha1 ) {
449 if ( ( $revDel & self::IS_DELETED ) ) {
450 $vals['sha1hidden'] = true;
451 }
452 if ( !( $revDel & self::CANNOT_VIEW ) ) {
453 if ( $slot->getSha1() != '' ) {
454 $vals['sha1'] = Wikimedia\base_convert( $slot->getSha1(), 36, 16, 40 );
455 } else {
456 $vals['sha1'] = '';
457 }
458 }
459 }
460
461 if ( $this->fld_contentmodel ) {
462 $vals['contentmodel'] = $slot->getModel();
463 }
464
465 $content = null;
466 if ( $this->fetchContent ) {
467 if ( ( $revDel & self::IS_DELETED ) ) {
468 $vals['texthidden'] = true;
469 }
470 if ( !( $revDel & self::CANNOT_VIEW ) ) {
471 try {
472 $content = $slot->getContent();
473 } catch ( RevisionAccessException $e ) {
474 // @todo: Gergő says to mention T198099 as a "todo" here.
475 $vals['textmissing'] = true;
476 }
477 // Expand templates after getting section content because
478 // template-added sections don't count and Parser::preprocess()
479 // will have less input
480 if ( $content && $this->section !== false ) {
481 $content = $content->getSection( $this->section, false );
482 if ( !$content ) {
483 $vals['nosuchsection'] = true;
484 }
485 }
486 }
487 }
488
489 return $vals;
490 }
491
492 /**
493 * Format a Content using deprecated options
494 * @param Content $content Content to format
495 * @param RevisionRecord $revision Revision being processed
496 * @return array
497 */
498 private function extractDeprecatedContent( Content $content, RevisionRecord $revision ) {
499 $vals = [];
500 $title = Title::newFromLinkTarget( $revision->getPageAsLinkTarget() );
501
502 if ( $this->fld_parsetree || ( $this->fld_content && $this->generateXML ) ) {
503 if ( $content->getModel() === CONTENT_MODEL_WIKITEXT ) {
504 /** @var WikitextContent $content */
505 '@phan-var WikitextContent $content';
506 $t = $content->getText(); # note: don't set $text
507
508 $parser = MediaWikiServices::getInstance()->getParser();
509 $parser->startExternalParse(
510 $title,
511 ParserOptions::newFromContext( $this->getContext() ),
512 Parser::OT_PREPROCESS
513 );
514 $dom = $parser->preprocessToDom( $t );
515 // @phan-suppress-next-line PhanUndeclaredMethodInCallable
516 if ( is_callable( [ $dom, 'saveXML' ] ) ) {
517 // @phan-suppress-next-line PhanUndeclaredMethod
518 $xml = $dom->saveXML();
519 } else {
520 // @phan-suppress-next-line PhanUndeclaredMethod
521 $xml = $dom->__toString();
522 }
523 $vals['parsetree'] = $xml;
524 } else {
525 $vals['badcontentformatforparsetree'] = true;
526 $this->addWarning(
527 [
528 'apierror-parsetree-notwikitext-title',
529 wfEscapeWikiText( $title->getPrefixedText() ),
530 $content->getModel()
531 ],
532 'parsetree-notwikitext'
533 );
534 }
535 }
536
537 if ( $this->fld_content ) {
538 $text = null;
539
540 if ( $this->expandTemplates && !$this->parseContent ) {
541 if ( $content->getModel() === CONTENT_MODEL_WIKITEXT ) {
542 /** @var WikitextContent $content */
543 '@phan-var WikitextContent $content';
544 $text = $content->getText();
545
546 $text = MediaWikiServices::getInstance()->getParser()->preprocess(
547 $text,
548 $title,
549 ParserOptions::newFromContext( $this->getContext() )
550 );
551 } else {
552 $this->addWarning( [
553 'apierror-templateexpansion-notwikitext',
554 wfEscapeWikiText( $title->getPrefixedText() ),
555 $content->getModel()
556 ] );
557 $vals['badcontentformat'] = true;
558 $text = false;
559 }
560 }
561 if ( $this->parseContent ) {
562 $po = $content->getParserOutput(
563 $title,
564 $revision->getId(),
565 ParserOptions::newFromContext( $this->getContext() )
566 );
567 $text = $po->getText();
568 }
569
570 if ( $text === null ) {
571 $format = $this->contentFormat ?: $content->getDefaultFormat();
572 $model = $content->getModel();
573
574 if ( !$content->isSupportedFormat( $format ) ) {
575 $name = wfEscapeWikiText( $title->getPrefixedText() );
576 $this->addWarning( [ 'apierror-badformat', $this->contentFormat, $model, $name ] );
577 $vals['badcontentformat'] = true;
578 $text = false;
579 } else {
580 $text = $content->serialize( $format );
581 // always include format and model.
582 // Format is needed to deserialize, model is needed to interpret.
583 $vals['contentformat'] = $format;
584 $vals['contentmodel'] = $model;
585 }
586 }
587
588 if ( $text !== false ) {
589 ApiResult::setContentValue( $vals, 'content', $text );
590 }
591 }
592
593 if ( $content && ( !is_null( $this->diffto ) || !is_null( $this->difftotext ) ) ) {
594 static $n = 0; // Number of uncached diffs we've had
595
596 if ( $n < $this->getConfig()->get( 'APIMaxUncachedDiffs' ) ) {
597 $vals['diff'] = [];
598 $context = new DerivativeContext( $this->getContext() );
599 $context->setTitle( $title );
600 $handler = $content->getContentHandler();
601
602 if ( !is_null( $this->difftotext ) ) {
603 $model = $title->getContentModel();
604
605 if ( $this->contentFormat
606 && !ContentHandler::getForModelID( $model )->isSupportedFormat( $this->contentFormat )
607 ) {
608 $name = wfEscapeWikiText( $title->getPrefixedText() );
609 $this->addWarning( [ 'apierror-badformat', $this->contentFormat, $model, $name ] );
610 $vals['diff']['badcontentformat'] = true;
611 $engine = null;
612 } else {
613 $difftocontent = ContentHandler::makeContent(
614 $this->difftotext,
615 $title,
616 $model,
617 $this->contentFormat
618 );
619
620 if ( $this->difftotextpst ) {
621 $popts = ParserOptions::newFromContext( $this->getContext() );
622 $difftocontent = $difftocontent->preSaveTransform( $title, $this->getUser(), $popts );
623 }
624
625 $engine = $handler->createDifferenceEngine( $context );
626 $engine->setContent( $content, $difftocontent );
627 }
628 } else {
629 $engine = $handler->createDifferenceEngine( $context, $revision->getId(), $this->diffto );
630 $vals['diff']['from'] = $engine->getOldid();
631 $vals['diff']['to'] = $engine->getNewid();
632 }
633 if ( $engine ) {
634 $difftext = $engine->getDiffBody();
635 ApiResult::setContentValue( $vals['diff'], 'body', $difftext );
636 if ( !$engine->wasCacheHit() ) {
637 $n++;
638 }
639 }
640 } else {
641 $vals['diff']['notcached'] = true;
642 }
643 }
644
645 return $vals;
646 }
647
648 public function getCacheMode( $params ) {
649 if ( $this->userCanSeeRevDel() ) {
650 return 'private';
651 }
652
653 return 'public';
654 }
655
656 public function getAllowedParams() {
657 $slotRoles = MediaWikiServices::getInstance()->getSlotRoleRegistry()->getKnownRoles();
658 sort( $slotRoles, SORT_STRING );
659
660 return [
661 'prop' => [
662 ApiBase::PARAM_ISMULTI => true,
663 ApiBase::PARAM_DFLT => 'ids|timestamp|flags|comment|user',
664 ApiBase::PARAM_TYPE => [
665 'ids',
666 'flags',
667 'timestamp',
668 'user',
669 'userid',
670 'size',
671 'slotsize',
672 'sha1',
673 'slotsha1',
674 'contentmodel',
675 'comment',
676 'parsedcomment',
677 'content',
678 'tags',
679 'roles',
680 'parsetree',
681 ],
682 ApiBase::PARAM_HELP_MSG => 'apihelp-query+revisions+base-param-prop',
683 ApiBase::PARAM_HELP_MSG_PER_VALUE => [
684 'ids' => 'apihelp-query+revisions+base-paramvalue-prop-ids',
685 'flags' => 'apihelp-query+revisions+base-paramvalue-prop-flags',
686 'timestamp' => 'apihelp-query+revisions+base-paramvalue-prop-timestamp',
687 'user' => 'apihelp-query+revisions+base-paramvalue-prop-user',
688 'userid' => 'apihelp-query+revisions+base-paramvalue-prop-userid',
689 'size' => 'apihelp-query+revisions+base-paramvalue-prop-size',
690 'slotsize' => 'apihelp-query+revisions+base-paramvalue-prop-slotsize',
691 'sha1' => 'apihelp-query+revisions+base-paramvalue-prop-sha1',
692 'slotsha1' => 'apihelp-query+revisions+base-paramvalue-prop-slotsha1',
693 'contentmodel' => 'apihelp-query+revisions+base-paramvalue-prop-contentmodel',
694 'comment' => 'apihelp-query+revisions+base-paramvalue-prop-comment',
695 'parsedcomment' => 'apihelp-query+revisions+base-paramvalue-prop-parsedcomment',
696 'content' => 'apihelp-query+revisions+base-paramvalue-prop-content',
697 'tags' => 'apihelp-query+revisions+base-paramvalue-prop-tags',
698 'roles' => 'apihelp-query+revisions+base-paramvalue-prop-roles',
699 'parsetree' => [ 'apihelp-query+revisions+base-paramvalue-prop-parsetree',
700 CONTENT_MODEL_WIKITEXT ],
701 ],
702 ApiBase::PARAM_DEPRECATED_VALUES => [
703 'parsetree' => true,
704 ],
705 ],
706 'slots' => [
707 ApiBase::PARAM_TYPE => $slotRoles,
708 ApiBase::PARAM_HELP_MSG => 'apihelp-query+revisions+base-param-slots',
709 ApiBase::PARAM_ISMULTI => true,
710 ApiBase::PARAM_ALL => true,
711 ],
712 'limit' => [
713 ApiBase::PARAM_TYPE => 'limit',
714 ApiBase::PARAM_MIN => 1,
715 ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG1,
716 ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2,
717 ApiBase::PARAM_HELP_MSG => 'apihelp-query+revisions+base-param-limit',
718 ],
719 'expandtemplates' => [
720 ApiBase::PARAM_DFLT => false,
721 ApiBase::PARAM_HELP_MSG => 'apihelp-query+revisions+base-param-expandtemplates',
722 ApiBase::PARAM_DEPRECATED => true,
723 ],
724 'generatexml' => [
725 ApiBase::PARAM_DFLT => false,
726 ApiBase::PARAM_DEPRECATED => true,
727 ApiBase::PARAM_HELP_MSG => 'apihelp-query+revisions+base-param-generatexml',
728 ],
729 'parse' => [
730 ApiBase::PARAM_DFLT => false,
731 ApiBase::PARAM_HELP_MSG => 'apihelp-query+revisions+base-param-parse',
732 ApiBase::PARAM_DEPRECATED => true,
733 ],
734 'section' => [
735 ApiBase::PARAM_HELP_MSG => 'apihelp-query+revisions+base-param-section',
736 ],
737 'diffto' => [
738 ApiBase::PARAM_HELP_MSG => 'apihelp-query+revisions+base-param-diffto',
739 ApiBase::PARAM_DEPRECATED => true,
740 ],
741 'difftotext' => [
742 ApiBase::PARAM_HELP_MSG => 'apihelp-query+revisions+base-param-difftotext',
743 ApiBase::PARAM_DEPRECATED => true,
744 ],
745 'difftotextpst' => [
746 ApiBase::PARAM_DFLT => false,
747 ApiBase::PARAM_HELP_MSG => 'apihelp-query+revisions+base-param-difftotextpst',
748 ApiBase::PARAM_DEPRECATED => true,
749 ],
750 'contentformat' => [
751 ApiBase::PARAM_TYPE => ContentHandler::getAllContentFormats(),
752 ApiBase::PARAM_HELP_MSG => 'apihelp-query+revisions+base-param-contentformat',
753 ApiBase::PARAM_DEPRECATED => true,
754 ],
755 ];
756 }
757
758 }