63 $this->
run( $resultPageSet );
78 $prop = array_flip( $params[
'prop'] );
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'] );
97 $this->slotRoles = $params[
'slots'];
99 if ( $this->slotRoles !==
null ) {
100 if ( $this->fld_parsetree ) {
102 'apierror-invalidparammix-cannotusewith',
105 ],
'invalidparammix' );
108 'expandtemplates',
'generatexml',
'parse',
'diffto',
'difftotext',
'difftotextpst',
111 if ( $params[$p] !==
null && $params[$p] !==
false ) {
113 'apierror-invalidparammix-cannotusewith',
116 ],
'invalidparammix' );
121 if ( !empty( $params[
'contentformat'] ) ) {
122 $this->contentFormat = $params[
'contentformat'];
125 $this->limit = $params[
'limit'];
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;
134 if ( ( !ctype_digit( $params[
'diffto'] ) || $params[
'diffto'] < 0 )
135 && $params[
'diffto'] !=
'prev' && $params[
'diffto'] !=
'next'
138 $this->
dieWithError( [
'apierror-baddiffto', $p ],
'diffto' );
143 if ( $params[
'diffto'] != 0 ) {
144 $difftoRev = MediaWikiServices::getInstance()->getRevisionStore()
145 ->getRevisionById( $params[
'diffto'] );
147 $this->
dieWithError( [
'apierror-nosuchrevid', $params[
'diffto'] ] );
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;
155 $this->diffto = $params[
'diffto'];
158 $this->fetchContent = $this->fld_content || !is_null( $this->diffto )
162 if ( $this->fetchContent ) {
164 $this->expandTemplates = $params[
'expandtemplates'];
165 $this->generateXML = $params[
'generatexml'];
166 $this->parseContent = $params[
'parse'];
167 if ( $this->parseContent ) {
169 if ( is_null( $this->limit ) ) {
173 $this->section = $params[
'section'] ??
false;
178 if ( $this->limit ==
'max' ) {
179 $this->limit = $this->
getMain()->canApiHighLimits() ? $botMax : $userMax;
180 if ( $this->setParsedLimit ) {
185 if ( is_null( $this->limit ) ) {
188 $this->
validateLimit(
'limit', $this->limit, 1, $userMax, $botMax );
190 $this->needSlots = $this->fetchContent || $this->fld_contentmodel ||
192 if ( $this->needSlots && $this->slotRoles ===
null ) {
196 $parentParam = $parent->encodeParamName( $parent->getModuleManager()->getModuleGroup( $name ) );
198 [
'apiwarn-deprecation-missingparam', $encParam ],
199 "action=query&{$parentParam}={$name}&!{$encParam}"
214 $canSee = $revision->
audienceCan( $field, RevisionRecord::FOR_THIS_USER, $this->
getUser() );
232 if ( $this->fld_ids ) {
233 $vals[
'revid'] = (int)$revision->
getId();
239 if ( $this->fld_flags ) {
240 $vals[
'minor'] = $revision->
isMinor();
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;
249 if ( !( $revDel & self::CANNOT_VIEW ) ) {
250 $u = $revision->
getUser( RevisionRecord::RAW );
251 if ( $this->fld_user ) {
252 $vals[
'user'] = $u->getName();
254 $userid = $u->getId();
256 $vals[
'anon'] =
true;
259 if ( $this->fld_userid ) {
260 $vals[
'userid'] = $userid;
265 if ( $this->fld_timestamp ) {
269 if ( $this->fld_size ) {
271 $vals[
'size'] = (int)$revision->
getSize();
279 if ( $this->fld_sha1 ) {
280 $revDel = $this->
checkRevDel( $revision, RevisionRecord::DELETED_TEXT );
281 if ( ( $revDel & self::IS_DELETED ) ) {
282 $vals[
'sha1hidden'] =
true;
285 if ( !( $revDel & self::CANNOT_VIEW ) ) {
287 $vals[
'sha1'] = Wikimedia\base_convert( $revision->
getSha1(), 36, 16, 40 );
297 if ( $this->fld_roles ) {
301 if ( $this->needSlots ) {
302 $revDel = $this->
checkRevDel( $revision, RevisionRecord::DELETED_TEXT );
303 if ( ( $this->fld_slotsha1 || $this->fetchContent ) && ( $revDel & self::IS_DELETED ) ) {
311 $vals[
'slotsmissing'] =
true;
313 LoggerFactory::getInstance(
'api-warning' )->error(
314 'Failed to access revision slots',
315 [
'revision' => $revision->
getId(),
'exception' => $ex, ]
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;
325 if ( !( $revDel & self::CANNOT_VIEW ) ) {
326 $comment = $revision->
getComment( RevisionRecord::RAW );
327 $comment = $comment ? $comment->text :
'';
329 if ( $this->fld_comment ) {
330 $vals[
'comment'] = $comment;
333 if ( $this->fld_parsedcomment ) {
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;
351 if ( $anyHidden && $revision->
isDeleted( RevisionRecord::DELETED_RESTRICTED ) ) {
352 $vals[
'suppressed'] =
true;
370 if ( $this->slotRoles ===
null ) {
372 $slot = $revision->
getSlot( SlotRecord::MAIN, RevisionRecord::RAW );
376 $vals[
'textmissing'] =
true;
383 if ( !empty( $vals[
'nosuchsection'] ) ) {
386 'apierror-nosuchsection-what',
388 $this->
msg(
'revid', $revision->
getId() )
398 $roles = array_intersect( $this->slotRoles, $revision->
getSlotRoles() );
400 ApiResult::META_KVP_MERGE =>
true,
402 foreach ( $roles as $role ) {
404 $slot = $revision->
getSlot( $role, RevisionRecord::RAW );
408 $vals[
'slots'][$role][
'missing'] =
true;
416 $vals[
'slots'][$role][
'contentmodel'] =
$content->getModel();
417 $vals[
'slots'][$role][
'contentformat'] =
$content->getDefaultFormat();
419 $vals[
'slots'][$role],
442 ApiResult::setArrayType( $vals,
'assoc' );
444 if ( $this->fld_slotsize ) {
445 $vals[
'size'] = (int)$slot->
getSize();
448 if ( $this->fld_slotsha1 ) {
449 if ( ( $revDel & self::IS_DELETED ) ) {
450 $vals[
'sha1hidden'] =
true;
452 if ( !( $revDel & self::CANNOT_VIEW ) ) {
453 if ( $slot->
getSha1() !=
'' ) {
454 $vals[
'sha1'] = Wikimedia\base_convert( $slot->
getSha1(), 36, 16, 40 );
461 if ( $this->fld_contentmodel ) {
462 $vals[
'contentmodel'] = $slot->
getModel();
466 if ( $this->fetchContent ) {
467 if ( ( $revDel & self::IS_DELETED ) ) {
468 $vals[
'texthidden'] =
true;
470 if ( !( $revDel & self::CANNOT_VIEW ) ) {
475 $vals[
'textmissing'] =
true;
480 if (
$content && $this->section !==
false ) {
483 $vals[
'nosuchsection'] =
true;
502 if ( $this->fld_parsetree || ( $this->fld_content && $this->generateXML ) ) {
505 '@phan-var WikitextContent $content';
506 $t =
$content->getText(); # note: don
't set $text
508 $parser = MediaWikiServices::getInstance()->getParser();
509 $parser->startExternalParse(
511 ParserOptions::newFromContext( $this->getContext() ),
512 Parser::OT_PREPROCESS
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();
520 // @phan-suppress-next-line PhanUndeclaredMethod
521 $xml = $dom->__toString();
523 $vals['parsetree
'] = $xml;
525 $vals['badcontentformatforparsetree
'] = true;
528 'apierror-parsetree-notwikitext-title
',
529 wfEscapeWikiText( $title->getPrefixedText() ),
532 'parsetree-notwikitext
'
537 if ( $this->fld_content ) {
540 if ( $this->expandTemplates && !$this->parseContent ) {
541 if ( $content->getModel() === CONTENT_MODEL_WIKITEXT ) {
544 $text = $content->getText();
546 $text = MediaWikiServices::getInstance()->getParser()->preprocess(
549 ParserOptions::newFromContext( $this->getContext() )
553 'apierror-templateexpansion-notwikitext
',
554 wfEscapeWikiText( $title->getPrefixedText() ),
557 $vals['badcontentformat
'] = true;
561 if ( $this->parseContent ) {
562 $po = $content->getParserOutput(
565 ParserOptions::newFromContext( $this->getContext() )
567 $text = $po->getText();
570 if ( $text === null ) {
571 $format = $this->contentFormat ?: $content->getDefaultFormat();
572 $model = $content->getModel();
574 if ( !$content->isSupportedFormat( $format ) ) {
575 $name = wfEscapeWikiText( $title->getPrefixedText() );
576 $this->addWarning( [ 'apierror-badformat
', $this->contentFormat, $model, $name ] );
577 $vals['badcontentformat
'] = true;
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;
588 if ( $text !== false ) {
589 ApiResult::setContentValue( $vals, 'content
', $text );
593 if ( $content && ( !is_null( $this->diffto ) || !is_null( $this->difftotext ) ) ) {
594 static $n = 0; // Number of uncached diffs we've had
596 if ( $n < $this->getConfig()->
get(
'APIMaxUncachedDiffs' ) ) {
600 $handler =
$content->getContentHandler();
602 if ( !is_null( $this->difftotext ) ) {
603 $model =
$title->getContentModel();
605 if ( $this->contentFormat
606 && !ContentHandler::getForModelID( $model )->isSupportedFormat( $this->contentFormat )
609 $this->addWarning( [
'apierror-badformat', $this->contentFormat, $model, $name ] );
610 $vals[
'diff'][
'badcontentformat'] =
true;
613 $difftocontent = ContentHandler::makeContent(
620 if ( $this->difftotextpst ) {
621 $popts = ParserOptions::newFromContext( $this->
getContext() );
622 $difftocontent = $difftocontent->preSaveTransform(
$title, $this->
getUser(), $popts );
625 $engine = $handler->createDifferenceEngine(
$context );
626 $engine->setContent(
$content, $difftocontent );
629 $engine = $handler->createDifferenceEngine(
$context, $revision->
getId(), $this->diffto );
630 $vals[
'diff'][
'from'] = $engine->getOldid();
631 $vals[
'diff'][
'to'] = $engine->getNewid();
634 $difftext = $engine->getDiffBody();
635 ApiResult::setContentValue( $vals[
'diff'],
'body', $difftext );
636 if ( !$engine->wasCacheHit() ) {
641 $vals[
'diff'][
'notcached'] =
true;
649 if ( $this->userCanSeeRevDel() ) {
657 $slotRoles = MediaWikiServices::getInstance()->getSlotRoleRegistry()->getKnownRoles();
658 sort( $slotRoles, SORT_STRING );
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',
719 'expandtemplates' => [
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
wfEscapeWikiText( $text)
Escapes the given text so that it may be output using addWikiText() without any linking,...
getModulePrefix()
Get parameter prefix (usually two letters or an empty string).
const PARAM_MAX2
(integer) Max value allowed for the parameter for users with the apihighlimits right,...
const PARAM_DEPRECATED
(boolean) Is the parameter deprecated (will show a warning)?
const PARAM_MAX
(integer) Max value allowed for the parameter, for PARAM_TYPE 'integer' and 'limit'.
dieWithError( $msg, $code=null, $data=null, $httpCode=null)
Abort execution with an error.
const PARAM_DEPRECATED_VALUES
(array) When PARAM_TYPE is an array, this indicates which of the values are deprecated.
getMain()
Get the main module.
const PARAM_TYPE
(string|string[]) Either an array of allowed value strings, or a string type as described below.
const PARAM_DFLT
(null|boolean|integer|string) Default value of the parameter.
const PARAM_HELP_MSG_PER_VALUE
((string|array|Message)[]) When PARAM_TYPE is an array, this is an array mapping those values to $msg...
addDeprecation( $msg, $feature, $data=[])
Add a deprecation warning for this module.
const PARAM_MIN
(integer) Lowest value allowed for the parameter, for PARAM_TYPE 'integer' and 'limit'.
const LIMIT_BIG1
Fast query, standard limit.
const LIMIT_SML2
Slow query, apihighlimits limit.
validateLimit( $paramName, &$value, $min, $max, $botMax=null, $enforceLimits=false)
Validate the value against the minimum and user/bot maximum limits.
getResult()
Get the result object.
const LIMIT_SML1
Slow query, standard limit.
const PARAM_HELP_MSG
(string|array|Message) Specify an alternative i18n documentation message for this parameter.
addWarning( $msg, $code=null, $data=null)
Add a warning for this module.
const PARAM_ALL
(boolean|string) When PARAM_TYPE has a defined set of values and PARAM_ISMULTI is true,...
const LIMIT_BIG2
Fast query, apihighlimits limit.
getModuleName()
Get the name of the module being executed by this instance.
const PARAM_ISMULTI
(boolean) Accept multiple pipe-separated values for this parameter (e.g.
This class contains a list of pages that the client has requested.
getParent()
Get the parent of this module.1.25 ApiBase|null
encodeParamName( $paramName)
Overrides ApiBase to prepend 'g' to every generator parameter.
A base class for functions common to producing a list of revisions.
executeGenerator( $resultPageSet)
Execute this module as a generator.
getCacheMode( $params)
Get the cache mode for the data generated by this module.
extractAllSlotInfo(RevisionRecord $revision, $revDel)
Extracts information about all relevant slots.
parseParameters( $params)
Parse the parameters into the various instance fields.
getAllowedParams()
Returns an array of allowed parameters (parameter name) => (default value) or (parameter name) => (ar...
extractDeprecatedContent(Content $content, RevisionRecord $revision)
Format a Content using deprecated options.
execute()
Evaluates the parameters, performs the requested query, and sets up the result.
extractSlotInfo(SlotRecord $slot, $revDel, &$content=null)
Extract information from the SlotRecord.
run(ApiPageSet $resultPageSet=null)
checkRevDel(RevisionRecord $revision, $field)
Test revision deletion status.
extractRevisionInfo(RevisionRecord $revision, $row)
Extract information from the RevisionRecord.
static setArrayType(array &$arr, $type, $kvpKeyName=null)
Set the array data type.
static setIndexedTagName(array &$arr, $tag)
Set the tag name for numeric-keyed values in XML format.
static setContentValue(array &$arr, $name, $value, $flags=0)
Add an output value to the array by name and mark as META_CONTENT.
msg( $key,... $params)
Get a Message object with context set Parameters are the same as wfMessage()
An IContextSource implementation which will inherit context from another source but allow individual ...
static formatComment( $comment, $title=null, $local=false, $wikiId=null)
This function is called by all recent changes variants, by the page history, and by the user contribu...
Content object for wiki text pages.
const CONTENT_MODEL_WIKITEXT
Base interface for content objects.