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