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