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