MediaWiki  master
ApiQueryRevisionsBase.php
Go to the documentation of this file.
1 <?php
35 
44 
45  // region Constants for internal use. Don't use externally.
48  // Bits to indicate the results of the revdel permission check on a revision,
49  // see self::checkRevDel()
50  private const IS_DELETED = 1; // Whether the field is revision-deleted
51  private const CANNOT_VIEW = 2; // Whether the user cannot view the field due to revdel
52 
53  // endregion
54 
58 
59  protected $fld_ids = false, $fld_flags = false, $fld_timestamp = false,
60  $fld_size = false, $fld_slotsize = false, $fld_sha1 = false, $fld_slotsha1 = false,
61  $fld_comment = false, $fld_parsedcomment = false, $fld_user = false, $fld_userid = false,
62  $fld_content = false, $fld_tags = false, $fld_contentmodel = false, $fld_roles = false,
63  $fld_parsetree = false;
64 
66  private $revisionStore;
67 
70 
72  private $parserFactory;
73 
76 
79 
82 
96  public function __construct(
97  ApiQuery $queryModule,
98  $moduleName,
99  $paramPrefix = '',
106  ) {
107  parent::__construct( $queryModule, $moduleName, $paramPrefix );
108  // This class is part of the stable interface and
109  // therefor fallback to global state, if services are not provided
110  $services = MediaWikiServices::getInstance();
111  $this->revisionStore = $revisionStore ?? $services->getRevisionStore();
112  $this->contentHandlerFactory = $contentHandlerFactory ?? $services->getContentHandlerFactory();
113  $this->parserFactory = $parserFactory ?? $services->getParserFactory();
114  $this->slotRoleRegistry = $slotRoleRegistry ?? $services->getSlotRoleRegistry();
115  $this->contentRenderer = $contentRenderer ?? $services->getContentRenderer();
116  $this->contentTransformer = $contentTransformer ?? $services->getContentTransformer();
117  }
118 
119  public function execute() {
120  $this->run();
121  }
122 
123  public function executeGenerator( $resultPageSet ) {
124  $this->run( $resultPageSet );
125  }
126 
131  abstract protected function run( ApiPageSet $resultPageSet = null );
132 
138  protected function parseParameters( $params ) {
139  $prop = array_fill_keys( $params['prop'], true );
140 
141  $this->fld_ids = isset( $prop['ids'] );
142  $this->fld_flags = isset( $prop['flags'] );
143  $this->fld_timestamp = isset( $prop['timestamp'] );
144  $this->fld_comment = isset( $prop['comment'] );
145  $this->fld_parsedcomment = isset( $prop['parsedcomment'] );
146  $this->fld_size = isset( $prop['size'] );
147  $this->fld_slotsize = isset( $prop['slotsize'] );
148  $this->fld_sha1 = isset( $prop['sha1'] );
149  $this->fld_slotsha1 = isset( $prop['slotsha1'] );
150  $this->fld_content = isset( $prop['content'] );
151  $this->fld_contentmodel = isset( $prop['contentmodel'] );
152  $this->fld_userid = isset( $prop['userid'] );
153  $this->fld_user = isset( $prop['user'] );
154  $this->fld_tags = isset( $prop['tags'] );
155  $this->fld_roles = isset( $prop['roles'] );
156  $this->fld_parsetree = isset( $prop['parsetree'] );
157 
158  $this->slotRoles = $params['slots'];
159 
160  if ( $this->slotRoles !== null ) {
161  if ( $this->fld_parsetree ) {
162  $this->dieWithError( [
163  'apierror-invalidparammix-cannotusewith',
164  $this->encodeParamName( 'prop=parsetree' ),
165  $this->encodeParamName( 'slots' ),
166  ], 'invalidparammix' );
167  }
168  foreach ( [
169  'expandtemplates', 'generatexml', 'parse', 'diffto', 'difftotext', 'difftotextpst',
170  'contentformat'
171  ] as $p ) {
172  if ( $params[$p] !== null && $params[$p] !== false ) {
173  $this->dieWithError( [
174  'apierror-invalidparammix-cannotusewith',
175  $this->encodeParamName( $p ),
176  $this->encodeParamName( 'slots' ),
177  ], 'invalidparammix' );
178  }
179  }
180  }
181 
182  if ( !empty( $params['contentformat'] ) ) {
183  $this->contentFormat = $params['contentformat'];
184  }
185 
186  $this->limit = $params['limit'];
187 
188  if ( $params['difftotext'] !== null ) {
189  $this->difftotext = $params['difftotext'];
190  $this->difftotextpst = $params['difftotextpst'];
191  } elseif ( $params['diffto'] !== null ) {
192  if ( $params['diffto'] == 'cur' ) {
193  $params['diffto'] = 0;
194  }
195  if ( ( !ctype_digit( $params['diffto'] ) || $params['diffto'] < 0 )
196  && $params['diffto'] != 'prev' && $params['diffto'] != 'next'
197  ) {
198  $p = $this->getModulePrefix();
199  $this->dieWithError( [ 'apierror-baddiffto', $p ], 'diffto' );
200  }
201  // Check whether the revision exists and is readable,
202  // DifferenceEngine returns a rather ambiguous empty
203  // string if that's not the case
204  if ( $params['diffto'] != 0 ) {
205  $difftoRev = $this->revisionStore->getRevisionById( $params['diffto'] );
206  if ( !$difftoRev ) {
207  $this->dieWithError( [ 'apierror-nosuchrevid', $params['diffto'] ] );
208  }
209  $revDel = $this->checkRevDel( $difftoRev, RevisionRecord::DELETED_TEXT );
210  if ( $revDel & self::CANNOT_VIEW ) {
211  $this->addWarning( [ 'apiwarn-difftohidden', $difftoRev->getId() ] );
212  $params['diffto'] = null;
213  }
214  }
215  $this->diffto = $params['diffto'];
216  }
217 
218  $this->fetchContent = $this->fld_content || $this->diffto !== null
219  || $this->difftotext !== null || $this->fld_parsetree;
220 
221  $smallLimit = false;
222  if ( $this->fetchContent ) {
223  $smallLimit = true;
224  $this->expandTemplates = $params['expandtemplates'];
225  $this->generateXML = $params['generatexml'];
226  $this->parseContent = $params['parse'];
227  if ( $this->parseContent ) {
228  // Must manually initialize unset limit
229  if ( $this->limit === null ) {
230  $this->limit = 1;
231  }
232  }
233  $this->section = $params['section'] ?? false;
234  }
235 
236  $userMax = $this->parseContent ? 1 : ( $smallLimit ? ApiBase::LIMIT_SML1 : ApiBase::LIMIT_BIG1 );
237  $botMax = $this->parseContent ? 1 : ( $smallLimit ? ApiBase::LIMIT_SML2 : ApiBase::LIMIT_BIG2 );
238  if ( $this->limit == 'max' ) {
239  $this->limit = $this->getMain()->canApiHighLimits() ? $botMax : $userMax;
240  if ( $this->setParsedLimit ) {
241  $this->getResult()->addParsedLimit( $this->getModuleName(), $this->limit );
242  }
243  }
244 
245  $this->limit = $this->getMain()->getParamValidator()->validateValue(
246  $this, 'limit', $this->limit ?? 10, [
247  ParamValidator::PARAM_TYPE => 'limit',
248  IntegerDef::PARAM_MIN => 1,
249  IntegerDef::PARAM_MAX => $userMax,
250  IntegerDef::PARAM_MAX2 => $botMax,
251  IntegerDef::PARAM_IGNORE_RANGE => true,
252  ]
253  );
254 
255  $this->needSlots = $this->fetchContent || $this->fld_contentmodel ||
256  $this->fld_slotsize || $this->fld_slotsha1;
257  if ( $this->needSlots && $this->slotRoles === null ) {
258  $encParam = $this->encodeParamName( 'slots' );
259  $name = $this->getModuleName();
260  $parent = $this->getParent();
261  $parentParam = $parent->encodeParamName( $parent->getModuleManager()->getModuleGroup( $name ) );
262  $this->addDeprecation(
263  [ 'apiwarn-deprecation-missingparam', $encParam ],
264  "action=query&{$parentParam}={$name}&!{$encParam}"
265  );
266  }
267  }
268 
276  private function checkRevDel( RevisionRecord $revision, $field ) {
277  $ret = $revision->isDeleted( $field ) ? self::IS_DELETED : 0;
278  if ( $ret ) {
279  $canSee = $revision->userCan( $field, $this->getAuthority() );
280  $ret |= ( $canSee ? 0 : self::CANNOT_VIEW );
281  }
282  return $ret;
283  }
284 
293  protected function extractRevisionInfo( RevisionRecord $revision, $row ) {
294  $vals = [];
295  $anyHidden = false;
296 
297  if ( $this->fld_ids ) {
298  $vals['revid'] = (int)$revision->getId();
299  if ( $revision->getParentId() !== null ) {
300  $vals['parentid'] = (int)$revision->getParentId();
301  }
302  }
303 
304  if ( $this->fld_flags ) {
305  $vals['minor'] = $revision->isMinor();
306  }
307 
308  if ( $this->fld_user || $this->fld_userid ) {
309  $revDel = $this->checkRevDel( $revision, RevisionRecord::DELETED_USER );
310  if ( $revDel & self::IS_DELETED ) {
311  $vals['userhidden'] = true;
312  $anyHidden = true;
313  }
314  if ( !( $revDel & self::CANNOT_VIEW ) ) {
315  $u = $revision->getUser( RevisionRecord::RAW );
316  if ( $this->fld_user ) {
317  $vals['user'] = $u->getName();
318  }
319  $userid = $u->getId();
320  if ( !$userid ) {
321  $vals['anon'] = true;
322  }
323 
324  if ( $this->fld_userid ) {
325  $vals['userid'] = $userid;
326  }
327  }
328  }
329 
330  if ( $this->fld_timestamp ) {
331  $vals['timestamp'] = wfTimestamp( TS_ISO_8601, $revision->getTimestamp() );
332  }
333 
334  if ( $this->fld_size ) {
335  try {
336  $vals['size'] = (int)$revision->getSize();
337  } catch ( RevisionAccessException $e ) {
338  // Back compat: If there's no size, return 0.
339  // @todo: Gergő says to mention T198099 as a "todo" here.
340  $vals['size'] = 0;
341  }
342  }
343 
344  if ( $this->fld_sha1 ) {
345  $revDel = $this->checkRevDel( $revision, RevisionRecord::DELETED_TEXT );
346  if ( $revDel & self::IS_DELETED ) {
347  $vals['sha1hidden'] = true;
348  $anyHidden = true;
349  }
350  if ( !( $revDel & self::CANNOT_VIEW ) ) {
351  try {
352  $vals['sha1'] = Wikimedia\base_convert( $revision->getSha1(), 36, 16, 40 );
353  } catch ( RevisionAccessException $e ) {
354  // Back compat: If there's no sha1, return empty string.
355  // @todo: Gergő says to mention T198099 as a "todo" here.
356  $vals['sha1'] = '';
357  }
358  }
359  }
360 
361  try {
362  if ( $this->fld_roles ) {
363  $vals['roles'] = $revision->getSlotRoles();
364  }
365 
366  if ( $this->needSlots ) {
367  $revDel = $this->checkRevDel( $revision, RevisionRecord::DELETED_TEXT );
368  if ( ( $this->fld_slotsha1 || $this->fetchContent ) && ( $revDel & self::IS_DELETED ) ) {
369  $anyHidden = true;
370  }
371  $vals = array_merge( $vals, $this->extractAllSlotInfo( $revision, $revDel ) );
372  }
373  } catch ( RevisionAccessException $ex ) {
374  // This is here so T212428 doesn't spam the log.
375  // TODO: find out why T212428 happens in the first place!
376  $vals['slotsmissing'] = true;
377 
378  LoggerFactory::getInstance( 'api-warning' )->error(
379  'Failed to access revision slots',
380  [ 'revision' => $revision->getId(), 'exception' => $ex, ]
381  );
382  }
383 
384  if ( $this->fld_comment || $this->fld_parsedcomment ) {
385  $revDel = $this->checkRevDel( $revision, RevisionRecord::DELETED_COMMENT );
386  if ( $revDel & self::IS_DELETED ) {
387  $vals['commenthidden'] = true;
388  $anyHidden = true;
389  }
390  if ( !( $revDel & self::CANNOT_VIEW ) ) {
391  $comment = $revision->getComment( RevisionRecord::RAW );
392  $comment = $comment ? $comment->text : '';
393 
394  if ( $this->fld_comment ) {
395  $vals['comment'] = $comment;
396  }
397 
398  if ( $this->fld_parsedcomment ) {
399  $vals['parsedcomment'] = Linker::formatComment(
400  $comment, Title::newFromLinkTarget( $revision->getPageAsLinkTarget() )
401  );
402  }
403  }
404  }
405 
406  if ( $this->fld_tags ) {
407  if ( $row->ts_tags ) {
408  $tags = explode( ',', $row->ts_tags );
409  ApiResult::setIndexedTagName( $tags, 'tag' );
410  $vals['tags'] = $tags;
411  } else {
412  $vals['tags'] = [];
413  }
414  }
415 
416  if ( $anyHidden && $revision->isDeleted( RevisionRecord::DELETED_RESTRICTED ) ) {
417  $vals['suppressed'] = true;
418  }
419 
420  return $vals;
421  }
422 
432  private function extractAllSlotInfo( RevisionRecord $revision, $revDel ): array {
433  $vals = [];
434 
435  if ( $this->slotRoles === null ) {
436  try {
437  $slot = $revision->getSlot( SlotRecord::MAIN, RevisionRecord::RAW );
438  } catch ( RevisionAccessException $e ) {
439  // Back compat: If there's no slot, there's no content, so set 'textmissing'
440  // @todo: Gergő says to mention T198099 as a "todo" here.
441  $vals['textmissing'] = true;
442  $slot = null;
443  }
444 
445  if ( $slot ) {
446  $content = null;
447  $vals += $this->extractSlotInfo( $slot, $revDel, $content );
448  if ( !empty( $vals['nosuchsection'] ) ) {
449  $this->dieWithError(
450  [
451  'apierror-nosuchsection-what',
452  wfEscapeWikiText( $this->section ),
453  $this->msg( 'revid', $revision->getId() )
454  ],
455  'nosuchsection'
456  );
457  }
458  if ( $content ) {
459  $vals += $this->extractDeprecatedContent( $content, $revision );
460  }
461  }
462  } else {
463  $roles = array_intersect( $this->slotRoles, $revision->getSlotRoles() );
464  $vals['slots'] = [
466  ];
467  foreach ( $roles as $role ) {
468  try {
469  $slot = $revision->getSlot( $role, RevisionRecord::RAW );
470  } catch ( RevisionAccessException $e ) {
471  // Don't error out here so the client can still process other slots/revisions.
472  // @todo: Gergő says to mention T198099 as a "todo" here.
473  $vals['slots'][$role]['missing'] = true;
474  continue;
475  }
476  $content = null;
477  $vals['slots'][$role] = $this->extractSlotInfo( $slot, $revDel, $content );
478  // @todo Move this into extractSlotInfo() (and remove its $content parameter)
479  // when extractDeprecatedContent() is no more.
480  if ( $content ) {
482  $vals['slots'][$role]['contentmodel'] = $content->getModel();
483  $vals['slots'][$role]['contentformat'] = $content->getDefaultFormat();
485  $vals['slots'][$role],
486  'content',
487  $content->serialize()
488  );
489  }
490  }
491  ApiResult::setArrayType( $vals['slots'], 'kvp', 'role' );
492  ApiResult::setIndexedTagName( $vals['slots'], 'slot' );
493  }
494  return $vals;
495  }
496 
506  private function extractSlotInfo( SlotRecord $slot, $revDel, &$content = null ) {
507  $vals = [];
508  ApiResult::setArrayType( $vals, 'assoc' );
509 
510  if ( $this->fld_slotsize ) {
511  $vals['size'] = (int)$slot->getSize();
512  }
513 
514  if ( $this->fld_slotsha1 ) {
515  if ( $revDel & self::IS_DELETED ) {
516  $vals['sha1hidden'] = true;
517  }
518  if ( !( $revDel & self::CANNOT_VIEW ) ) {
519  if ( $slot->getSha1() != '' ) {
520  $vals['sha1'] = Wikimedia\base_convert( $slot->getSha1(), 36, 16, 40 );
521  } else {
522  $vals['sha1'] = '';
523  }
524  }
525  }
526 
527  if ( $this->fld_contentmodel ) {
528  $vals['contentmodel'] = $slot->getModel();
529  }
530 
531  $content = null;
532  if ( $this->fetchContent ) {
533  if ( $revDel & self::IS_DELETED ) {
534  $vals['texthidden'] = true;
535  }
536  if ( !( $revDel & self::CANNOT_VIEW ) ) {
537  try {
538  $content = $slot->getContent();
539  } catch ( RevisionAccessException $e ) {
540  // @todo: Gergő says to mention T198099 as a "todo" here.
541  $vals['textmissing'] = true;
542  }
543  // Expand templates after getting section content because
544  // template-added sections don't count and Parser::preprocess()
545  // will have less input
546  if ( $content && $this->section !== false ) {
547  $content = $content->getSection( $this->section );
548  if ( !$content ) {
549  $vals['nosuchsection'] = true;
550  }
551  }
552  }
553  }
554 
555  return $vals;
556  }
557 
564  private function extractDeprecatedContent( Content $content, RevisionRecord $revision ) {
565  $vals = [];
567 
568  if ( $this->fld_parsetree || ( $this->fld_content && $this->generateXML ) ) {
569  if ( $content->getModel() === CONTENT_MODEL_WIKITEXT ) {
571  '@phan-var WikitextContent $content';
572  $t = $content->getText(); # note: don't set $text
573 
574  $parser = $this->parserFactory->create();
575  $parser->startExternalParse(
576  $title,
577  ParserOptions::newFromContext( $this->getContext() ),
578  Parser::OT_PREPROCESS
579  );
580  $dom = $parser->preprocessToDom( $t );
581  if ( is_callable( [ $dom, 'saveXML' ] ) ) {
582  // @phan-suppress-next-line PhanUndeclaredMethod
583  $xml = $dom->saveXML();
584  } else {
585  // @phan-suppress-next-line PhanUndeclaredMethod
586  $xml = $dom->__toString();
587  }
588  $vals['parsetree'] = $xml;
589  } else {
590  $vals['badcontentformatforparsetree'] = true;
591  $this->addWarning(
592  [
593  'apierror-parsetree-notwikitext-title',
594  wfEscapeWikiText( $title->getPrefixedText() ),
595  $content->getModel()
596  ],
597  'parsetree-notwikitext'
598  );
599  }
600  }
601 
602  if ( $this->fld_content ) {
603  $text = null;
604 
605  if ( $this->expandTemplates && !$this->parseContent ) {
606  if ( $content->getModel() === CONTENT_MODEL_WIKITEXT ) {
608  '@phan-var WikitextContent $content';
609  $text = $content->getText();
610 
611  $text = $this->parserFactory->create()->preprocess(
612  $text,
613  $title,
614  ParserOptions::newFromContext( $this->getContext() )
615  );
616  } else {
617  $this->addWarning( [
618  'apierror-templateexpansion-notwikitext',
619  wfEscapeWikiText( $title->getPrefixedText() ),
620  $content->getModel()
621  ] );
622  $vals['badcontentformat'] = true;
623  $text = false;
624  }
625  }
626  if ( $this->parseContent ) {
627  $po = $this->contentRenderer->getParserOutput(
628  $content,
629  $title,
630  $revision->getId(),
631  ParserOptions::newFromContext( $this->getContext() )
632  );
633  $text = $po->getText();
634  }
635 
636  if ( $text === null ) {
637  $format = $this->contentFormat ?: $content->getDefaultFormat();
638  $model = $content->getModel();
639 
640  if ( !$content->isSupportedFormat( $format ) ) {
641  $name = wfEscapeWikiText( $title->getPrefixedText() );
642  $this->addWarning( [ 'apierror-badformat', $this->contentFormat, $model, $name ] );
643  $vals['badcontentformat'] = true;
644  $text = false;
645  } else {
646  $text = $content->serialize( $format );
647  // always include format and model.
648  // Format is needed to deserialize, model is needed to interpret.
649  $vals['contentformat'] = $format;
650  $vals['contentmodel'] = $model;
651  }
652  }
653 
654  if ( $text !== false ) {
655  ApiResult::setContentValue( $vals, 'content', $text );
656  }
657  }
658 
659  if ( $content && ( $this->diffto !== null || $this->difftotext !== null ) ) {
660  static $n = 0; // Number of uncached diffs we've had
661 
662  if ( $n < $this->getConfig()->get( 'APIMaxUncachedDiffs' ) ) {
663  $vals['diff'] = [];
664  $context = new DerivativeContext( $this->getContext() );
665  $context->setTitle( $title );
666  $handler = $content->getContentHandler();
667 
668  if ( $this->difftotext !== null ) {
669  $model = $title->getContentModel();
670 
671  if ( $this->contentFormat
672  && !$this->contentHandlerFactory->getContentHandler( $model )
673  ->isSupportedFormat( $this->contentFormat )
674  ) {
675  $name = wfEscapeWikiText( $title->getPrefixedText() );
676  $this->addWarning( [ 'apierror-badformat', $this->contentFormat, $model, $name ] );
677  $vals['diff']['badcontentformat'] = true;
678  $engine = null;
679  } else {
680  $difftocontent = ContentHandler::makeContent(
681  $this->difftotext,
682  $title,
683  $model,
684  $this->contentFormat
685  );
686 
687  if ( $this->difftotextpst ) {
688  $popts = ParserOptions::newFromContext( $this->getContext() );
689  $difftocontent = $this->contentTransformer->preSaveTransform(
690  $difftocontent,
691  $title,
692  $this->getUser(),
693  $popts
694  );
695  }
696 
697  $engine = $handler->createDifferenceEngine( $context );
698  $engine->setContent( $content, $difftocontent );
699  }
700  } else {
701  $engine = $handler->createDifferenceEngine( $context, $revision->getId(), $this->diffto );
702  $vals['diff']['from'] = $engine->getOldid();
703  $vals['diff']['to'] = $engine->getNewid();
704  }
705  if ( $engine ) {
706  $difftext = $engine->getDiffBody();
707  ApiResult::setContentValue( $vals['diff'], 'body', $difftext );
708  if ( !$engine->wasCacheHit() ) {
709  $n++;
710  }
711  }
712  } else {
713  $vals['diff']['notcached'] = true;
714  }
715  }
716 
717  return $vals;
718  }
719 
726  public function getCacheMode( $params ) {
727  if ( $this->userCanSeeRevDel() ) {
728  return 'private';
729  }
730 
731  return 'public';
732  }
733 
739  public function getAllowedParams() {
740  $slotRoles = $this->slotRoleRegistry->getKnownRoles();
741  sort( $slotRoles, SORT_STRING );
742 
743  return [
744  'prop' => [
745  ApiBase::PARAM_ISMULTI => true,
746  ApiBase::PARAM_DFLT => 'ids|timestamp|flags|comment|user',
748  'ids',
749  'flags',
750  'timestamp',
751  'user',
752  'userid',
753  'size',
754  'slotsize',
755  'sha1',
756  'slotsha1',
757  'contentmodel',
758  'comment',
759  'parsedcomment',
760  'content',
761  'tags',
762  'roles',
763  'parsetree',
764  ],
765  ApiBase::PARAM_HELP_MSG => 'apihelp-query+revisions+base-param-prop',
767  'ids' => 'apihelp-query+revisions+base-paramvalue-prop-ids',
768  'flags' => 'apihelp-query+revisions+base-paramvalue-prop-flags',
769  'timestamp' => 'apihelp-query+revisions+base-paramvalue-prop-timestamp',
770  'user' => 'apihelp-query+revisions+base-paramvalue-prop-user',
771  'userid' => 'apihelp-query+revisions+base-paramvalue-prop-userid',
772  'size' => 'apihelp-query+revisions+base-paramvalue-prop-size',
773  'slotsize' => 'apihelp-query+revisions+base-paramvalue-prop-slotsize',
774  'sha1' => 'apihelp-query+revisions+base-paramvalue-prop-sha1',
775  'slotsha1' => 'apihelp-query+revisions+base-paramvalue-prop-slotsha1',
776  'contentmodel' => 'apihelp-query+revisions+base-paramvalue-prop-contentmodel',
777  'comment' => 'apihelp-query+revisions+base-paramvalue-prop-comment',
778  'parsedcomment' => 'apihelp-query+revisions+base-paramvalue-prop-parsedcomment',
779  'content' => 'apihelp-query+revisions+base-paramvalue-prop-content',
780  'tags' => 'apihelp-query+revisions+base-paramvalue-prop-tags',
781  'roles' => 'apihelp-query+revisions+base-paramvalue-prop-roles',
782  'parsetree' => [ 'apihelp-query+revisions+base-paramvalue-prop-parsetree',
784  ],
786  'parsetree' => true,
787  ],
788  ],
789  'slots' => [
791  ApiBase::PARAM_HELP_MSG => 'apihelp-query+revisions+base-param-slots',
792  ApiBase::PARAM_ISMULTI => true,
793  ApiBase::PARAM_ALL => true,
794  ],
795  'limit' => [
796  ApiBase::PARAM_TYPE => 'limit',
797  ApiBase::PARAM_MIN => 1,
800  ApiBase::PARAM_HELP_MSG => 'apihelp-query+revisions+base-param-limit',
801  ],
802  'expandtemplates' => [
803  ApiBase::PARAM_DFLT => false,
804  ApiBase::PARAM_HELP_MSG => 'apihelp-query+revisions+base-param-expandtemplates',
806  ],
807  'generatexml' => [
808  ApiBase::PARAM_DFLT => false,
810  ApiBase::PARAM_HELP_MSG => 'apihelp-query+revisions+base-param-generatexml',
811  ],
812  'parse' => [
813  ApiBase::PARAM_DFLT => false,
814  ApiBase::PARAM_HELP_MSG => 'apihelp-query+revisions+base-param-parse',
816  ],
817  'section' => [
818  ApiBase::PARAM_HELP_MSG => 'apihelp-query+revisions+base-param-section',
819  ],
820  'diffto' => [
821  ApiBase::PARAM_HELP_MSG => 'apihelp-query+revisions+base-param-diffto',
823  ],
824  'difftotext' => [
825  ApiBase::PARAM_HELP_MSG => 'apihelp-query+revisions+base-param-difftotext',
827  ],
828  'difftotextpst' => [
829  ApiBase::PARAM_DFLT => false,
830  ApiBase::PARAM_HELP_MSG => 'apihelp-query+revisions+base-param-difftotextpst',
832  ],
833  'contentformat' => [
834  ApiBase::PARAM_TYPE => $this->contentHandlerFactory->getAllContentFormats(),
835  ApiBase::PARAM_HELP_MSG => 'apihelp-query+revisions+base-param-contentformat',
837  ],
838  ];
839  }
840 }
ApiQueryRevisionsBase\parseParameters
parseParameters( $params)
Parse the parameters into the various instance fields.
Definition: ApiQueryRevisionsBase.php:138
ContextSource\$context
IContextSource $context
Definition: ContextSource.php:39
ContextSource\getConfig
getConfig()
Definition: ContextSource.php:72
MediaWiki\Revision\RevisionAccessException
Exception representing a failure to look up a revision.
Definition: RevisionAccessException.php:37
MediaWiki\Revision\RevisionRecord\getUser
getUser( $audience=self::FOR_PUBLIC, Authority $performer=null)
Fetch revision's author's user identity, if it's available to the specified audience.
Definition: RevisionRecord.php:389
ContextSource\getContext
getContext()
Get the base IContextSource object.
Definition: ContextSource.php:47
ApiQuery
This is the main query class.
Definition: ApiQuery.php:39
MediaWiki\Revision\RevisionRecord
Page revision base class.
Definition: RevisionRecord.php:47
ApiBase\addWarning
addWarning( $msg, $code=null, $data=null)
Add a warning for this module.
Definition: ApiBase.php:1354
ApiQueryRevisionsBase\$fld_slotsize
$fld_slotsize
Definition: ApiQueryRevisionsBase.php:60
ApiQueryGeneratorBase\encodeParamName
encodeParamName( $paramName)
Overrides ApiBase to prepend 'g' to every generator parameter.
Definition: ApiQueryGeneratorBase.php:70
ApiQueryRevisionsBase\$contentHandlerFactory
IContentHandlerFactory $contentHandlerFactory
Definition: ApiQueryRevisionsBase.php:69
ApiQueryRevisionsBase\$fld_comment
$fld_comment
Definition: ApiQueryRevisionsBase.php:61
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:204
MediaWiki\Revision\RevisionStore
Service for looking up page revisions.
Definition: RevisionStore.php:89
ApiQueryBase\getParent
getParent()
Get the parent of this module.Stability: stableto override 1.25 ApiBase|null
Definition: ApiQueryBase.php:108
ApiBase\dieWithError
dieWithError( $msg, $code=null, $data=null, $httpCode=null)
Abort execution with an error.
Definition: ApiBase.php:1436
ApiBase\PARAM_HELP_MSG
const PARAM_HELP_MSG
(string|array|Message) Specify an alternative i18n documentation message for this parameter.
Definition: ApiBase.php:162
ApiBase\PARAM_ALL
const PARAM_ALL
Definition: ApiBase.php:117
ApiQueryRevisionsBase\$fld_roles
$fld_roles
Definition: ApiQueryRevisionsBase.php:62
ApiQueryRevisionsBase\$section
$section
Definition: ApiQueryRevisionsBase.php:56
wfTimestamp
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
Definition: GlobalFunctions.php:1649
ApiQueryRevisionsBase\CANNOT_VIEW
const CANNOT_VIEW
Definition: ApiQueryRevisionsBase.php:51
ApiQueryRevisionsBase\extractAllSlotInfo
extractAllSlotInfo(RevisionRecord $revision, $revDel)
Extracts information about all relevant slots.
Definition: ApiQueryRevisionsBase.php:432
ApiBase\PARAM_TYPE
const PARAM_TYPE
Definition: ApiBase.php:81
ApiBase\getResult
getResult()
Get the result object.
Definition: ApiBase.php:628
ApiQueryRevisionsBase\$fld_userid
$fld_userid
Definition: ApiQueryRevisionsBase.php:61
MediaWiki\Revision\RevisionRecord\isMinor
isMinor()
MCR migration note: this replaced Revision::isMinor.
Definition: RevisionRecord.php:426
ApiQueryRevisionsBase\$fld_sha1
$fld_sha1
Definition: ApiQueryRevisionsBase.php:60
MediaWiki\Revision\RevisionRecord\getSha1
getSha1()
Returns the base36 sha1 of this revision.
MediaWiki\Revision\SlotRecord\getSha1
getSha1()
Returns the content size.
Definition: SlotRecord.php:556
ApiQueryRevisionsBase\$fetchContent
$fetchContent
Definition: ApiQueryRevisionsBase.php:56
ApiQueryRevisionsBase\$setParsedLimit
$setParsedLimit
Definition: ApiQueryRevisionsBase.php:56
ApiQueryRevisionsBase\$slotRoles
$slotRoles
Definition: ApiQueryRevisionsBase.php:57
ContextSource\getUser
getUser()
Definition: ContextSource.php:136
ApiBase\PARAM_DEPRECATED_VALUES
const PARAM_DEPRECATED_VALUES
Definition: ApiBase.php:129
ApiQueryRevisionsBase\$difftotextpst
$difftotextpst
Definition: ApiQueryRevisionsBase.php:55
ApiPageSet
This class contains a list of pages that the client has requested.
Definition: ApiPageSet.php:45
ApiQueryRevisionsBase\$limit
$limit
Definition: ApiQueryRevisionsBase.php:55
ApiQueryRevisionsBase\$fld_content
$fld_content
Definition: ApiQueryRevisionsBase.php:62
ApiResult\setContentValue
static setContentValue(array &$arr, $name, $value, $flags=0)
Add an output value to the array by name and mark as META_CONTENT.
Definition: ApiResult.php:467
ApiQueryRevisionsBase\$fld_contentmodel
$fld_contentmodel
Definition: ApiQueryRevisionsBase.php:62
ApiQueryRevisionsBase
A base class for functions common to producing a list of revisions.
Definition: ApiQueryRevisionsBase.php:43
ApiQueryRevisionsBase\$fld_slotsha1
$fld_slotsha1
Definition: ApiQueryRevisionsBase.php:60
ApiBase\PARAM_DEPRECATED
const PARAM_DEPRECATED
Definition: ApiBase.php:101
ApiBase\PARAM_MIN
const PARAM_MIN
Definition: ApiBase.php:93
DerivativeContext
An IContextSource implementation which will inherit context from another source but allow individual ...
Definition: DerivativeContext.php:32
ApiQueryRevisionsBase\$expandTemplates
$expandTemplates
Definition: ApiQueryRevisionsBase.php:55
ApiResult\setArrayType
static setArrayType(array &$arr, $type, $kvpKeyName=null)
Set the array data type.
Definition: ApiResult.php:716
ApiQueryRevisionsBase\$contentRenderer
ContentRenderer $contentRenderer
Definition: ApiQueryRevisionsBase.php:78
ApiQueryRevisionsBase\$contentFormat
$contentFormat
Definition: ApiQueryRevisionsBase.php:56
MediaWiki\Logger\LoggerFactory
PSR-3 logger instance factory.
Definition: LoggerFactory.php:45
ApiBase\LIMIT_BIG1
const LIMIT_BIG1
Fast query, standard limit.
Definition: ApiBase.php:220
ApiQueryRevisionsBase\getAllowedParams
getAllowedParams()
Definition: ApiQueryRevisionsBase.php:739
ApiBase\PARAM_MAX
const PARAM_MAX
Definition: ApiBase.php:85
MediaWiki\Content\Transform\ContentTransformer
A service to transform content.
Definition: ContentTransformer.php:15
$title
$title
Definition: testCompression.php:38
ApiQueryRevisionsBase\$diffto
$diffto
Definition: ApiQueryRevisionsBase.php:55
MediaWiki\Revision\RevisionRecord\getComment
getComment( $audience=self::FOR_PUBLIC, Authority $performer=null)
Fetch revision comment, if it's available to the specified audience.
Definition: RevisionRecord.php:413
WikitextContent
Content object for wiki text pages.
Definition: WikitextContent.php:36
ApiQueryRevisionsBase\$fld_parsetree
$fld_parsetree
Definition: ApiQueryRevisionsBase.php:63
ApiQueryRevisionsBase\execute
execute()
Definition: ApiQueryRevisionsBase.php:119
MediaWiki\Content\Renderer\ContentRenderer
A service to render content.
Definition: ContentRenderer.php:15
ApiQueryRevisionsBase\IS_DELETED
const IS_DELETED
Definition: ApiQueryRevisionsBase.php:50
ApiQueryRevisionsBase\$fld_tags
$fld_tags
Definition: ApiQueryRevisionsBase.php:62
ApiQueryRevisionsBase\$needSlots
$needSlots
Definition: ApiQueryRevisionsBase.php:57
ContentHandler\makeContent
static makeContent( $text, Title $title=null, $modelId=null, $format=null)
Convenience function for creating a Content object from a given textual representation.
Definition: ContentHandler.php:149
ApiQueryRevisionsBase\checkRevDel
checkRevDel(RevisionRecord $revision, $field)
Test revision deletion status.
Definition: ApiQueryRevisionsBase.php:276
ApiBase\getModulePrefix
getModulePrefix()
Get parameter prefix (usually two letters or an empty string).
Definition: ApiBase.php:505
ContextSource\msg
msg( $key,... $params)
Get a Message object with context set Parameters are the same as wfMessage()
Definition: ContextSource.php:197
MediaWiki\Revision\RevisionRecord\getParentId
getParentId( $wikiId=self::LOCAL)
Get parent revision ID (the original previous page revision).
Definition: RevisionRecord.php:297
ApiResult\setIndexedTagName
static setIndexedTagName(array &$arr, $tag)
Set the tag name for numeric-keyed values in XML format.
Definition: ApiResult.php:604
ParserFactory
Definition: ParserFactory.php:37
$content
$content
Definition: router.php:76
ApiQueryRevisionsBase\$parseContent
$parseContent
Definition: ApiQueryRevisionsBase.php:56
ApiQueryRevisionsBase\$parserFactory
ParserFactory $parserFactory
Definition: ApiQueryRevisionsBase.php:72
ParserOptions\newFromContext
static newFromContext(IContextSource $context)
Get a ParserOptions object from a IContextSource object.
Definition: ParserOptions.php:1065
ApiBase\addDeprecation
addDeprecation( $msg, $feature, $data=[])
Add a deprecation warning for this module.
Definition: ApiBase.php:1368
MediaWiki\Content\IContentHandlerFactory
Definition: IContentHandlerFactory.php:10
ContextSource\getAuthority
getAuthority()
Definition: ContextSource.php:144
ApiBase\LIMIT_SML2
const LIMIT_SML2
Slow query, apihighlimits limit.
Definition: ApiBase.php:226
MediaWiki\Revision\RevisionRecord\getPageAsLinkTarget
getPageAsLinkTarget()
Returns the title of the page this revision is associated with as a LinkTarget object.
Definition: RevisionRecord.php:355
ApiQueryRevisionsBase\extractRevisionInfo
extractRevisionInfo(RevisionRecord $revision, $row)
Extract information from the RevisionRecord.
Definition: ApiQueryRevisionsBase.php:293
wfEscapeWikiText
wfEscapeWikiText( $text)
Escapes the given text so that it may be output using addWikiText() without any linking,...
Definition: GlobalFunctions.php:1440
ApiQueryRevisionsBase\$slotRoleRegistry
SlotRoleRegistry $slotRoleRegistry
Definition: ApiQueryRevisionsBase.php:75
CONTENT_MODEL_WIKITEXT
const CONTENT_MODEL_WIKITEXT
Definition: Defines.php:208
ApiQueryRevisionsBase\getCacheMode
getCacheMode( $params)
Definition: ApiQueryRevisionsBase.php:726
ApiQueryRevisionsBase\$fld_flags
$fld_flags
Definition: ApiQueryRevisionsBase.php:59
Title\newFromLinkTarget
static newFromLinkTarget(LinkTarget $linkTarget, $forceClone='')
Returns a Title given a LinkTarget.
Definition: Title.php:289
Linker\formatComment
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...
Definition: Linker.php:1413
Content
Base interface for content objects.
Definition: Content.php:35
ApiQueryRevisionsBase\$difftotext
$difftotext
Definition: ApiQueryRevisionsBase.php:55
ApiQueryGeneratorBase
Definition: ApiQueryGeneratorBase.php:28
MediaWiki\Revision\RevisionRecord\getSlotRoles
getSlotRoles()
Returns the slot names (roles) of all slots present in this revision.
Definition: RevisionRecord.php:207
ApiQueryRevisionsBase\$fld_ids
$fld_ids
Definition: ApiQueryRevisionsBase.php:59
MediaWiki\Revision\SlotRecord\getSize
getSize()
Returns the content size.
Definition: SlotRecord.php:540
Wikimedia\ParamValidator\TypeDef\IntegerDef
Type definition for integer types.
Definition: IntegerDef.php:23
ApiBase\LIMIT_BIG2
const LIMIT_BIG2
Fast query, apihighlimits limit.
Definition: ApiBase.php:222
MediaWiki\Revision\RevisionRecord\getId
getId( $wikiId=self::LOCAL)
Get revision ID.
Definition: RevisionRecord.php:279
MediaWiki\Revision\RevisionRecord\isDeleted
isDeleted( $field)
MCR migration note: this replaced Revision::isDeleted.
Definition: RevisionRecord.php:437
ApiQueryRevisionsBase\$contentTransformer
ContentTransformer $contentTransformer
Definition: ApiQueryRevisionsBase.php:81
ApiBase\PARAM_DFLT
const PARAM_DFLT
Definition: ApiBase.php:73
MediaWiki\Revision\RevisionRecord\userCan
userCan( $field, Authority $performer)
Determine if the give authority is allowed to view a particular field of this revision,...
Definition: RevisionRecord.php:509
ApiBase\getModuleName
getModuleName()
Get the name of the module being executed by this instance.
Definition: ApiBase.php:497
ApiQueryRevisionsBase\$fld_user
$fld_user
Definition: ApiQueryRevisionsBase.php:61
ApiBase\PARAM_ISMULTI
const PARAM_ISMULTI
Definition: ApiBase.php:77
MediaWiki\Revision\RevisionRecord\getTimestamp
getTimestamp()
MCR migration note: this replaced Revision::getTimestamp.
Definition: RevisionRecord.php:459
ApiQueryRevisionsBase\$fld_timestamp
$fld_timestamp
Definition: ApiQueryRevisionsBase.php:59
ApiQueryRevisionsBase\$revisionStore
RevisionStore $revisionStore
Definition: ApiQueryRevisionsBase.php:66
ApiBase\PARAM_MAX2
const PARAM_MAX2
Definition: ApiBase.php:89
ApiQueryRevisionsBase\__construct
__construct(ApiQuery $queryModule, $moduleName, $paramPrefix='', RevisionStore $revisionStore=null, IContentHandlerFactory $contentHandlerFactory=null, ParserFactory $parserFactory=null, SlotRoleRegistry $slotRoleRegistry=null, ContentRenderer $contentRenderer=null, ContentTransformer $contentTransformer=null)
Definition: ApiQueryRevisionsBase.php:96
MediaWiki\Revision\RevisionRecord\getSize
getSize()
Returns the nominal size of this revision, in bogo-bytes.
MediaWiki\Revision\SlotRoleRegistry
A registry service for SlotRoleHandlers, used to define which slot roles are available on which page.
Definition: SlotRoleRegistry.php:48
ApiBase\getMain
getMain()
Get the main module.
Definition: ApiBase.php:513
ApiResult\META_KVP_MERGE
const META_KVP_MERGE
Key for the metadata item that indicates that the KVP key should be added into an assoc value,...
Definition: ApiResult.php:129
ApiQueryRevisionsBase\executeGenerator
executeGenerator( $resultPageSet)
Definition: ApiQueryRevisionsBase.php:123
$t
$t
Definition: testCompression.php:74
ApiQueryRevisionsBase\$fld_parsedcomment
$fld_parsedcomment
Definition: ApiQueryRevisionsBase.php:61
ApiQueryRevisionsBase\run
run(ApiPageSet $resultPageSet=null)
ApiBase\PARAM_HELP_MSG_PER_VALUE
const PARAM_HELP_MSG_PER_VALUE
((string|array|Message)[]) When PARAM_TYPE is an array, this is an array mapping those values to $msg...
Definition: ApiBase.php:195
ApiQueryBase\userCanSeeRevDel
userCanSeeRevDel()
Check whether the current user has permission to view revision-deleted fields.
Definition: ApiQueryBase.php:607
ApiQueryRevisionsBase\$fld_size
$fld_size
Definition: ApiQueryRevisionsBase.php:60
MediaWiki\Revision\SlotRecord\getContent
getContent()
Returns the Content of the given slot.
Definition: SlotRecord.php:317
MediaWiki\Revision\SlotRecord\getModel
getModel()
Returns the content model.
Definition: SlotRecord.php:584
Wikimedia\ParamValidator\ParamValidator
Service for formatting and validating API parameters.
Definition: ParamValidator.php:42
ApiQueryRevisionsBase\extractDeprecatedContent
extractDeprecatedContent(Content $content, RevisionRecord $revision)
Format a Content using deprecated options.
Definition: ApiQueryRevisionsBase.php:564
ApiQueryRevisionsBase\extractSlotInfo
extractSlotInfo(SlotRecord $slot, $revDel, &$content=null)
Extract information from the SlotRecord.
Definition: ApiQueryRevisionsBase.php:506
MediaWiki\Revision\RevisionRecord\getSlot
getSlot( $role, $audience=self::FOR_PUBLIC, Authority $performer=null)
Returns meta-data for the given slot.
Definition: RevisionRecord.php:180
MediaWiki\Revision\SlotRecord
Value object representing a content slot associated with a page revision.
Definition: SlotRecord.php:40
ApiBase\LIMIT_SML1
const LIMIT_SML1
Slow query, standard limit.
Definition: ApiBase.php:224
ApiQueryRevisionsBase\$generateXML
$generateXML
Definition: ApiQueryRevisionsBase.php:55