3 * Copyright © 2006 Yuri Astrakhan "<Firstname><Lastname>@gmail.com"
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.
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.
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
23 use MediaWiki\Storage\RevisionAccessException
;
24 use MediaWiki\Storage\RevisionRecord
;
25 use MediaWiki\Storage\SlotRecord
;
26 use MediaWiki\MediaWikiServices
;
29 * A base class for functions common to producing a list of revisions.
33 abstract class ApiQueryRevisionsBase
extends ApiQueryGeneratorBase
{
36 * @name Constants for internal use. Don't use externally.
40 // Bits to indicate the results of the revdel permission check on a revision,
41 // see self::checkRevDel()
42 const IS_DELETED
= 1; // Whether the field is revision-deleted
43 const CANNOT_VIEW
= 2; // Whether the user cannot view the field due to revdel
47 protected $limit, $diffto, $difftotext, $difftotextpst, $expandTemplates, $generateXML,
48 $section, $parseContent, $fetchContent, $contentFormat, $setParsedLimit = true,
49 $slotRoles = null, $needSlots;
51 protected $fld_ids = false, $fld_flags = false, $fld_timestamp = false,
52 $fld_size = false, $fld_slotsize = false, $fld_sha1 = false, $fld_slotsha1 = false,
53 $fld_comment = false, $fld_parsedcomment = false, $fld_user = false, $fld_userid = false,
54 $fld_content = false, $fld_tags = false, $fld_contentmodel = false, $fld_roles = false,
55 $fld_parsetree = false;
57 public function execute() {
61 public function executeGenerator( $resultPageSet ) {
62 $this->run( $resultPageSet );
66 * @param ApiPageSet|null $resultPageSet
69 abstract protected function run( ApiPageSet
$resultPageSet = null );
72 * Parse the parameters into the various instance fields.
74 * @param array $params
76 protected function parseParameters( $params ) {
77 $prop = array_flip( $params['prop'] );
79 $this->fld_ids
= isset( $prop['ids'] );
80 $this->fld_flags
= isset( $prop['flags'] );
81 $this->fld_timestamp
= isset( $prop['timestamp'] );
82 $this->fld_comment
= isset( $prop['comment'] );
83 $this->fld_parsedcomment
= isset( $prop['parsedcomment'] );
84 $this->fld_size
= isset( $prop['size'] );
85 $this->fld_slotsize
= isset( $prop['slotsize'] );
86 $this->fld_sha1
= isset( $prop['sha1'] );
87 $this->fld_slotsha1
= isset( $prop['slotsha1'] );
88 $this->fld_content
= isset( $prop['content'] );
89 $this->fld_contentmodel
= isset( $prop['contentmodel'] );
90 $this->fld_userid
= isset( $prop['userid'] );
91 $this->fld_user
= isset( $prop['user'] );
92 $this->fld_tags
= isset( $prop['tags'] );
93 $this->fld_roles
= isset( $prop['roles'] );
94 $this->fld_parsetree
= isset( $prop['parsetree'] );
96 $this->slotRoles
= $params['slots'];
98 if ( $this->slotRoles
!== null ) {
99 if ( $this->fld_parsetree
) {
100 $this->dieWithError( [
101 'apierror-invalidparammix-cannotusewith',
102 $this->encodeParamName( 'prop=parsetree' ),
103 $this->encodeParamName( 'slots' ),
104 ], 'invalidparammix' );
107 'expandtemplates', 'generatexml', 'parse', 'diffto', 'difftotext', 'difftotextpst',
110 if ( $params[$p] !== null && $params[$p] !== false ) {
111 $this->dieWithError( [
112 'apierror-invalidparammix-cannotusewith',
113 $this->encodeParamName( $p ),
114 $this->encodeParamName( 'slots' ),
115 ], 'invalidparammix' );
120 if ( !empty( $params['contentformat'] ) ) {
121 $this->contentFormat
= $params['contentformat'];
124 $this->limit
= $params['limit'];
126 if ( !is_null( $params['difftotext'] ) ) {
127 $this->difftotext
= $params['difftotext'];
128 $this->difftotextpst
= $params['difftotextpst'];
129 } elseif ( !is_null( $params['diffto'] ) ) {
130 if ( $params['diffto'] == 'cur' ) {
131 $params['diffto'] = 0;
133 if ( ( !ctype_digit( $params['diffto'] ) ||
$params['diffto'] < 0 )
134 && $params['diffto'] != 'prev' && $params['diffto'] != 'next'
136 $p = $this->getModulePrefix();
137 $this->dieWithError( [ 'apierror-baddiffto', $p ], 'diffto' );
139 // Check whether the revision exists and is readable,
140 // DifferenceEngine returns a rather ambiguous empty
141 // string if that's not the case
142 if ( $params['diffto'] != 0 ) {
143 $difftoRev = MediaWikiServices
::getInstance()->getRevisionStore()
144 ->getRevisionById( $params['diffto'] );
146 $this->dieWithError( [ 'apierror-nosuchrevid', $params['diffto'] ] );
148 $revDel = $this->checkRevDel( $difftoRev, RevisionRecord
::DELETED_TEXT
);
149 if ( $revDel & self
::CANNOT_VIEW
) {
150 $this->addWarning( [ 'apiwarn-difftohidden', $difftoRev->getId() ] );
151 $params['diffto'] = null;
154 $this->diffto
= $params['diffto'];
157 $this->fetchContent
= $this->fld_content ||
!is_null( $this->diffto
)
158 ||
!is_null( $this->difftotext
) ||
$this->fld_parsetree
;
161 if ( $this->fetchContent
) {
163 $this->expandTemplates
= $params['expandtemplates'];
164 $this->generateXML
= $params['generatexml'];
165 $this->parseContent
= $params['parse'];
166 if ( $this->parseContent
) {
167 // Must manually initialize unset limit
168 if ( is_null( $this->limit
) ) {
172 if ( isset( $params['section'] ) ) {
173 $this->section
= $params['section'];
175 $this->section
= false;
179 $userMax = $this->parseContent ?
1 : ( $smallLimit ? ApiBase
::LIMIT_SML1
: ApiBase
::LIMIT_BIG1
);
180 $botMax = $this->parseContent ?
1 : ( $smallLimit ? ApiBase
::LIMIT_SML2
: ApiBase
::LIMIT_BIG2
);
181 if ( $this->limit
== 'max' ) {
182 $this->limit
= $this->getMain()->canApiHighLimits() ?
$botMax : $userMax;
183 if ( $this->setParsedLimit
) {
184 $this->getResult()->addParsedLimit( $this->getModuleName(), $this->limit
);
188 if ( is_null( $this->limit
) ) {
191 $this->validateLimit( 'limit', $this->limit
, 1, $userMax, $botMax );
193 $this->needSlots
= $this->fetchContent ||
$this->fld_contentmodel ||
194 $this->fld_slotsize ||
$this->fld_slotsha1
;
195 if ( $this->needSlots
&& $this->slotRoles
=== null ) {
196 $encParam = $this->encodeParamName( 'slots' );
197 $name = $this->getModuleName();
198 $parent = $this->getParent();
199 $parentParam = $parent->encodeParamName( $parent->getModuleManager()->getModuleGroup( $name ) );
200 $this->addDeprecation(
201 [ 'apiwarn-deprecation-missingparam', $encParam ],
202 "action=query&{$parentParam}={$name}&!{$encParam}"
208 * Test revision deletion status
209 * @param RevisionRecord $revision Revision to check
210 * @param int $field One of the RevisionRecord::DELETED_* constants
211 * @return int Revision deletion status flags. Bitwise OR of
212 * self::IS_DELETED and self::CANNOT_VIEW, as appropriate.
214 private function checkRevDel( RevisionRecord
$revision, $field ) {
215 $ret = $revision->isDeleted( $field ) ? self
::IS_DELETED
: 0;
217 $canSee = $revision->audienceCan( $field, RevisionRecord
::FOR_THIS_USER
, $this->getUser() );
218 $ret = $ret |
( $canSee ?
0 : self
::CANNOT_VIEW
);
224 * Extract information from the RevisionRecord
226 * @since 1.32, takes a RevisionRecord instead of a Revision
227 * @param RevisionRecord $revision Revision
228 * @param object $row Should have a field 'ts_tags' if $this->fld_tags is set
231 protected function extractRevisionInfo( RevisionRecord
$revision, $row ) {
235 if ( $this->fld_ids
) {
236 $vals['revid'] = intval( $revision->getId() );
237 if ( !is_null( $revision->getParentId() ) ) {
238 $vals['parentid'] = intval( $revision->getParentId() );
242 if ( $this->fld_flags
) {
243 $vals['minor'] = $revision->isMinor();
246 if ( $this->fld_user ||
$this->fld_userid
) {
247 $revDel = $this->checkRevDel( $revision, RevisionRecord
::DELETED_USER
);
248 if ( ( $revDel & self
::IS_DELETED
) ) {
249 $vals['userhidden'] = true;
252 if ( !( $revDel & self
::CANNOT_VIEW
) ) {
253 $u = $revision->getUser( RevisionRecord
::RAW
);
254 if ( $this->fld_user
) {
255 $vals['user'] = $u->getName();
257 $userid = $u->getId();
259 $vals['anon'] = true;
262 if ( $this->fld_userid
) {
263 $vals['userid'] = $userid;
268 if ( $this->fld_timestamp
) {
269 $vals['timestamp'] = wfTimestamp( TS_ISO_8601
, $revision->getTimestamp() );
272 if ( $this->fld_size
) {
274 $vals['size'] = intval( $revision->getSize() );
275 } catch ( RevisionAccessException
$e ) {
276 // Back compat: If there's no size, return 0.
277 // @todo: Gergő says to mention T198099 as a "todo" here.
282 if ( $this->fld_sha1
) {
283 $revDel = $this->checkRevDel( $revision, RevisionRecord
::DELETED_TEXT
);
284 if ( ( $revDel & self
::IS_DELETED
) ) {
285 $vals['sha1hidden'] = true;
288 if ( !( $revDel & self
::CANNOT_VIEW
) ) {
290 $vals['sha1'] = Wikimedia\base_convert
( $revision->getSha1(), 36, 16, 40 );
291 } catch ( RevisionAccessException
$e ) {
292 // Back compat: If there's no sha1, return emtpy string.
293 // @todo: Gergő says to mention T198099 as a "todo" here.
299 if ( $this->fld_roles
) {
300 $vals['roles'] = $revision->getSlotRoles();
303 if ( $this->needSlots
) {
304 $revDel = $this->checkRevDel( $revision, RevisionRecord
::DELETED_TEXT
);
305 if ( ( $this->fld_slotsha1 ||
$this->fetchContent
) && ( $revDel & self
::IS_DELETED
) ) {
308 if ( $this->slotRoles
=== null ) {
310 $slot = $revision->getSlot( SlotRecord
::MAIN
, RevisionRecord
::RAW
);
311 } catch ( RevisionAccessException
$e ) {
312 // Back compat: If there's no slot, there's no content, so set 'textmissing'
313 // @todo: Gergő says to mention T198099 as a "todo" here.
314 $vals['textmissing'] = true;
320 $vals +
= $this->extractSlotInfo( $slot, $revDel, $content );
321 if ( !empty( $vals['nosuchsection'] ) ) {
324 'apierror-nosuchsection-what',
325 wfEscapeWikiText( $this->section
),
326 $this->msg( 'revid', $revision->getId() )
332 $vals +
= $this->extractDeprecatedContent( $content, $revision );
336 $roles = array_intersect( $this->slotRoles
, $revision->getSlotRoles() );
338 ApiResult
::META_KVP_MERGE
=> true,
340 foreach ( $roles as $role ) {
342 $slot = $revision->getSlot( $role, RevisionRecord
::RAW
);
343 } catch ( RevisionAccessException
$e ) {
344 // Don't error out here so the client can still process other slots/revisions.
345 // @todo: Gergő says to mention T198099 as a "todo" here.
346 $vals['slots'][$role]['missing'] = true;
350 $vals['slots'][$role] = $this->extractSlotInfo( $slot, $revDel, $content );
351 // @todo Move this into extractSlotInfo() (and remove its $content parameter)
352 // when extractDeprecatedContent() is no more.
354 $vals['slots'][$role]['contentmodel'] = $content->getModel();
355 $vals['slots'][$role]['contentformat'] = $content->getDefaultFormat();
356 ApiResult
::setContentValue( $vals['slots'][$role], 'content', $content->serialize() );
359 ApiResult
::setArrayType( $vals['slots'], 'kvp', 'role' );
360 ApiResult
::setIndexedTagName( $vals['slots'], 'slot' );
364 if ( $this->fld_comment ||
$this->fld_parsedcomment
) {
365 $revDel = $this->checkRevDel( $revision, RevisionRecord
::DELETED_COMMENT
);
366 if ( ( $revDel & self
::IS_DELETED
) ) {
367 $vals['commenthidden'] = true;
370 if ( !( $revDel & self
::CANNOT_VIEW
) ) {
371 $comment = $revision->getComment( RevisionRecord
::RAW
);
372 $comment = $comment ?
$comment->text
: '';
374 if ( $this->fld_comment
) {
375 $vals['comment'] = $comment;
378 if ( $this->fld_parsedcomment
) {
379 $vals['parsedcomment'] = Linker
::formatComment(
380 $comment, Title
::newFromLinkTarget( $revision->getPageAsLinkTarget() )
386 if ( $this->fld_tags
) {
387 if ( $row->ts_tags
) {
388 $tags = explode( ',', $row->ts_tags
);
389 ApiResult
::setIndexedTagName( $tags, 'tag' );
390 $vals['tags'] = $tags;
396 if ( $anyHidden && $revision->isDeleted( RevisionRecord
::DELETED_RESTRICTED
) ) {
397 $vals['suppressed'] = true;
404 * Extract information from the SlotRecord
406 * @param SlotRecord $slot
407 * @param int $revDel Revdel status flags, from self::checkRevDel()
408 * @param Content|null &$content Set to the slot's content, if available
409 * and $this->fetchContent is true
412 private function extractSlotInfo( SlotRecord
$slot, $revDel, &$content = null ) {
414 ApiResult
::setArrayType( $vals, 'assoc' );
416 if ( $this->fld_slotsize
) {
417 $vals['size'] = intval( $slot->getSize() );
420 if ( $this->fld_slotsha1
) {
421 if ( ( $revDel & self
::IS_DELETED
) ) {
422 $vals['sha1hidden'] = true;
424 if ( !( $revDel & self
::CANNOT_VIEW
) ) {
425 if ( $slot->getSha1() != '' ) {
426 $vals['sha1'] = Wikimedia\base_convert
( $slot->getSha1(), 36, 16, 40 );
433 if ( $this->fld_contentmodel
) {
434 $vals['contentmodel'] = $slot->getModel();
438 if ( $this->fetchContent
) {
439 if ( ( $revDel & self
::IS_DELETED
) ) {
440 $vals['texthidden'] = true;
442 if ( !( $revDel & self
::CANNOT_VIEW
) ) {
444 $content = $slot->getContent();
445 } catch ( RevisionAccessException
$e ) {
446 // @todo: Gergő says to mention T198099 as a "todo" here.
447 $vals['textmissing'] = true;
449 // Expand templates after getting section content because
450 // template-added sections don't count and Parser::preprocess()
451 // will have less input
452 if ( $content && $this->section
!== false ) {
453 $content = $content->getSection( $this->section
, false );
455 $vals['nosuchsection'] = true;
465 * Format a Content using deprecated options
466 * @param Content $content Content to format
467 * @param RevisionRecord $revision Revision being processed
470 private function extractDeprecatedContent( Content
$content, RevisionRecord
$revision ) {
474 $title = Title
::newFromLinkTarget( $revision->getPageAsLinkTarget() );
476 if ( $this->fld_parsetree ||
( $this->fld_content
&& $this->generateXML
) ) {
477 if ( $content->getModel() === CONTENT_MODEL_WIKITEXT
) {
478 $t = $content->getNativeData(); # note: don't set $text
480 $wgParser->startExternalParse(
482 ParserOptions
::newFromContext( $this->getContext() ),
483 Parser
::OT_PREPROCESS
485 $dom = $wgParser->preprocessToDom( $t );
486 if ( is_callable( [ $dom, 'saveXML' ] ) ) {
487 $xml = $dom->saveXML();
489 $xml = $dom->__toString();
491 $vals['parsetree'] = $xml;
493 $vals['badcontentformatforparsetree'] = true;
496 'apierror-parsetree-notwikitext-title',
497 wfEscapeWikiText( $title->getPrefixedText() ),
500 'parsetree-notwikitext'
505 if ( $this->fld_content
) {
508 if ( $this->expandTemplates
&& !$this->parseContent
) {
509 if ( $content->getModel() === CONTENT_MODEL_WIKITEXT
) {
510 $text = $content->getNativeData();
512 $text = $wgParser->preprocess(
515 ParserOptions
::newFromContext( $this->getContext() )
519 'apierror-templateexpansion-notwikitext',
520 wfEscapeWikiText( $title->getPrefixedText() ),
523 $vals['badcontentformat'] = true;
527 if ( $this->parseContent
) {
528 $po = $content->getParserOutput(
531 ParserOptions
::newFromContext( $this->getContext() )
533 $text = $po->getText();
536 if ( $text === null ) {
537 $format = $this->contentFormat ?
: $content->getDefaultFormat();
538 $model = $content->getModel();
540 if ( !$content->isSupportedFormat( $format ) ) {
541 $name = wfEscapeWikiText( $title->getPrefixedText() );
542 $this->addWarning( [ 'apierror-badformat', $this->contentFormat
, $model, $name ] );
543 $vals['badcontentformat'] = true;
546 $text = $content->serialize( $format );
547 // always include format and model.
548 // Format is needed to deserialize, model is needed to interpret.
549 $vals['contentformat'] = $format;
550 $vals['contentmodel'] = $model;
554 if ( $text !== false ) {
555 ApiResult
::setContentValue( $vals, 'content', $text );
559 if ( $content && ( !is_null( $this->diffto
) ||
!is_null( $this->difftotext
) ) ) {
560 static $n = 0; // Number of uncached diffs we've had
562 if ( $n < $this->getConfig()->get( 'APIMaxUncachedDiffs' ) ) {
564 $context = new DerivativeContext( $this->getContext() );
565 $context->setTitle( $title );
566 $handler = $content->getContentHandler();
568 if ( !is_null( $this->difftotext
) ) {
569 $model = $title->getContentModel();
571 if ( $this->contentFormat
572 && !ContentHandler
::getForModelID( $model )->isSupportedFormat( $this->contentFormat
)
574 $name = wfEscapeWikiText( $title->getPrefixedText() );
575 $this->addWarning( [ 'apierror-badformat', $this->contentFormat
, $model, $name ] );
576 $vals['diff']['badcontentformat'] = true;
579 $difftocontent = ContentHandler
::makeContent(
586 if ( $this->difftotextpst
) {
587 $popts = ParserOptions
::newFromContext( $this->getContext() );
588 $difftocontent = $difftocontent->preSaveTransform( $title, $this->getUser(), $popts );
591 $engine = $handler->createDifferenceEngine( $context );
592 $engine->setContent( $content, $difftocontent );
595 $engine = $handler->createDifferenceEngine( $context, $revision->getId(), $this->diffto
);
596 $vals['diff']['from'] = $engine->getOldid();
597 $vals['diff']['to'] = $engine->getNewid();
600 $difftext = $engine->getDiffBody();
601 ApiResult
::setContentValue( $vals['diff'], 'body', $difftext );
602 if ( !$engine->wasCacheHit() ) {
607 $vals['diff']['notcached'] = true;
614 public function getCacheMode( $params ) {
615 if ( $this->userCanSeeRevDel() ) {
622 public function getAllowedParams() {
623 $slotRoles = MediaWikiServices
::getInstance()->getSlotRoleStore()->getMap();
624 if ( !in_array( SlotRecord
::MAIN
, $slotRoles, true ) ) {
625 $slotRoles[] = SlotRecord
::MAIN
;
627 sort( $slotRoles, SORT_STRING
);
631 ApiBase
::PARAM_ISMULTI
=> true,
632 ApiBase
::PARAM_DFLT
=> 'ids|timestamp|flags|comment|user',
633 ApiBase
::PARAM_TYPE
=> [
651 ApiBase
::PARAM_HELP_MSG
=> 'apihelp-query+revisions+base-param-prop',
652 ApiBase
::PARAM_HELP_MSG_PER_VALUE
=> [
653 'ids' => 'apihelp-query+revisions+base-paramvalue-prop-ids',
654 'flags' => 'apihelp-query+revisions+base-paramvalue-prop-flags',
655 'timestamp' => 'apihelp-query+revisions+base-paramvalue-prop-timestamp',
656 'user' => 'apihelp-query+revisions+base-paramvalue-prop-user',
657 'userid' => 'apihelp-query+revisions+base-paramvalue-prop-userid',
658 'size' => 'apihelp-query+revisions+base-paramvalue-prop-size',
659 'slotsize' => 'apihelp-query+revisions+base-paramvalue-prop-slotsize',
660 'sha1' => 'apihelp-query+revisions+base-paramvalue-prop-sha1',
661 'slotsha1' => 'apihelp-query+revisions+base-paramvalue-prop-slotsha1',
662 'contentmodel' => 'apihelp-query+revisions+base-paramvalue-prop-contentmodel',
663 'comment' => 'apihelp-query+revisions+base-paramvalue-prop-comment',
664 'parsedcomment' => 'apihelp-query+revisions+base-paramvalue-prop-parsedcomment',
665 'content' => 'apihelp-query+revisions+base-paramvalue-prop-content',
666 'tags' => 'apihelp-query+revisions+base-paramvalue-prop-tags',
667 'roles' => 'apihelp-query+revisions+base-paramvalue-prop-roles',
668 'parsetree' => [ 'apihelp-query+revisions+base-paramvalue-prop-parsetree',
669 CONTENT_MODEL_WIKITEXT
],
671 ApiBase
::PARAM_DEPRECATED_VALUES
=> [
676 ApiBase
::PARAM_TYPE
=> $slotRoles,
677 ApiBase
::PARAM_HELP_MSG
=> 'apihelp-query+revisions+base-param-slots',
678 ApiBase
::PARAM_ISMULTI
=> true,
679 ApiBase
::PARAM_ALL
=> true,
682 ApiBase
::PARAM_TYPE
=> 'limit',
683 ApiBase
::PARAM_MIN
=> 1,
684 ApiBase
::PARAM_MAX
=> ApiBase
::LIMIT_BIG1
,
685 ApiBase
::PARAM_MAX2
=> ApiBase
::LIMIT_BIG2
,
686 ApiBase
::PARAM_HELP_MSG
=> 'apihelp-query+revisions+base-param-limit',
688 'expandtemplates' => [
689 ApiBase
::PARAM_DFLT
=> false,
690 ApiBase
::PARAM_HELP_MSG
=> 'apihelp-query+revisions+base-param-expandtemplates',
691 ApiBase
::PARAM_DEPRECATED
=> true,
694 ApiBase
::PARAM_DFLT
=> false,
695 ApiBase
::PARAM_DEPRECATED
=> true,
696 ApiBase
::PARAM_HELP_MSG
=> 'apihelp-query+revisions+base-param-generatexml',
699 ApiBase
::PARAM_DFLT
=> false,
700 ApiBase
::PARAM_HELP_MSG
=> 'apihelp-query+revisions+base-param-parse',
701 ApiBase
::PARAM_DEPRECATED
=> true,
704 ApiBase
::PARAM_HELP_MSG
=> 'apihelp-query+revisions+base-param-section',
707 ApiBase
::PARAM_HELP_MSG
=> 'apihelp-query+revisions+base-param-diffto',
708 ApiBase
::PARAM_DEPRECATED
=> true,
711 ApiBase
::PARAM_HELP_MSG
=> 'apihelp-query+revisions+base-param-difftotext',
712 ApiBase
::PARAM_DEPRECATED
=> true,
715 ApiBase
::PARAM_DFLT
=> false,
716 ApiBase
::PARAM_HELP_MSG
=> 'apihelp-query+revisions+base-param-difftotextpst',
717 ApiBase
::PARAM_DEPRECATED
=> true,
720 ApiBase
::PARAM_TYPE
=> ContentHandler
::getAllContentFormats(),
721 ApiBase
::PARAM_HELP_MSG
=> 'apihelp-query+revisions+base-param-contentformat',
722 ApiBase
::PARAM_DEPRECATED
=> true,