28use MediaWiki\HookContainer\ProtectedHookAccessorTrait;
58use Wikimedia\NonSerializable\NonSerializableTrait;
71 use ProtectedHookAccessorTrait;
72 use NonSerializableTrait;
100 private $fetchResult =
null;
114 protected $viewIsRenderAction =
false;
135 private $mRevisionRecord =
null;
142 $this->mOldId = $oldId;
143 $this->mPage = $this->
newPage( $title );
145 $services = MediaWikiServices::getInstance();
146 $this->linkRenderer = $services->getLinkRenderer();
147 $this->revisionStore = $services->getRevisionStore();
148 $this->userNameUtils = $services->getUserNameUtils();
149 $this->userOptionsLookup = $services->getUserOptionsLookup();
150 $this->commentFormatter = $services->getCommentFormatter();
151 $this->wikiPageFactory = $services->getWikiPageFactory();
152 $this->jobQueueGroup = $services->getJobQueueGroup();
153 $this->archivedRevisionLookup = $services->getArchivedRevisionLookup();
154 $this->dbProvider = $services->getConnectionProvider();
155 $this->blockStore = $services->getDatabaseBlockStore();
156 $this->restrictionStore = $services->getRestrictionStore();
173 $t = Title::newFromID( $id );
174 return $t ===
null ? null :
new static( $t );
187 $title = Title::makeTitle(
NS_FILE, $title->getDBkey() );
191 (
new HookRunner( MediaWikiServices::getInstance()->getHookContainer() ) )
193 ->onArticleFromTitle( $title, $page, $context );
195 switch ( $title->getNamespace() ) {
206 $page->setContext( $context );
219 $article = self::newFromTitle( $page->
getTitle(), $context );
220 $article->mPage = $page;
230 return $this->mRedirectedFrom;
238 $this->mRedirectedFrom = $from;
247 return $this->mPage->getTitle();
261 $this->mRedirectedFrom =
null; #
Title object if set
262 $this->mRedirectUrl =
false;
263 $this->mRevisionRecord =
null;
264 $this->fetchResult =
null;
268 $this->mPage->clear();
279 if ( $this->mOldId ===
null ) {
280 $this->mOldId = $this->getOldIDFromRequest();
283 return $this->mOldId;
292 $this->mRedirectUrl =
false;
294 $request = $this->getContext()->getRequest();
295 $oldid = $request->getIntOrNull(
'oldid' );
297 if ( $oldid ===
null ) {
301 if ( $oldid !== 0 ) {
302 # Load the given revision and check whether the page is another one.
303 # In that case, update this instance to reflect the change.
304 if ( $oldid === $this->mPage->getLatest() ) {
305 $this->mRevisionRecord = $this->mPage->getRevisionRecord();
307 $this->mRevisionRecord = $this->revisionStore->getRevisionById( $oldid );
308 if ( $this->mRevisionRecord !==
null ) {
309 $revPageId = $this->mRevisionRecord->getPageId();
311 if ( $this->mPage->getId() !== $revPageId ) {
312 $this->mPage = $this->wikiPageFactory->newFromID( $revPageId );
318 $oldRev = $this->mRevisionRecord;
319 if ( $request->getRawVal(
'direction' ) ===
'next' ) {
322 $nextRev = $this->revisionStore->getNextRevision( $oldRev );
324 $nextid = $nextRev->getId();
329 $this->mRevisionRecord =
null;
331 $this->mRedirectUrl = $this->
getTitle()->getFullURL(
'redirect=no' );
333 } elseif ( $request->getRawVal(
'direction' ) ===
'prev' ) {
336 $prevRev = $this->revisionStore->getPreviousRevision( $oldRev );
338 $previd = $prevRev->getId();
343 $this->mRevisionRecord =
null;
360 if ( $this->fetchResult ) {
361 return $this->mRevisionRecord;
364 $oldid = $this->getOldID();
367 if ( !$this->mRevisionRecord ) {
369 $this->mRevisionRecord = $this->mPage->getRevisionRecord();
371 if ( !$this->mRevisionRecord ) {
372 wfDebug( __METHOD__ .
" failed to find page data for title " .
373 $this->
getTitle()->getPrefixedText() );
376 $this->fetchResult = Status::newFatal(
'noarticletext' );
380 $this->mRevisionRecord = $this->revisionStore->getRevisionById( $oldid );
382 if ( !$this->mRevisionRecord ) {
383 wfDebug( __METHOD__ .
" failed to load revision, rev_id $oldid" );
385 $this->fetchResult = Status::newFatal( $this->getMissingRevisionMsg( $oldid ) );
391 if ( !$this->mRevisionRecord->userCan( RevisionRecord::DELETED_TEXT, $this->getContext()->getAuthority() ) ) {
392 wfDebug( __METHOD__ .
" failed to retrieve content of revision " . $this->mRevisionRecord->getId() );
396 $this->fetchResult =
new Status;
397 $title = $this->
getTitle()->getPrefixedDBkey();
399 if ( $this->mRevisionRecord->isDeleted( RevisionRecord::DELETED_RESTRICTED ) ) {
400 $this->fetchResult->
fatal(
'rev-suppressed-text' );
402 $this->fetchResult->fatal(
'rev-deleted-text-permission', $title );
408 $this->fetchResult = Status::newGood( $this->mRevisionRecord );
409 return $this->mRevisionRecord;
418 # If no oldid, this is the current version.
419 if ( $this->getOldID() == 0 ) {
423 return $this->mPage->exists() &&
424 $this->mRevisionRecord &&
425 $this->mRevisionRecord->isCurrent();
437 if ( $this->fetchResult && $this->fetchResult->isOK() ) {
439 $rev = $this->fetchResult->getValue();
440 return $rev->
getId();
442 return $this->mPage->getLatest();
451 $context = $this->getContext();
452 $useFileCache = $context->getConfig()->get( MainConfigNames::UseFileCache );
454 # Get variables from query string
455 # As side effect this will load the revision and update the title
456 # in a revision ID is passed in the request, so this should remain
457 # the first call of this method even if $oldid is used way below.
458 $oldid = $this->getOldID();
460 $authority = $context->getAuthority();
461 # Another check in case getOldID() is altering the title
462 $permissionStatus = PermissionStatus::newEmpty();
464 ->authorizeRead(
'read', $this->
getTitle(), $permissionStatus )
466 wfDebug( __METHOD__ .
": denied on secondary read check" );
471 # getOldID() may as well want us to redirect somewhere else
472 if ( $this->mRedirectUrl ) {
473 $outputPage->
redirect( $this->mRedirectUrl );
474 wfDebug( __METHOD__ .
": redirecting due to oldid" );
479 # If we got diff in the query, we want to see a diff page instead of the article.
480 if ( $context->getRequest()->getCheck(
'diff' ) ) {
481 wfDebug( __METHOD__ .
": showing diff page" );
482 $this->showDiffPage();
487 $this->showProtectionIndicator();
489 # Set page title (may be overridden from ParserOutput if title conversion is enabled or DISPLAYTITLE is used)
491 str_replace(
'_',
' ', $this->
getTitle()->getNsText() ),
497 # Allow frames by default
498 $outputPage->
getMetadata()->setPreventClickjacking(
false );
500 $parserOptions = $this->getParserOptions();
503 # Allow extensions to vary parser options used for article rendering
504 (
new HookRunner( MediaWikiServices::getInstance()->getHookContainer() ) )
505 ->onArticleParserOptions( $this, $parserOptions );
506 # Render printable version, use printable version cache
509 $poOptions[
'enableSectionEditLinks'] =
false;
510 $this->addMessageBoxStyles( $outputPage );
513 $outputPage->
msg(
'printableversion-deprecated-warning' )->escaped()
516 } elseif ( $this->viewIsRenderAction || !$this->isCurrent() ||
517 !$authority->probablyCan(
'edit', $this->getTitle() )
519 $poOptions[
'enableSectionEditLinks'] =
false;
522 # Try client and file cache
523 if ( $oldid === 0 && $this->mPage->checkTouched() ) {
524 # Try to stream the output from file cache
525 if ( $useFileCache && $this->tryFileCache() ) {
526 wfDebug( __METHOD__ .
": done file cache" );
527 # tell wgOut that output is taken care of
529 $this->mPage->doViewUpdates( $authority, $oldid );
535 $this->showRedirectedFromHeader();
536 $this->showNamespaceHeader();
538 if ( $this->viewIsRenderAction ) {
539 $poOptions += [
'absoluteURLs' => true ];
541 $poOptions += [
'includeDebugInfo' => true ];
545 $this->generateContentOutput( $authority, $parserOptions, $oldid, $outputPage, $poOptions );
548 $this->showViewError(
wfMessage(
'badrevision' )->text() );
555 # For the main page, overwrite the <title> element with the con-
556 # tents of 'pagetitle-view-mainpage' instead of the default (if
558 # This message always exists because it is in the i18n files
559 if ( $this->
getTitle()->isMainPage() ) {
560 $msg = $context->msg(
'pagetitle-view-mainpage' )->inContentLanguage();
561 if ( !$msg->isDisabled() ) {
571 $outputPage->
adaptCdnTTL( $this->mPage->getTimestamp(), 86_400 );
573 $this->showViewFooter();
574 $this->mPage->doViewUpdates( $authority, $oldid, $this->fetchRevisionRecord() );
576 # Load the postEdit module if the user just saved this revision
577 # See also EditPage::setPostEditCookie
578 $request = $context->getRequest();
579 $cookieKey = EditPage::POST_EDIT_COOKIE_KEY_PREFIX . $this->getRevIdFetched();
580 $postEdit = $request->getCookie( $cookieKey );
582 # Clear the cookie. This also prevents caching of the response.
583 $request->response()->clearCookie( $cookieKey );
585 $outputPage->
addModules(
'mediawiki.action.view.postEdit' );
586 if ( $this->getContext()->getConfig()->
get( MainConfigNames::EnableEditRecovery )
587 && $this->userOptionsLookup->getOption( $this->getContext()->getUser(),
'editrecovery' )
589 $outputPage->
addModules(
'mediawiki.editRecovery.postEdit' );
599 $context = $this->getContext();
602 $protectionIndicatorsAreEnabled = $context->getConfig()
603 ->get( MainConfigNames::EnableProtectionIndicators );
605 if ( !$protectionIndicatorsAreEnabled || $title->isMainPage() ) {
609 $protection = $this->restrictionStore->getRestrictions( $title,
'edit' );
611 $cascadeProtection = $this->restrictionStore->getCascadeProtectionSources( $title )[1];
613 $isCascadeProtected = array_key_exists(
'edit', $cascadeProtection );
615 if ( !$protection && !$isCascadeProtected ) {
619 if ( $isCascadeProtected ) {
623 $protectionLevel = $cascadeProtection[
'edit'][0];
625 $protectionLevel = $protection[0];
632 $protectionLevel = htmlspecialchars( $protectionLevel );
634 $protectionExpiry = $this->restrictionStore->getRestrictionExpiry( $title,
'edit' );
635 $formattedProtectionExpiry = $context->getLanguage()
636 ->formatExpiry( $protectionExpiry ??
'' );
638 $protectionMsg =
'protection-indicator-title';
639 if ( $protectionExpiry ===
'infinity' || !$protectionExpiry ) {
640 $protectionMsg .=
'-infinity';
648 $protectionIndicatorId =
'protection-' . $protectionLevel;
649 $protectionIndicatorId .= ( $isCascadeProtected ?
'-cascade' :
'' );
652 $protectionMsg = $outputPage->
msg( $protectionMsg, $protectionLevel, $formattedProtectionExpiry )->text();
656 $protectionHelpLink = $outputPage->
msg( $protectionIndicatorId .
'-helppage' );
657 if ( $protectionHelpLink->isDisabled() ) {
658 $protectionHelpLink =
'https://mediawiki.org/wiki/Special:MyLanguage/Help:Protection';
660 $protectionHelpLink = $protectionHelpLink->text();
664 $protectionIndicatorId => Html::rawElement(
'a', [
665 'class' =>
'mw-protection-indicator-icon--lock',
666 'title' => $protectionMsg,
667 'href' => $protectionHelpLink
671 Html::element(
'span', [], $protectionMsg ) )
674 $outputPage->
addModuleStyles(
'mediawiki.protectionIndicators.styles' );
689 private function generateContentOutput(
696 # Should the parser cache be used?
697 $useParserCache = true;
699 $parserOutputAccess = MediaWikiServices::getInstance()->getParserOutputAccess();
702 $this->getHookRunner()->onArticleViewHeader( $this, $outputDone, $useParserCache );
705 $pOutput = $outputDone;
709 $this->doOutputMetaData( $pOutput, $outputPage );
715 if ( !$this->mPage->exists() ) {
716 wfDebug( __METHOD__ .
": showing missing article" );
717 $this->showMissingArticle();
718 $this->mPage->doViewUpdates( $performer );
724 if ( $useParserCache && !$oldid ) {
725 $pOutput = $parserOutputAccess->getCachedParserOutput(
729 ParserOutputAccess::OPT_NO_AUDIENCE_CHECK
733 $this->doOutputFromParserCache( $pOutput, $outputPage, $textOptions );
734 $this->doOutputMetaData( $pOutput, $outputPage );
739 $rev = $this->fetchRevisionRecord();
740 if ( !$this->fetchResult->isOK() ) {
741 $this->showViewError( $this->fetchResult->getWikiText(
742 false,
false, $this->getContext()->getLanguage()
747 # Are we looking at an old revision
749 $this->setOldSubtitle( $oldid );
751 if ( !$this->showDeletedRevisionHeader() ) {
752 wfDebug( __METHOD__ .
": cannot view deleted revision" );
759 if ( $useParserCache ) {
760 $pOutput = $parserOutputAccess->getCachedParserOutput(
764 ParserOutputAccess::OPT_NO_AUDIENCE_CHECK
768 $this->doOutputFromParserCache( $pOutput, $outputPage, $textOptions );
769 $this->doOutputMetaData( $pOutput, $outputPage );
775 # Ensure that UI elements requiring revision ID have
776 # the correct version information. (This may be overwritten after creation of ParserOutput)
779 # Preload timestamp to avoid a DB hit
782 # Pages containing custom CSS or JavaScript get special treatment
783 if ( $this->
getTitle()->isSiteConfigPage() || $this->
getTitle()->isUserConfigPage() ) {
784 $dir = $this->
getContext()->getLanguage()->getDir();
785 $lang = $this->
getContext()->getLanguage()->getHtmlCode();
788 "<div id='mw-clearyourcache' lang='$lang' dir='$dir' class='mw-content-$dir'>\n$1\n</div>",
792 } elseif ( !$this->getHookRunner()->onArticleRevisionViewCustom(
800 $this->doOutputMetaData( $pOutput, $outputPage );
804 # Run the parse, protected by a pool counter
805 wfDebug( __METHOD__ .
": doing uncached parse" );
810 $opt |= ParserOutputAccess::OPT_NO_CHECK_CACHE;
813 $opt |= ParserOutputAccess::OPT_NO_AUDIENCE_CHECK;
816 $opt |= ParserOutputAccess::OPT_FOR_ARTICLE_VIEW;
821 $opt |= ParserOutputAccess::OPT_LINKS_UPDATE;
823 if ( !$rev->
getId() || !$useParserCache ) {
825 $opt |= ParserOutputAccess::OPT_NO_CACHE;
828 $renderStatus = $parserOutputAccess->getParserOutput(
850 if ( $oldid === 0 || $oldid === $this->getPage()->getLatest() ) {
851 $parsoidCacheWarmingEnabled = $this->
getContext()->getConfig()
852 ->get( MainConfigNames::ParsoidCacheConfig )[
'WarmParsoidParserCache'];
854 if ( $parsoidCacheWarmingEnabled ) {
857 $this->getPage()->toPageRecord(),
858 [
'causeAction' =>
'view' ]
860 $this->jobQueueGroup->lazyPush( $parsoidJobSpec );
864 $this->doOutputFromRenderStatus(
871 if ( !$renderStatus->
isOK() ) {
875 $pOutput = $renderStatus->
getValue();
876 $this->doOutputMetaData( $pOutput, $outputPage );
881 # Adjust title for main page & pages with displaytitle
883 $this->adjustDisplayTitle( $pOutput );
895 # Check for any __NOINDEX__ tags on the page using $pOutput
896 $policy = $this->getRobotPolicy(
'view', $pOutput ?: null );
897 $outputPage->
getMetadata()->setIndexPolicy( $policy[
'index'] );
900 $this->mParserOutput = $pOutput;
908 private function doOutputFromParserCache(
913 # Ensure that UI elements requiring revision ID have
914 # the correct version information.
919 # Preload timestamp to avoid a DB hit
921 if ( $cachedTimestamp !==
null ) {
923 $this->mPage->setTimestamp( $cachedTimestamp );
933 private function doOutputFromRenderStatus(
940 if ( !$renderStatus->
isOK() ) {
942 false,
'view-pool-error', $context->getLanguage()
947 $pOutput = $renderStatus->
getValue();
950 if ( $renderStatus->
hasMessage(
'view-pool-dirty-output' ) ) {
951 $outputPage->
lowerCdnMaxage( $context->getConfig()->get( MainConfigNames::CdnMaxageStale ) );
953 $staleReason = $renderStatus->
hasMessage(
'view-pool-contention' )
954 ? $context->msg(
'view-pool-contention' )->escaped()
955 : $context->msg(
'view-pool-timeout' )->escaped();
956 $outputPage->
addHTML(
"<!-- parser cache is expired, " .
957 "sending anyway due to $staleReason-->\n" );
961 if ( $cachedId !==
null ) {
969 if ( $this->getRevisionRedirectTarget( $rev ) ) {
970 $outputPage->
addSubtitle(
"<span id=\"redirectsub\">" .
971 $context->msg(
'redirectpagesub' )->parse() .
"</span>" );
979 private function getRevisionRedirectTarget(
RevisionRecord $revision ) {
983 $content = $revision->
getContent( SlotRecord::MAIN );
984 return $content ? $content->getRedirectTarget() :
null;
991 $out = $this->getContext()->getOutput();
993 # Adjust the title if it was set by displaytitle, -{T|}- or language conversion
995 if ( strval( $titleText ) !==
'' ) {
996 $out->setPageTitle( $titleText );
997 $out->setDisplayTitle( $titleText );
1006 $context = $this->getContext();
1009 $request = $context->getRequest();
1010 $diff = $request->getVal(
'diff' );
1011 $rcid = $request->getInt(
'rcid' );
1012 $purge = $request->getRawVal(
'action' ) ===
'purge';
1013 $unhide = $request->getInt(
'unhide' ) === 1;
1014 $oldid = $this->getOldID();
1016 $rev = $this->fetchRevisionRecord();
1021 $rev = $this->revisionStore->getRevisionById( $oldid );
1028 $msg = $context->msg(
'difference-missing-revision' )
1037 $services = MediaWikiServices::getInstance();
1039 $contentHandler = $services
1040 ->getContentHandlerFactory()
1041 ->getContentHandler(
1044 $de = $contentHandler->createDifferenceEngine(
1053 $diffType = $request->getVal(
'diff-type' );
1055 if ( $diffType ===
null ) {
1056 $diffType = $this->userOptionsLookup
1057 ->getOption( $context->getUser(),
'diff-type' );
1059 $de->setExtraQueryParams( [
'diff-type' => $diffType ] );
1062 $de->setSlotDiffOptions( [
1063 'diff-type' => $diffType,
1064 'expand-url' => $this->viewIsRenderAction,
1065 'inline-toggle' =>
true,
1067 $de->showDiffPage( $this->isDiffOnlyView() );
1071 [ , $new ] = $de->mapDiffPrevNext( $oldid, $diff );
1073 $this->mPage->doViewUpdates( $context->getAuthority(), (
int)$new );
1076 $context->getOutput()->addHelpLink(
'Help:Diff' );
1080 return $this->getContext()->getRequest()->getBool(
1082 $this->userOptionsLookup->getBoolOption( $this->getContext()->getUser(),
'diffonly' )
1094 $context = $this->getContext();
1095 $mainConfig = $context->getConfig();
1096 $articleRobotPolicies = $mainConfig->get( MainConfigNames::ArticleRobotPolicies );
1097 $namespaceRobotPolicies = $mainConfig->get( MainConfigNames::NamespaceRobotPolicies );
1098 $defaultRobotPolicy = $mainConfig->get( MainConfigNames::DefaultRobotPolicy );
1100 $ns = $title->getNamespace();
1102 # Don't index user and user talk pages for blocked users (T13443)
1104 $specificTarget =
null;
1105 $vagueTarget =
null;
1106 $titleText = $title->getText();
1107 if ( IPUtils::isValid( $titleText ) ) {
1108 $vagueTarget = $titleText;
1110 $specificTarget = $title->getRootText();
1112 if ( $this->blockStore->newFromTarget( $specificTarget, $vagueTarget ) instanceof
DatabaseBlock ) {
1114 'index' =>
'noindex',
1115 'follow' =>
'nofollow'
1120 if ( $this->mPage->getId() === 0 || $this->getOldID() ) {
1121 # Non-articles (special pages etc), and old revisions
1123 'index' =>
'noindex',
1124 'follow' =>
'nofollow'
1126 } elseif ( $context->getOutput()->isPrintable() ) {
1127 # Discourage indexing of printable versions, but encourage following
1129 'index' =>
'noindex',
1130 'follow' =>
'follow'
1132 } elseif ( $context->getRequest()->getInt(
'curid' ) ) {
1133 # For ?curid=x urls, disallow indexing
1135 'index' =>
'noindex',
1136 'follow' =>
'follow'
1140 # Otherwise, construct the policy based on the various config variables.
1141 $policy = self::formatRobotPolicy( $defaultRobotPolicy );
1143 if ( isset( $namespaceRobotPolicies[$ns] ) ) {
1144 # Honour customised robot policies for this namespace
1145 $policy = array_merge(
1147 self::formatRobotPolicy( $namespaceRobotPolicies[$ns] )
1150 if ( $title->canUseNoindex() && $pOutput && $pOutput->
getIndexPolicy() ) {
1151 # __INDEX__ and __NOINDEX__ magic words, if allowed. Incorporates
1152 # a final check that we have really got the parser output.
1153 $policy = array_merge(
1159 if ( isset( $articleRobotPolicies[$title->getPrefixedText()] ) ) {
1160 # (T16900) site config can override user-defined __INDEX__ or __NOINDEX__
1161 $policy = array_merge(
1163 self::formatRobotPolicy( $articleRobotPolicies[$title->getPrefixedText()] )
1178 if ( is_array( $policy ) ) {
1180 } elseif ( !$policy ) {
1185 foreach ( explode(
',', $policy ) as $var ) {
1186 $var = trim( $var );
1187 if ( $var ===
'index' || $var ===
'noindex' ) {
1188 $arr[
'index'] = $var;
1189 } elseif ( $var ===
'follow' || $var ===
'nofollow' ) {
1190 $arr[
'follow'] = $var;
1205 $context = $this->getContext();
1206 $redirectSources = $context->getConfig()->get( MainConfigNames::RedirectSources );
1208 $request = $context->getRequest();
1209 $rdfrom = $request->getVal(
'rdfrom' );
1212 $query = $request->getQueryValues();
1213 unset( $query[
'rdfrom'] );
1214 unset( $query[
'title'] );
1215 if ( $this->
getTitle()->isRedirect() ) {
1217 $query[
'redirect'] =
'no';
1219 $redirectTargetUrl = $this->
getTitle()->getLinkURL( $query );
1221 if ( $this->mRedirectedFrom ) {
1224 if ( $this->getHookRunner()->onArticleViewRedirect( $this ) ) {
1225 $redir = $this->linkRenderer->makeKnownLink(
1226 $this->mRedirectedFrom,
1229 [
'redirect' =>
'no' ]
1232 $outputPage->
addSubtitle(
"<span class=\"mw-redirectedfrom\">" .
1233 $context->msg(
'redirectedfrom' )->rawParams( $redir )->parse()
1239 'wgInternalRedirectTargetUrl' => $redirectTargetUrl,
1241 $outputPage->
addModules(
'mediawiki.action.view.redirect' );
1251 } elseif ( $rdfrom ) {
1254 if ( $redirectSources && preg_match( $redirectSources, $rdfrom ) ) {
1255 $redir = $this->linkRenderer->makeExternalLink( $rdfrom, $rdfrom, $this->
getTitle() );
1256 $outputPage->
addSubtitle(
"<span class=\"mw-redirectedfrom\">" .
1257 $context->msg(
'redirectedfrom' )->rawParams( $redir )->parse()
1262 'wgInternalRedirectTargetUrl' => $redirectTargetUrl,
1264 $outputPage->
addModules(
'mediawiki.action.view.redirect' );
1278 if ( $this->
getTitle()->isTalkPage() && !$this->getContext()->msg(
'talkpageheader' )->isDisabled() ) {
1279 $this->getContext()->getOutput()->wrapWikiMsg(
1280 "<div class=\"mw-talkpageheader\">\n$1\n</div>",
1281 [
'talkpageheader' ]
1290 # check if we're displaying a [[User talk:x.x.x.x]] anonymous talk page
1292 && IPUtils::isValid( $this->
getTitle()->getText() )
1294 $this->getContext()->getOutput()->addWikiMsg(
'anontalkpagetext' );
1298 $patrolFooterShown = $this->showPatrolFooter();
1300 $this->getHookRunner()->onArticleViewFooter( $this, $patrolFooterShown );
1314 $context = $this->getContext();
1315 $mainConfig = $context->getConfig();
1316 $useNPPatrol = $mainConfig->get( MainConfigNames::UseNPPatrol );
1317 $useRCPatrol = $mainConfig->get( MainConfigNames::UseRCPatrol );
1318 $useFilePatrol = $mainConfig->get( MainConfigNames::UseFilePatrol );
1319 $fileMigrationStage = $mainConfig->get( MainConfigNames::FileSchemaMigrationStage );
1321 if ( !$this->getHookRunner()->onArticleShowPatrolFooter( $this ) ) {
1326 $user = $context->getUser();
1330 if ( !$context->getAuthority()->probablyCan(
'patrol', $title )
1331 || !( $useRCPatrol || $useNPPatrol
1332 || ( $useFilePatrol && $title->inNamespace(
NS_FILE ) ) )
1338 if ( $this->mRevisionRecord
1339 && !RecentChange::isInRCLifespan( $this->mRevisionRecord->getTimestamp(), 21600 )
1347 $cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
1348 $key = $cache->makeKey(
'unpatrollable-page', $title->getArticleID() );
1349 if ( $cache->get( $key ) ) {
1353 $dbr = $this->dbProvider->getReplicaDatabase();
1354 $oldestRevisionRow = $dbr->newSelectQueryBuilder()
1355 ->select( [
'rev_id',
'rev_timestamp' ] )
1356 ->from(
'revision' )
1357 ->where( [
'rev_page' => $title->getArticleID() ] )
1358 ->orderBy( [
'rev_timestamp',
'rev_id' ] )
1359 ->caller( __METHOD__ )->fetchRow();
1360 $oldestRevisionTimestamp = $oldestRevisionRow ? $oldestRevisionRow->rev_timestamp :
false;
1366 $recentPageCreation =
false;
1367 if ( $oldestRevisionTimestamp
1368 && RecentChange::isInRCLifespan( $oldestRevisionTimestamp, 21600 )
1371 $recentPageCreation =
true;
1372 $rc = RecentChange::newFromConds(
1374 'rc_this_oldid' => intval( $oldestRevisionRow->rev_id ),
1382 $markPatrolledMsg = $context->msg(
'markaspatrolledtext' );
1390 $recentFileUpload =
false;
1391 if ( ( !$rc || $rc->getAttribute(
'rc_patrolled' ) ) && $useFilePatrol
1392 && $title->getNamespace() ===
NS_FILE ) {
1395 $newestUploadTimestamp = $dbr->newSelectQueryBuilder()
1396 ->select(
'img_timestamp' )
1398 ->where( [
'img_name' => $title->getDBkey() ] )
1399 ->caller( __METHOD__ )->fetchField();
1401 $newestUploadTimestamp = $dbr->newSelectQueryBuilder()
1402 ->select(
'fr_timestamp' )
1404 ->join(
'filerevision',
null,
'file_latest = fr_id' )
1405 ->where( [
'file_name' => $title->getDBkey() ] )
1406 ->caller( __METHOD__ )->fetchField();
1409 if ( $newestUploadTimestamp
1410 && RecentChange::isInRCLifespan( $newestUploadTimestamp, 21600 )
1413 $recentFileUpload =
true;
1414 $rc = RecentChange::newFromConds(
1417 'rc_log_type' =>
'upload',
1418 'rc_timestamp' => $newestUploadTimestamp,
1420 'rc_cur_id' => $title->getArticleID()
1426 $markPatrolledMsg = $context->msg(
'markaspatrolledtext-file' );
1431 if ( !$recentPageCreation && !$recentFileUpload ) {
1436 $cache->set( $key,
'1' );
1448 if ( $rc->getAttribute(
'rc_patrolled' ) ) {
1453 $cache->set( $key,
'1' );
1458 if ( $rc->getPerformerIdentity()->equals( $user ) ) {
1464 $outputPage->
getMetadata()->setPreventClickjacking(
true );
1465 $outputPage->
addModules(
'mediawiki.misc-authed-curate' );
1467 $link = $this->linkRenderer->makeKnownLink(
1469 new HtmlArmor(
'<button class="cdx-button cdx-button--action-progressive">'
1471 . $markPatrolledMsg->escaped() .
'</button>' ),
1474 'action' =>
'markpatrolled',
1475 'rcid' => $rc->getAttribute(
'rc_id' ),
1480 $outputPage->
addHTML(
"<div class='patrollink' data-mw='interface'>$link</div>" );
1492 $cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
1493 $cache->delete( $cache->makeKey(
'unpatrollable-page', $articleID ) );
1501 $context = $this->getContext();
1502 $send404Code = $context->getConfig()->get( MainConfigNames::Send404Code );
1506 $validUserPage =
false;
1510 $services = MediaWikiServices::getInstance();
1512 $contextUser = $context->getUser();
1514 # Show info in user (talk) namespace. Does the user exist? Is he blocked?
1515 if ( $title->getNamespace() ===
NS_USER
1518 $rootPart = $title->getRootText();
1519 $userFactory = $services->getUserFactory();
1520 $user = $userFactory->newFromNameOrIp( $rootPart );
1522 $block = $this->blockStore->newFromTarget( $user, $user );
1524 if ( $user && $user->isRegistered() && $user->isHidden() &&
1525 !$context->getAuthority()->isAllowed(
'hideuser' )
1532 if ( !( $user && $user->isRegistered() ) && !$this->userNameUtils->isIP( $rootPart ) ) {
1533 $this->addMessageBoxStyles( $outputPage );
1535 $outputPage->
addHTML( Html::warningBox(
1536 $context->msg(
'userpage-userdoesnotexist-view',
wfEscapeWikiText( $rootPart ) )->parse(),
1537 'mw-userpage-userdoesnotexist'
1541 LogEventsList::showLogExtract(
1544 Title::makeTitleSafe(
NS_USER, $rootPart ),
1548 'showIfEmpty' =>
false,
1549 'msgKey' => [
'renameuser-renamed-notice', $title->getBaseText() ]
1553 $user && $block !==
null &&
1554 $block->getType() != DatabaseBlock::TYPE_AUTO &&
1556 $block->isSitewide() ||
1557 $services->getPermissionManager()->isBlockedFrom( $user, $title,
true )
1562 LogEventsList::showLogExtract(
1565 $services->getNamespaceInfo()->getCanonicalName(
NS_USER ) .
':' .
1566 $block->getTargetName(),
1570 'showIfEmpty' =>
false,
1572 'blocked-notice-logextract',
1573 $user->getName() # Support GENDER in notice
1577 $validUserPage = !$title->isSubpage();
1579 $validUserPage = !$title->isSubpage();
1583 $this->getHookRunner()->onShowMissingArticle( $this );
1585 # Show delete and move logs if there were any such events.
1586 # The logging query can DOS the site when bots/crawlers cause 404 floods,
1587 # so be careful showing this. 404 pages must be cheap as they are hard to cache.
1588 $dbCache = MediaWikiServices::getInstance()->getMainObjectStash();
1589 $key = $dbCache->makeKey(
'page-recent-delete', md5( $title->getPrefixedText() ) );
1590 $isRegistered = $contextUser->isRegistered();
1591 $sessionExists = $context->getRequest()->getSession()->isPersistent();
1593 if ( $isRegistered || $dbCache->get( $key ) || $sessionExists ) {
1594 $logTypes = [
'delete',
'move',
'protect',
'merge' ];
1596 $dbr = $this->dbProvider->getReplicaDatabase();
1598 $conds = [ $dbr->expr(
'log_action',
'!=',
'revision' ) ];
1600 $this->getHookRunner()->onArticle__MissingArticleConditions( $conds, $logTypes );
1601 LogEventsList::showLogExtract(
1609 'showIfEmpty' =>
false,
1610 'msgKey' => [ $isRegistered || $sessionExists
1611 ?
'moveddeleted-notice'
1612 :
'moveddeleted-notice-recent'
1618 if ( !$this->mPage->hasViewableContent() && $send404Code && !$validUserPage ) {
1621 $context->getRequest()->response()->statusHeader( 404 );
1625 $policy = $this->getRobotPolicy(
'view' );
1626 $outputPage->
getMetadata()->setIndexPolicy( $policy[
'index'] );
1629 $hookResult = $this->getHookRunner()->onBeforeDisplayNoArticleText( $this );
1631 if ( !$hookResult ) {
1635 # Show error message
1636 $oldid = $this->getOldID();
1637 if ( !$oldid && $title->getNamespace() ===
NS_MEDIAWIKI && $title->hasSourceText() ) {
1638 $text = $this->
getTitle()->getDefaultMessageText() ??
'';
1642 $text = $this->getMissingRevisionMsg( $oldid )->plain();
1643 } elseif ( $context->getAuthority()->probablyCan(
'edit', $title ) ) {
1644 $message = $isRegistered ?
'noarticletext' :
'noarticletextanon';
1645 $text = $context->msg( $message )->plain();
1647 $text = $context->msg(
'noarticletext-nopermission' )->plain();
1650 $dir = $context->getLanguage()->getDir();
1651 $lang = $context->getLanguage()->getHtmlCode();
1653 'class' =>
"noarticletext mw-content-$dir",
1656 ] ) .
"\n$text\n</div>" );
1664 private function showViewError(
string $errortext ) {
1665 $outputPage = $this->getContext()->getOutput();
1666 $outputPage->
setPageTitleMsg( $this->getContext()->msg(
'errorpagetitle' ) );
1670 $this->addMessageBoxStyles( $outputPage );
1681 if ( !$this->mRevisionRecord->isDeleted( RevisionRecord::DELETED_TEXT ) ) {
1685 $outputPage = $this->getContext()->getOutput();
1687 $titleText = $this->
getTitle()->getPrefixedDBkey();
1688 $this->addMessageBoxStyles( $outputPage );
1690 if ( !$this->mRevisionRecord->userCan(
1691 RevisionRecord::DELETED_TEXT,
1692 $this->getContext()->getAuthority()
1696 $outputPage->
msg(
'rev-deleted-text-permission', $titleText )->parse(),
1703 } elseif ( $this->getContext()->getRequest()->getInt(
'unhide' ) !== 1 ) {
1704 # Give explanation and add a link to view the revision...
1705 $oldid = intval( $this->getOldID() );
1706 $link = $this->
getTitle()->getFullURL(
"oldid={$oldid}&unhide=1" );
1707 $msg = $this->mRevisionRecord->isDeleted( RevisionRecord::DELETED_RESTRICTED ) ?
1708 'rev-suppressed-text-unhide' :
'rev-deleted-text-unhide';
1711 $outputPage->
msg( $msg, $link )->parse(),
1719 $msg = $this->mRevisionRecord->isDeleted( RevisionRecord::DELETED_RESTRICTED )
1720 ? [
'rev-suppressed-text-view', $titleText ]
1721 : [
'rev-deleted-text-view', $titleText ];
1724 $outputPage->
msg( $msg[0], $msg[1] )->parse(),
1733 private function addMessageBoxStyles(
OutputPage $outputPage ) {
1735 'mediawiki.codex.messagebox.styles',
1748 if ( !$this->getHookRunner()->onDisplayOldSubtitle( $this, $oldid ) ) {
1752 $context = $this->getContext();
1753 $unhide = $context->getRequest()->getInt(
'unhide' ) === 1;
1755 # Cascade unhide param in links for easy deletion browsing
1758 $extraParams[
'unhide'] = 1;
1761 if ( $this->mRevisionRecord && $this->mRevisionRecord->getId() === $oldid ) {
1762 $revisionRecord = $this->mRevisionRecord;
1764 $revisionRecord = $this->revisionStore->getRevisionById( $oldid );
1766 if ( !$revisionRecord ) {
1767 throw new LogicException(
'There should be a revision record at this point.' );
1770 $timestamp = $revisionRecord->getTimestamp();
1772 $current = ( $oldid == $this->mPage->getLatest() );
1773 $language = $context->getLanguage();
1774 $user = $context->getUser();
1776 $td = $language->userTimeAndDate( $timestamp, $user );
1777 $tddate = $language->userDate( $timestamp, $user );
1778 $tdtime = $language->userTime( $timestamp, $user );
1780 # Show user links if allowed to see them. If hidden, then show them only if requested...
1781 $userlinks = Linker::revUserTools( $revisionRecord, !$unhide );
1783 $infomsg = $current && !$context->msg(
'revision-info-current' )->isDisabled()
1784 ?
'revision-info-current'
1789 'mediawiki.action.styles',
1790 'mediawiki.interface.helpers.styles'
1793 $revisionUser = $revisionRecord->getUser();
1794 $revisionInfo =
"<div id=\"mw-{$infomsg}\">" .
1795 $context->msg( $infomsg, $td )
1796 ->rawParams( $userlinks )
1798 $revisionRecord->getId(),
1801 $revisionUser ? $revisionUser->getName() :
''
1803 ->rawParams( $this->commentFormatter->formatRevision(
1813 ? $context->msg(
'currentrevisionlink' )->escaped()
1814 : $this->linkRenderer->makeKnownLink(
1816 $context->msg(
'currentrevisionlink' )->text(),
1821 ? $context->msg(
'diff' )->escaped()
1822 : $this->linkRenderer->makeKnownLink(
1824 $context->msg(
'diff' )->text(),
1831 $prevExist = (bool)$this->revisionStore->getPreviousRevision( $revisionRecord );
1832 $prevlink = $prevExist
1833 ? $this->linkRenderer->makeKnownLink(
1835 $context->msg(
'previousrevision' )->text(),
1838 'direction' =>
'prev',
1842 : $context->msg(
'previousrevision' )->escaped();
1843 $prevdiff = $prevExist
1844 ? $this->linkRenderer->makeKnownLink(
1846 $context->msg(
'diff' )->text(),
1853 : $context->msg(
'diff' )->escaped();
1854 $nextlink = $current
1855 ? $context->msg(
'nextrevision' )->escaped()
1856 : $this->linkRenderer->makeKnownLink(
1858 $context->msg(
'nextrevision' )->text(),
1861 'direction' =>
'next',
1865 $nextdiff = $current
1866 ? $context->msg(
'diff' )->escaped()
1867 : $this->linkRenderer->makeKnownLink(
1869 $context->msg(
'diff' )->text(),
1877 $cdel = Linker::getRevDeleteLink(
1878 $context->getAuthority(),
1882 if ( $cdel !==
'' ) {
1887 $this->addMessageBoxStyles( $outputPage );
1891 "<div id=\"mw-revision-nav\">" . $cdel .
1892 $context->msg(
'revision-nav' )->rawParams(
1893 $prevdiff, $prevlink, $lnk, $curdiff, $nextlink, $nextdiff
1894 )->escaped() .
"</div>",
1915 $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
1928 $out = $this->getContext()->getOutput();
1929 $msg = $out->msg(
'namespace-' . $this->
getTitle()->getNamespace() .
'-helppage' );
1931 if ( !$msg->isDisabled() ) {
1932 $title = Title::newFromText( $msg->plain() );
1933 if ( $title instanceof
Title ) {
1934 $out->addHelpLink( $title->getLocalURL(),
true );
1937 $out->addHelpLink( $to, $overrideBaseUrl );
1945 $this->getContext()->getRequest()->response()->header(
'X-Robots-Tag: noindex' );
1946 $this->getContext()->getOutput()->setArticleBodyOnly(
true );
1948 $this->viewIsRenderAction =
true;
1977 static $called =
false;
1980 wfDebug(
"Article::tryFileCache(): called twice!?" );
1985 if ( $this->isFileCacheable() ) {
1987 if ( $cache->isCacheGood( $this->mPage->getTouched() ) ) {
1988 wfDebug(
"Article::tryFileCache(): about to load file" );
1989 $cache->loadFromFileCache( $this->getContext() );
1992 wfDebug(
"Article::tryFileCache(): starting buffer" );
1993 ob_start( [ &$cache,
'saveToFileCache' ] );
1996 wfDebug(
"Article::tryFileCache(): not cacheable" );
2010 if ( HTMLFileCache::useFileCache( $this->getContext(), $mode ) ) {
2011 $cacheable = $this->mPage->getId()
2012 && !$this->mRedirectedFrom && !$this->
getTitle()->isRedirect();
2015 $cacheable = $this->getHookRunner()->onIsFileCacheable( $this ) ??
false;
2034 if ( $user ===
null ) {
2035 $parserOptions = $this->getParserOptions();
2037 $parserOptions = $this->mPage->makeParserOptions( $user );
2041 return $this->mPage->getParserOutput( $parserOptions, $oldid );
2049 $parserOptions = $this->mPage->makeParserOptions( $this->getContext() );
2051 return $parserOptions;
2061 $this->mContext = $context;
2072 return $this->mContext;
2074 wfDebug( __METHOD__ .
" called and \$mContext is null. " .
2075 "Return RequestContext::getMain()" );
2076 return RequestContext::getMain();
2086 return $this->mPage->getActionOverrides();
2089 private function getMissingRevisionMsg(
int $oldid ):
Message {
2093 $context = $this->getContext();
2094 $revRecord = $this->archivedRevisionLookup->getArchivedRevisionRecord(
null, $oldid );
2097 $revRecord->userCan(
2098 RevisionRecord::DELETED_TEXT,
2099 $context->getAuthority()
2101 $context->getAuthority()->isAllowedAny(
'deletedtext',
'undelete' )
2103 return $context->msg(
2104 'missing-revision-permission',
2106 $revRecord->getTimestamp(),
2107 Title::newFromPageIdentity( $revRecord->getPage() )->getPrefixedDBkey()
2110 return $context->msg(
'missing-revision', $oldid );
const SCHEMA_COMPAT_READ_OLD
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
wfEscapeWikiText( $input)
Escapes the given text so that it may be output using addWikiText() without any linking,...
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that a deprecated feature was used.
if(!defined('MW_SETUP_CALLBACK'))
Legacy class representing an editable page and handling UI for some page actions.
static newFromWikiPage(WikiPage $page, IContextSource $context)
Create an Article object of the appropriate class for the given page.
getContext()
Gets the context this Article is executed in.
getOldIDFromRequest()
Sets $this->mRedirectUrl to a correct URL if the query parameters are incorrect.
getRedirectedFrom()
Get the page this view was redirected from.
Title null $mRedirectedFrom
Title from which we were redirected here, if any.
bool $viewIsRenderAction
Whether render() was called.
view()
This is the default action of the index.php entry point: just view the page of the given title.
showProtectionIndicator()
Show a lock icon above the article body if the page is protected.
__construct(Title $title, $oldId=null)
static purgePatrolFooterCache( $articleID)
Purge the cache used to check if it is worth showing the patrol footer For example,...
ParserOutput null false $mParserOutput
The ParserOutput generated for viewing the page, initialized by view().
LinkRenderer $linkRenderer
getTitle()
Get the title object of the article.
getActionOverrides()
Call to WikiPage function for backwards compatibility.
adjustDisplayTitle(ParserOutput $pOutput)
Adjust title for pages with displaytitle, -{T|}- or language conversion.
DatabaseBlockStore $blockStore
showDeletedRevisionHeader()
If the revision requested for view is deleted, check permissions.
getParserOptions()
Get parser options suitable for rendering the primary article wikitext.
IContextSource null $mContext
The context this Article is executed in.
static getRedirectHeaderHtml(Language $lang, Title $target, $forceKnown=false)
Return the HTML for the top of a redirect page.
protect()
action=protect handler
string false $mRedirectUrl
URL to redirect to or false if none.
isCurrent()
Returns true if the currently-referenced revision is the current edit to this page (and it exists).
showMissingArticle()
Show the error text for a missing article.
IConnectionProvider $dbProvider
unprotect()
action=unprotect handler (alias)
getPage()
Get the WikiPage object of this instance.
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
static newFromID( $id)
Constructor from a page id.
int null $mOldId
The oldid of the article that was requested to be shown, 0 for the current revision.
static formatRobotPolicy( $policy)
Converts a String robot policy into an associative array, to allow merging of several policies using ...
fetchRevisionRecord()
Fetches the revision to work on.
getRobotPolicy( $action, ?ParserOutput $pOutput=null)
Get the robot policy to be used for the current view.
showPatrolFooter()
If patrol is possible, output a patrol UI box.
setOldSubtitle( $oldid=0)
Generate the navigation links when browsing through an article revisions It shows the information as:...
showViewFooter()
Show the footer section of an ordinary page view.
WikiPage $mPage
The WikiPage object of this instance.
setRedirectedFrom(Title $from)
Tell the page view functions that this view was redirected from another page on the wiki.
isFileCacheable( $mode=HTMLFileCache::MODE_NORMAL)
Check if the page can be cached.
tryFileCache()
checkLastModified returns true if it has taken care of all output to the client that is necessary for...
getRevIdFetched()
Use this to fetch the rev ID used on page views.
showNamespaceHeader()
Show a header specific to the namespace currently being viewed, like [[MediaWiki:Talkpagetext]].
static newFromTitle( $title, IContextSource $context)
Create an Article object of the appropriate class for the given page.
showDiffPage()
Show a diff page according to current request variables.
RestrictionStore $restrictionStore
render()
Handle action=render.
showRedirectedFromHeader()
If this request is a redirect view, send "redirected from" subtitle to the output.
getParserOutput( $oldid=null, ?UserIdentity $user=null)
Lightweight method to get the parser output for a page, checking the parser cache and so on.
setContext( $context)
Sets the context this Article is executed in.
Special handling for category description pages.
Page view caching in the file system.
Marks HTML that shouldn't be escaped.
Rendering of file description pages.
Handle enqueueing of background jobs.
msg( $key,... $params)
Get a Message object with context set Parameters are the same as wfMessage()
Group all the pieces relevant to the context of a request into one instance.
The HTML user interface for page editing.
A class containing constants representing the names of configuration variables.
This is one of the Core classes and should be read at least once by any new developers.
parseAsContent( $text, $linestart=true)
Parse wikitext in the page content language and return the HTML.
disableClientCache()
Force the page to send nocache headers.
addJsConfigVars( $keys, $value=null)
Add one or more variables to be set in mw.config in JavaScript.
wrapWikiMsg( $wrap,... $msgSpecs)
This function takes a number of message/argument specifications, wraps them in some overall structure...
disable()
Disable output completely, i.e.
setRedirectedFrom(PageReference $t)
Set $mRedirectedFrom, the page which redirected us to the current page.
setRevisionTimestamp( $timestamp)
Set the timestamp of the revision which will be displayed.
adaptCdnTTL( $mtime, $minTTL=0, $maxTTL=0)
Get TTL in [$minTTL,$maxTTL] and pass it to lowerCdnMaxage()
addBodyClasses( $classes)
Add a class to the <body> element.
lowerCdnMaxage( $maxage)
Set the value of the "s-maxage" part of the "Cache-control" HTTP header to $maxage if that is lower t...
setContentLangForJS(Bcp47Code $lang)
setIndicators(array $indicators)
Add an array of indicators, with their identifiers as array keys and HTML contents as values.
setLastModified( $timestamp)
Override the last modified timestamp.
setRevisionIsCurrent(bool $isCurrent)
Set whether the revision displayed (as set in ::setRevisionId()) is the latest revision of the page.
addWikiTextAsContent( $text, $linestart=true, ?PageReference $title=null)
Convert wikitext in the page content language to HTML and add it to the buffer.
setFollowPolicy( $policy)
Set the follow policy for the page, but leave the index policy un- touched.
clearHTML()
Clear the body HTML.
setPageTitle( $name)
"Page title" means the contents of <h1>.
setPageTitleMsg(Message $msg)
"Page title" means the contents of <h1>.
addModules( $modules)
Load one or more ResourceLoader modules on this page.
redirect( $url, $responsecode='302')
Redirect to $url rather than displaying the normal page.
setHTMLTitle( $name)
"HTML title" means the contents of "<title>".
prependHTML( $text)
Prepend $text to the body HTML.
setRobotPolicy( $policy)
Set the robot policy for the page: http://www.robotstxt.org/meta.html
setCanonicalUrl( $url)
Set the URL to be used for the <link rel=canonical>>.
addHTML( $text)
Append $text to the body HTML.
addWikiTextAsInterface( $text, $linestart=true, ?PageReference $title=null)
Convert wikitext in the user interface language to HTML and add it to the buffer.
setRevisionId( $revid)
Set the revision ID which will be seen by the wiki text parser for things such as embedded {{REVISION...
addSubtitle( $str)
Add $str to the subtitle.
addModuleStyles( $modules)
Load the styles of one or more style-only ResourceLoader modules on this page.
addParserOutput(ParserOutput $parserOutput, $poOptions=[])
Add everything from a ParserOutput object.
getMetadata()
Return a ParserOutput that can be used to set metadata properties for the current page.
isPrintable()
Return whether the page is "printable".
setArticleFlag( $newVal)
Set whether the displayed content is related to the source of the corresponding article on the wiki S...
Service for getting rendered output of a given page.
Handles the page protection UI and backend.
Service for creating WikiPage objects.
static newSpec(int $revisionId, PageRecord $page, array $params=[])
Show an error when a user tries to do something they do not have the necessary permissions for.
hasMessage(string $message)
Returns true if the specified message is present as a warning or error.
isOK()
Returns whether the operation completed.
fatal( $message,... $parameters)
Add an error and set OK to false, indicating that the operation as a whole was fatal.
Base representation for an editable wiki page.
getTitle()
Get the title object of the article.
Interface for objects which can provide a MediaWiki context on request.
Interface for type hinting (accepts WikiPage, Article, ImagePage, CategoryPage)