/** * This is the default action of the index.php entry point: just view the * page of the given title. */ public function view() { global $wgUseFileCache, $wgUseETag, $wgDebugToolbar, $wgMaxRedirects; # Get variables from query string # As side effect this will load the revision and update the title # in a revision ID is passed in the request, so this should remain # the first call of this method even if $oldid is used way below. $oldid = $this->getOldID(); $user = $this->getContext()->getUser(); # Another whitelist check in case getOldID() is altering the title $permErrors = $this->getTitle()->getUserPermissionsErrors('read', $user); if (count($permErrors)) { wfDebug(__METHOD__ . ": denied on secondary read check\n"); throw new PermissionsError('read', $permErrors); } $outputPage = $this->getContext()->getOutput(); # getOldID() may as well want us to redirect somewhere else if ($this->mRedirectUrl) { $outputPage->redirect($this->mRedirectUrl); wfDebug(__METHOD__ . ": redirecting due to oldid\n"); return; } # If we got diff in the query, we want to see a diff page instead of the article. if ($this->getContext()->getRequest()->getCheck('diff')) { wfDebug(__METHOD__ . ": showing diff page\n"); $this->showDiffPage(); return; } # Set page title (may be overridden by DISPLAYTITLE) $outputPage->setPageTitle($this->getTitle()->getPrefixedText()); $outputPage->setArticleFlag(true); # Allow frames by default $outputPage->allowClickjacking(); $parserCache = ParserCache::singleton(); $parserOptions = $this->getParserOptions(); # Render printable version, use printable version cache if ($outputPage->isPrintable()) { $parserOptions->setIsPrintable(true); $parserOptions->setEditSection(false); } elseif (!$this->isCurrent() || !$this->getTitle()->quickUserCan('edit', $user)) { $parserOptions->setEditSection(false); } # Try client and file cache if (!$wgDebugToolbar && $oldid === 0 && $this->mPage->checkTouched()) { if ($wgUseETag) { $outputPage->setETag($parserCache->getETag($this, $parserOptions)); } # Use the greatest of the page's timestamp or the timestamp of any # redirect in the chain (bug 67849) $timestamp = $this->mPage->getTouched(); if (isset($this->mRedirectedFrom)) { $timestamp = max($timestamp, $this->mRedirectedFrom->getTouched()); # If there can be more than one redirect in the chain, we have # to go through the whole chain too in case an intermediate # redirect was changed. if ($wgMaxRedirects > 1) { $titles = Revision::newFromTitle($this->mRedirectedFrom)->getContent(Revision::FOR_THIS_USER, $user)->getRedirectChain(); $thisTitle = $this->getTitle(); foreach ($titles as $title) { if (Title::compare($title, $thisTitle) === 0) { break; } $timestamp = max($timestamp, $title->getTouched()); } } } # Is it client cached? if ($outputPage->checkLastModified($timestamp)) { wfDebug(__METHOD__ . ": done 304\n"); return; # Try file cache } elseif ($wgUseFileCache && $this->tryFileCache()) { wfDebug(__METHOD__ . ": done file cache\n"); # tell wgOut that output is taken care of $outputPage->disable(); $this->mPage->doViewUpdates($user, $oldid); return; } } # Should the parser cache be used? $useParserCache = $this->mPage->shouldCheckParserCache($parserOptions, $oldid); wfDebug('Article::view using parser cache: ' . ($useParserCache ? 'yes' : 'no') . "\n"); if ($user->getStubThreshold()) { $this->getContext()->getStats()->increment('pcache_miss_stub'); } $this->showRedirectedFromHeader(); $this->showNamespaceHeader(); # Iterate through the possible ways of constructing the output text. # Keep going until $outputDone is set, or we run out of things to do. $pass = 0; $outputDone = false; $this->mParserOutput = false; while (!$outputDone && ++$pass) { switch ($pass) { case 1: Hooks::run('ArticleViewHeader', array(&$this, &$outputDone, &$useParserCache)); break; case 2: # Early abort if the page doesn't exist if (!$this->mPage->exists()) { wfDebug(__METHOD__ . ": showing missing article\n"); $this->showMissingArticle(); $this->mPage->doViewUpdates($user); return; } # Try the parser cache if ($useParserCache) { $this->mParserOutput = $parserCache->get($this, $parserOptions); if ($this->mParserOutput !== false) { if ($oldid) { wfDebug(__METHOD__ . ": showing parser cache contents for current rev permalink\n"); $this->setOldSubtitle($oldid); } else { wfDebug(__METHOD__ . ": showing parser cache contents\n"); } $outputPage->addParserOutput($this->mParserOutput); # Ensure that UI elements requiring revision ID have # the correct version information. $outputPage->setRevisionId($this->mPage->getLatest()); # Preload timestamp to avoid a DB hit $cachedTimestamp = $this->mParserOutput->getTimestamp(); if ($cachedTimestamp !== null) { $outputPage->setRevisionTimestamp($cachedTimestamp); $this->mPage->setTimestamp($cachedTimestamp); } $outputDone = true; } } break; case 3: # This will set $this->mRevision if needed $this->fetchContentObject(); # Are we looking at an old revision if ($oldid && $this->mRevision) { $this->setOldSubtitle($oldid); if (!$this->showDeletedRevisionHeader()) { wfDebug(__METHOD__ . ": cannot view deleted revision\n"); return; } } # Ensure that UI elements requiring revision ID have # the correct version information. $outputPage->setRevisionId($this->getRevIdFetched()); # Preload timestamp to avoid a DB hit $outputPage->setRevisionTimestamp($this->getTimestamp()); # Pages containing custom CSS or JavaScript get special treatment if ($this->getTitle()->isCssOrJsPage() || $this->getTitle()->isCssJsSubpage()) { wfDebug(__METHOD__ . ": showing CSS/JS source\n"); $this->showCssOrJsPage(); $outputDone = true; } elseif (!Hooks::run('ArticleContentViewCustom', array($this->fetchContentObject(), $this->getTitle(), $outputPage))) { # Allow extensions do their own custom view for certain pages $outputDone = true; } elseif (!ContentHandler::runLegacyHooks('ArticleViewCustom', array($this->fetchContentObject(), $this->getTitle(), $outputPage))) { # Allow extensions do their own custom view for certain pages $outputDone = true; } break; case 4: # Run the parse, protected by a pool counter wfDebug(__METHOD__ . ": doing uncached parse\n"); $content = $this->getContentObject(); $poolArticleView = new PoolWorkArticleView($this->getPage(), $parserOptions, $this->getRevIdFetched(), $useParserCache, $content); if (!$poolArticleView->execute()) { $error = $poolArticleView->getError(); if ($error) { $outputPage->clearHTML(); // for release() errors $outputPage->enableClientCache(false); $outputPage->setRobotPolicy('noindex,nofollow'); $errortext = $error->getWikiText(false, 'view-pool-error'); $outputPage->addWikiText('<div class="errorbox">' . $errortext . '</div>'); } # Connection or timeout error return; } $this->mParserOutput = $poolArticleView->getParserOutput(); $outputPage->addParserOutput($this->mParserOutput); if ($content->getRedirectTarget()) { $outputPage->addSubtitle("<span id=\"redirectsub\">" . $this->getContext()->msg('redirectpagesub')->parse() . "</span>"); } # Don't cache a dirty ParserOutput object if ($poolArticleView->getIsDirty()) { $outputPage->setSquidMaxage(0); $outputPage->addHTML("<!-- parser cache is expired, " . "sending anyway due to pool overload-->\n"); } $outputDone = true; break; # Should be unreachable, but just in case... # Should be unreachable, but just in case... default: break 2; } } # Get the ParserOutput actually *displayed* here. # Note that $this->mParserOutput is the *current*/oldid version output. $pOutput = $outputDone instanceof ParserOutput ? $outputDone : $this->mParserOutput; # Adjust title for main page & pages with displaytitle if ($pOutput) { $this->adjustDisplayTitle($pOutput); } # For the main page, overwrite the <title> element with the con- # tents of 'pagetitle-view-mainpage' instead of the default (if # that's not empty). # This message always exists because it is in the i18n files if ($this->getTitle()->isMainPage()) { $msg = wfMessage('pagetitle-view-mainpage')->inContentLanguage(); if (!$msg->isDisabled()) { $outputPage->setHTMLTitle($msg->title($this->getTitle())->text()); } } # Check for any __NOINDEX__ tags on the page using $pOutput $policy = $this->getRobotPolicy('view', $pOutput); $outputPage->setIndexPolicy($policy['index']); $outputPage->setFollowPolicy($policy['follow']); $this->showViewFooter(); $this->mPage->doViewUpdates($user, $oldid); $outputPage->addModules('mediawiki.action.view.postEdit'); }
/** * This is the default action of the index.php entry point: just view the * page of the given title. */ public function view() { global $wgUser, $wgOut, $wgRequest, $wgParser; global $wgUseFileCache, $wgUseETag, $wgDebugToolbar; wfProfileIn(__METHOD__); # Get variables from query string # As side effect this will load the revision and update the title # in a revision ID is passed in the request, so this should remain # the first call of this method even if $oldid is used way below. $oldid = $this->getOldID(); # Another whitelist check in case getOldID() is altering the title $permErrors = $this->getTitle()->getUserPermissionsErrors('read', $wgUser); if (count($permErrors)) { wfDebug(__METHOD__ . ": denied on secondary read check\n"); wfProfileOut(__METHOD__); throw new PermissionsError('read', $permErrors); } # getOldID() may as well want us to redirect somewhere else if ($this->mRedirectUrl) { $wgOut->redirect($this->mRedirectUrl); wfDebug(__METHOD__ . ": redirecting due to oldid\n"); wfProfileOut(__METHOD__); return; } # If we got diff in the query, we want to see a diff page instead of the article. if ($wgRequest->getCheck('diff')) { wfDebug(__METHOD__ . ": showing diff page\n"); $this->showDiffPage(); wfProfileOut(__METHOD__); return; } # Set page title (may be overridden by DISPLAYTITLE) $wgOut->setPageTitle($this->getTitle()->getPrefixedText()); $wgOut->setArticleFlag(true); # Allow frames by default $wgOut->allowClickjacking(); $parserCache = ParserCache::singleton(); $parserOptions = $this->getParserOptions(); # Render printable version, use printable version cache if ($wgOut->isPrintable()) { $parserOptions->setIsPrintable(true); $parserOptions->setEditSection(false); } elseif (!$this->isCurrent() || !$this->getTitle()->quickUserCan('edit')) { $parserOptions->setEditSection(false); } # Try client and file cache if (!$wgDebugToolbar && $oldid === 0 && $this->mPage->checkTouched()) { if ($wgUseETag) { $wgOut->setETag($parserCache->getETag($this, $parserOptions)); } # Is it client cached? if ($wgOut->checkLastModified($this->mPage->getTouched())) { wfDebug(__METHOD__ . ": done 304\n"); wfProfileOut(__METHOD__); return; # Try file cache } elseif ($wgUseFileCache && $this->tryFileCache()) { wfDebug(__METHOD__ . ": done file cache\n"); # tell wgOut that output is taken care of $wgOut->disable(); $this->mPage->doViewUpdates($wgUser); wfProfileOut(__METHOD__); return; } } # Should the parser cache be used? $useParserCache = $this->mPage->isParserCacheUsed($parserOptions, $oldid); wfDebug('Article::view using parser cache: ' . ($useParserCache ? 'yes' : 'no') . "\n"); if ($wgUser->getStubThreshold()) { wfIncrStats('pcache_miss_stub'); } $this->showRedirectedFromHeader(); $this->showNamespaceHeader(); # Iterate through the possible ways of constructing the output text. # Keep going until $outputDone is set, or we run out of things to do. $pass = 0; $outputDone = false; $this->mParserOutput = false; while (!$outputDone && ++$pass) { switch ($pass) { case 1: wfRunHooks('ArticleViewHeader', array(&$this, &$outputDone, &$useParserCache)); break; case 2: # Early abort if the page doesn't exist if (!$this->mPage->exists()) { wfDebug(__METHOD__ . ": showing missing article\n"); $this->showMissingArticle(); wfProfileOut(__METHOD__); /* Wikia change begin - @author: Marcin, #BugId: 30436 */ $text = ''; if (wfRunHooks('ArticleNonExistentPage', array(&$this, $wgOut, &$text))) { $this->mParserOutput = $wgParser->parse($text, $this->getTitle(), $parserOptions); $wgOut->addParserOutput($this->mParserOutput); } /* Wikia change end */ return; } # Try the parser cache if ($useParserCache) { $this->mParserOutput = $parserCache->get($this, $parserOptions); //Wikia Change Transaction::setAttribute(Transaction::PARAM_PARSER_CACHE_USED, $this->mParserOutput !== false); //Wikia Change End if ($this->mParserOutput !== false) { if ($oldid) { wfDebug(__METHOD__ . ": showing parser cache contents for current rev permalink\n"); $this->setOldSubtitle($oldid); } else { wfDebug(__METHOD__ . ": showing parser cache contents\n"); } $wgOut->addParserOutput($this->mParserOutput); // Wikia change - begin - @author: wladek wfRunHooks('ArticleViewAddParserOutput', array($this, $this->mParserOutput)); // Wikia change - end # Ensure that UI elements requiring revision ID have # the correct version information. $wgOut->setRevisionId($this->mPage->getLatest()); # Preload timestamp to avoid a DB hit $cachedTimestamp = $this->mParserOutput->getTimestamp(); if ($cachedTimestamp !== null) { $wgOut->setRevisionTimestamp($cachedTimestamp); $this->mPage->setTimestamp($cachedTimestamp); } $outputDone = true; } // Wikia change - begin - @author: wladek } else { Transaction::setAttribute(Transaction::PARAM_PARSER_CACHE_USED, false); // Wikia change - end } break; case 3: # This will set $this->mRevision if needed $this->fetchContent(); // Wikia change - begin // @author macbre // return status different than HTTP 200 when revision is missing (BAC-630) if (!$this->mRevision instanceof Revision) { global $wgEnableParserCache; wfDebug(__METHOD__ . ": no revision found - disabling parser cache and returning 404\n"); $wgOut->getRequest()->response()->header('X-Missing-Revision: 1', true, 404); $useParserCache = false; $wgEnableParserCache = false; } // Wikia change - end # Are we looking at an old revision if ($oldid && $this->mRevision) { $this->setOldSubtitle($oldid); if (!$this->showDeletedRevisionHeader()) { wfDebug(__METHOD__ . ": cannot view deleted revision\n"); wfProfileOut(__METHOD__); return; } } # Ensure that UI elements requiring revision ID have # the correct version information. $wgOut->setRevisionId($this->getRevIdFetched()); # Preload timestamp to avoid a DB hit $wgOut->setRevisionTimestamp($this->getTimestamp()); # Pages containing custom CSS or JavaScript get special treatment if ($this->getTitle()->isCssOrJsPage() || $this->getTitle()->isCssJsSubpage()) { wfDebug(__METHOD__ . ": showing CSS/JS source\n"); $this->showCssOrJsPage(); $outputDone = true; } elseif (!wfRunHooks('ArticleViewCustom', array($this->mContent, $this->getTitle(), $wgOut))) { # Allow extensions do their own custom view for certain pages $outputDone = true; } else { $text = $this->getContent(); $rt = Title::newFromRedirectArray($text); if ($rt) { wfDebug(__METHOD__ . ": showing redirect=no page\n"); # Viewing a redirect page (e.g. with parameter redirect=no) $wgOut->addHTML($this->viewRedirect($rt)); # Parse just to get categories, displaytitle, etc. $this->mParserOutput = $wgParser->parse($text, $this->getTitle(), $parserOptions); $wgOut->addParserOutputNoText($this->mParserOutput); $outputDone = true; } } break; case 4: # Run the parse, protected by a pool counter wfDebug(__METHOD__ . ": doing uncached parse\n"); $poolArticleView = new PoolWorkArticleView($this, $parserOptions, $this->getRevIdFetched(), $useParserCache, $this->getContent()); if (!$poolArticleView->execute()) { $error = $poolArticleView->getError(); if ($error) { $wgOut->clearHTML(); // for release() errors $wgOut->enableClientCache(false); $wgOut->setRobotPolicy('noindex,nofollow'); $errortext = $error->getWikiText(false, 'view-pool-error'); $wgOut->addWikiText('<div class="errorbox">' . $errortext . '</div>'); } # Connection or timeout error wfProfileOut(__METHOD__); return; } $this->mParserOutput = $poolArticleView->getParserOutput(); $wgOut->addParserOutput($this->mParserOutput); // Wikia change - begin - @author: wladek Transaction::setAttribute(Transaction::PARAM_PARSER_CACHE_USED, $poolArticleView->getIsDirty()); wfRunHooks('ArticleViewAddParserOutput', array($this, $this->mParserOutput)); // Wikia change - end # Don't cache a dirty ParserOutput object if ($poolArticleView->getIsDirty()) { $wgOut->setSquidMaxage(0); $wgOut->addHTML("<!-- parser cache is expired, sending anyway due to pool overload-->\n"); } # <Wikia> if (!$poolArticleView->getIsDirty()) { wfRunHooks('ArticleViewAfterParser', array($this, $this->mParserOutput)); } # </Wikia> $outputDone = true; break; # Should be unreachable, but just in case... # Should be unreachable, but just in case... default: break 2; } } # Get the ParserOutput actually *displayed* here. # Note that $this->mParserOutput is the *current* version output. $pOutput = $outputDone instanceof ParserOutput ? $outputDone : $this->mParserOutput; # Adjust title for main page & pages with displaytitle if ($pOutput) { $this->adjustDisplayTitle($pOutput); if ($pOutput->getText() == '') { \Wikia\Logger\WikiaLogger::instance()->error('PLATFORM-1212 - empty parser output'); } } # For the main page, overwrite the <title> element with the con- # tents of 'pagetitle-view-mainpage' instead of the default (if # that's not empty). # This message always exists because it is in the i18n files if ($this->getTitle()->isMainPage()) { $msg = wfMessage('pagetitle-view-mainpage')->inContentLanguage(); if (!$msg->isDisabled()) { $wgOut->setHTMLTitle($msg->title($this->getTitle())->text()); } } # Check for any __NOINDEX__ tags on the page using $pOutput $policy = $this->getRobotPolicy('view', $pOutput); $wgOut->setIndexPolicy($policy['index']); $wgOut->setFollowPolicy($policy['follow']); $this->showViewFooter(); $this->mPage->doViewUpdates($wgUser); wfProfileOut(__METHOD__); }