Example #1
0
 public function execute()
 {
     global $wgUser;
     $params = $this->extractRequestParams();
     if (is_null($params['text']) && is_null($params['appendtext']) && is_null($params['prependtext']) && $params['undo'] == 0) {
         $this->dieUsageMsg(array('missingtext'));
     }
     $titleObj = Title::newFromText($params['title']);
     if (!$titleObj || $titleObj->isExternal()) {
         $this->dieUsageMsg(array('invalidtitle', $params['title']));
     }
     if ($params['redirect']) {
         if ($titleObj->isRedirect()) {
             $oldTitle = $titleObj;
             $titles = Title::newFromRedirectArray(Revision::newFromTitle($oldTitle)->getText(Revision::FOR_THIS_USER));
             $redirValues = array();
             foreach ($titles as $id => $newTitle) {
                 if (!isset($titles[$id - 1])) {
                     $titles[$id - 1] = $oldTitle;
                 }
                 $redirValues[] = array('from' => $titles[$id - 1]->getPrefixedText(), 'to' => $newTitle->getPrefixedText());
                 $titleObj = $newTitle;
             }
             $this->getResult()->setIndexedTagName($redirValues, 'r');
             $this->getResult()->addValue(null, 'redirects', $redirValues);
         }
     }
     // Some functions depend on $wgTitle == $ep->mTitle
     global $wgTitle;
     $wgTitle = $titleObj;
     if ($params['createonly'] && $titleObj->exists()) {
         $this->dieUsageMsg(array('createonly-exists'));
     }
     if ($params['nocreate'] && !$titleObj->exists()) {
         $this->dieUsageMsg(array('nocreate-missing'));
     }
     // Now let's check whether we're even allowed to do this
     $errors = $titleObj->getUserPermissionsErrors('edit', $wgUser);
     if (!$titleObj->exists()) {
         $errors = array_merge($errors, $titleObj->getUserPermissionsErrors('create', $wgUser));
     }
     if (count($errors)) {
         $this->dieUsageMsg($errors[0]);
     }
     $articleObj = new Article($titleObj);
     $toMD5 = $params['text'];
     if (!is_null($params['appendtext']) || !is_null($params['prependtext'])) {
         // For non-existent pages, Article::getContent()
         // returns an interface message rather than ''
         // We do want getContent()'s behavior for non-existent
         // MediaWiki: pages, though
         if ($articleObj->getID() == 0 && $titleObj->getNamespace() != NS_MEDIAWIKI) {
             $content = '';
         } else {
             $content = $articleObj->getContent();
         }
         if (!is_null($params['section'])) {
             // Process the content for section edits
             global $wgParser;
             $section = intval($params['section']);
             $content = $wgParser->getSection($content, $section, false);
             if ($content === false) {
                 $this->dieUsage("There is no section {$section}.", 'nosuchsection');
             }
         }
         $params['text'] = $params['prependtext'] . $content . $params['appendtext'];
         $toMD5 = $params['prependtext'] . $params['appendtext'];
     }
     if ($params['undo'] > 0) {
         if ($params['undoafter'] > 0) {
             if ($params['undo'] < $params['undoafter']) {
                 list($params['undo'], $params['undoafter']) = array($params['undoafter'], $params['undo']);
             }
             $undoafterRev = Revision::newFromID($params['undoafter']);
         }
         $undoRev = Revision::newFromID($params['undo']);
         if (is_null($undoRev) || $undoRev->isDeleted(Revision::DELETED_TEXT)) {
             $this->dieUsageMsg(array('nosuchrevid', $params['undo']));
         }
         if ($params['undoafter'] == 0) {
             $undoafterRev = $undoRev->getPrevious();
         }
         if (is_null($undoafterRev) || $undoafterRev->isDeleted(Revision::DELETED_TEXT)) {
             $this->dieUsageMsg(array('nosuchrevid', $params['undoafter']));
         }
         if ($undoRev->getPage() != $articleObj->getID()) {
             $this->dieUsageMsg(array('revwrongpage', $undoRev->getID(), $titleObj->getPrefixedText()));
         }
         if ($undoafterRev->getPage() != $articleObj->getID()) {
             $this->dieUsageMsg(array('revwrongpage', $undoafterRev->getID(), $titleObj->getPrefixedText()));
         }
         $newtext = $articleObj->getUndoText($undoRev, $undoafterRev);
         if ($newtext === false) {
             $this->dieUsageMsg(array('undo-failure'));
         }
         $params['text'] = $newtext;
         // If no summary was given and we only undid one rev,
         // use an autosummary
         if (is_null($params['summary']) && $titleObj->getNextRevisionID($undoafterRev->getID()) == $params['undo']) {
             $params['summary'] = wfMsgForContent('undo-summary', $params['undo'], $undoRev->getUserText());
         }
     }
     // See if the MD5 hash checks out
     if (!is_null($params['md5']) && md5($toMD5) !== $params['md5']) {
         $this->dieUsageMsg(array('hashcheckfailed'));
     }
     $ep = new EditPage($articleObj);
     // EditPage wants to parse its stuff from a WebRequest
     // That interface kind of sucks, but it's workable
     $reqArr = array('wpTextbox1' => $params['text'], 'wpEditToken' => $params['token'], 'wpIgnoreBlankSummary' => '');
     if (!is_null($params['summary'])) {
         $reqArr['wpSummary'] = $params['summary'];
     }
     // Watch out for basetimestamp == ''
     // wfTimestamp() treats it as NOW, almost certainly causing an edit conflict
     if (!is_null($params['basetimestamp']) && $params['basetimestamp'] != '') {
         $reqArr['wpEdittime'] = wfTimestamp(TS_MW, $params['basetimestamp']);
     } else {
         $reqArr['wpEdittime'] = $articleObj->getTimestamp();
     }
     if (!is_null($params['starttimestamp']) && $params['starttimestamp'] != '') {
         $reqArr['wpStarttime'] = wfTimestamp(TS_MW, $params['starttimestamp']);
     } else {
         $reqArr['wpStarttime'] = wfTimestampNow();
         // Fake wpStartime
     }
     if ($params['minor'] || !$params['notminor'] && $wgUser->getOption('minordefault')) {
         $reqArr['wpMinoredit'] = '';
     }
     if ($params['recreate']) {
         $reqArr['wpRecreate'] = '';
     }
     if (!is_null($params['section'])) {
         $section = intval($params['section']);
         if ($section == 0 && $params['section'] != '0' && $params['section'] != 'new') {
             $this->dieUsage("The section parameter must be set to an integer or 'new'", "invalidsection");
         }
         $reqArr['wpSection'] = $params['section'];
     } else {
         $reqArr['wpSection'] = '';
     }
     $watch = $this->getWatchlistValue($params['watchlist'], $titleObj);
     // Deprecated parameters
     if ($params['watch']) {
         $watch = true;
     } elseif ($params['unwatch']) {
         $watch = false;
     }
     if ($watch) {
         $reqArr['wpWatchthis'] = '';
     }
     $req = new FauxRequest($reqArr, true);
     $ep->importFormData($req);
     // Run hooks
     // Handle CAPTCHA parameters
     global $wgRequest;
     if (!is_null($params['captchaid'])) {
         $wgRequest->setVal('wpCaptchaId', $params['captchaid']);
     }
     if (!is_null($params['captchaword'])) {
         $wgRequest->setVal('wpCaptchaWord', $params['captchaword']);
     }
     $r = array();
     if (!wfRunHooks('APIEditBeforeSave', array($ep, $ep->textbox1, &$r))) {
         if (count($r)) {
             $r['result'] = 'Failure';
             $this->getResult()->addValue(null, $this->getModuleName(), $r);
             return;
         } else {
             $this->dieUsageMsg(array('hookaborted'));
         }
     }
     // Do the actual save
     $oldRevId = $articleObj->getRevIdFetched();
     $result = null;
     // Fake $wgRequest for some hooks inside EditPage
     // FIXME: This interface SUCKS
     $oldRequest = $wgRequest;
     $wgRequest = $req;
     $retval = $ep->internalAttemptSave($result, $wgUser->isAllowed('bot') && $params['bot']);
     $wgRequest = $oldRequest;
     global $wgMaxArticleSize;
     switch ($retval) {
         case EditPage::AS_HOOK_ERROR:
         case EditPage::AS_HOOK_ERROR_EXPECTED:
             $this->dieUsageMsg(array('hookaborted'));
         case EditPage::AS_IMAGE_REDIRECT_ANON:
             $this->dieUsageMsg(array('noimageredirect-anon'));
         case EditPage::AS_IMAGE_REDIRECT_LOGGED:
             $this->dieUsageMsg(array('noimageredirect-logged'));
         case EditPage::AS_SPAM_ERROR:
             $this->dieUsageMsg(array('spamdetected', $result['spam']));
         case EditPage::AS_FILTERING:
             $this->dieUsageMsg(array('filtered'));
         case EditPage::AS_BLOCKED_PAGE_FOR_USER:
             $this->dieUsageMsg(array('blockedtext'));
         case EditPage::AS_MAX_ARTICLE_SIZE_EXCEEDED:
         case EditPage::AS_CONTENT_TOO_BIG:
             $this->dieUsageMsg(array('contenttoobig', $wgMaxArticleSize));
         case EditPage::AS_READ_ONLY_PAGE_ANON:
             $this->dieUsageMsg(array('noedit-anon'));
         case EditPage::AS_READ_ONLY_PAGE_LOGGED:
             $this->dieUsageMsg(array('noedit'));
         case EditPage::AS_READ_ONLY_PAGE:
             $this->dieReadOnly();
         case EditPage::AS_RATE_LIMITED:
             $this->dieUsageMsg(array('actionthrottledtext'));
         case EditPage::AS_ARTICLE_WAS_DELETED:
             $this->dieUsageMsg(array('wasdeleted'));
         case EditPage::AS_NO_CREATE_PERMISSION:
             $this->dieUsageMsg(array('nocreate-loggedin'));
         case EditPage::AS_BLANK_ARTICLE:
             $this->dieUsageMsg(array('blankpage'));
         case EditPage::AS_CONFLICT_DETECTED:
             $this->dieUsageMsg(array('editconflict'));
             // case EditPage::AS_SUMMARY_NEEDED: Can't happen since we set wpIgnoreBlankSummary
         // case EditPage::AS_SUMMARY_NEEDED: Can't happen since we set wpIgnoreBlankSummary
         case EditPage::AS_TEXTBOX_EMPTY:
             $this->dieUsageMsg(array('emptynewsection'));
         case EditPage::AS_SUCCESS_NEW_ARTICLE:
             $r['new'] = '';
         case EditPage::AS_SUCCESS_UPDATE:
             $r['result'] = 'Success';
             $r['pageid'] = intval($titleObj->getArticleID());
             $r['title'] = $titleObj->getPrefixedText();
             // HACK: We create a new Article object here because getRevIdFetched()
             // refuses to be run twice, and because Title::getLatestRevId()
             // won't fetch from the master unless we select for update, which we
             // don't want to do.
             $newArticle = new Article($titleObj);
             $newRevId = $newArticle->getRevIdFetched();
             if ($newRevId == $oldRevId) {
                 $r['nochange'] = '';
             } else {
                 $r['oldrevid'] = intval($oldRevId);
                 $r['newrevid'] = intval($newRevId);
                 $r['newtimestamp'] = wfTimestamp(TS_ISO_8601, $newArticle->getTimestamp());
             }
             break;
         case EditPage::AS_SUMMARY_NEEDED:
             $this->dieUsageMsg(array('summaryrequired'));
         case EditPage::AS_END:
             // This usually means some kind of race condition
             // or DB weirdness occurred. Fall through to throw an unknown
             // error.
             // This needs fixing higher up, as Article::doEdit should be
             // used rather than Article::updateArticle, so that specific
             // error conditions can be returned
         // This usually means some kind of race condition
         // or DB weirdness occurred. Fall through to throw an unknown
         // error.
         // This needs fixing higher up, as Article::doEdit should be
         // used rather than Article::updateArticle, so that specific
         // error conditions can be returned
         default:
             $this->dieUsageMsg(array('unknownerror', $retval));
     }
     $this->getResult()->addValue(null, $this->getModuleName(), $r);
 }
Example #2
0
 /**
  * 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;
     wfProfileIn(__METHOD__);
     # Get variables from query string
     $oldid = $this->getOldID();
     $parserCache = ParserCache::singleton();
     $parserOptions = $this->getParserOptions();
     # Render printable version, use printable version cache
     if ($wgOut->isPrintable()) {
         $parserOptions->setIsPrintable(true);
         $parserOptions->setEditSection(false);
     } else {
         if ($wgUseETag && !$this->mTitle->quickUserCan('edit')) {
             $parserOptions->setEditSection(false);
         }
     }
     # Try client and file cache
     if ($oldid === 0 && $this->checkTouched()) {
         if ($wgUseETag) {
             $wgOut->setETag($parserCache->getETag($this, $parserOptions));
         }
         # Is it client cached?
         if ($wgOut->checkLastModified($this->getTouched())) {
             wfDebug(__METHOD__ . ": done 304\n");
             wfProfileOut(__METHOD__);
             return;
             # Try file cache
         } else {
             if ($wgUseFileCache && $this->tryFileCache()) {
                 wfDebug(__METHOD__ . ": done file cache\n");
                 # tell wgOut that output is taken care of
                 $wgOut->disable();
                 $this->viewUpdates();
                 wfProfileOut(__METHOD__);
                 return;
             }
         }
     }
     # getOldID may want us to redirect somewhere else
     if ($this->mRedirectUrl) {
         $wgOut->redirect($this->mRedirectUrl);
         wfDebug(__METHOD__ . ": redirecting due to oldid\n");
         wfProfileOut(__METHOD__);
         return;
     }
     $wgOut->setArticleFlag(true);
     # Set page title (may be overridden by DISPLAYTITLE)
     $wgOut->setPageTitle($this->mTitle->getPrefixedText());
     # 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;
     }
     # Allow frames by default
     $wgOut->allowClickjacking();
     if (!$wgUseETag && !$this->mTitle->quickUserCan('edit')) {
         $parserOptions->setEditSection(false);
     }
     # Should the parser cache be used?
     $useParserCache = $this->useParserCache($oldid);
     wfDebug('Article::view using parser cache: ' . ($useParserCache ? 'yes' : 'no') . "\n");
     if ($wgUser->getStubThreshold()) {
         wfIncrStats('pcache_miss_stub');
     }
     $wasRedirected = $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:
                 # Try the parser cache
                 if ($useParserCache) {
                     $this->mParserOutput = $parserCache->get($this, $parserOptions);
                     if ($this->mParserOutput !== false) {
                         wfDebug(__METHOD__ . ": showing parser cache contents\n");
                         $wgOut->addParserOutput($this->mParserOutput);
                         # Ensure that UI elements requiring revision ID have
                         # the correct version information.
                         $wgOut->setRevisionId($this->mLatest);
                         $outputDone = true;
                     }
                 }
                 break;
             case 3:
                 $text = $this->getContent();
                 if ($text === false || $this->getID() == 0) {
                     wfDebug(__METHOD__ . ": showing missing article\n");
                     $this->showMissingArticle();
                     wfProfileOut(__METHOD__);
                     return;
                 }
                 # Another whitelist check in case oldid is altering the title
                 if (!$this->mTitle->userCanRead()) {
                     wfDebug(__METHOD__ . ": denied on secondary read check\n");
                     $wgOut->loginToUse();
                     $wgOut->output();
                     $wgOut->disable();
                     wfProfileOut(__METHOD__);
                     return;
                 }
                 # Are we looking at an old revision
                 if ($oldid && !is_null($this->mRevision)) {
                     $this->setOldSubtitle($oldid);
                     if (!$this->showDeletedRevisionHeader()) {
                         wfDebug(__METHOD__ . ": cannot view deleted revision\n");
                         wfProfileOut(__METHOD__);
                         return;
                     }
                     # If this "old" version is the current, then try the parser cache...
                     if ($oldid === $this->getLatest() && $this->useParserCache(false)) {
                         $this->mParserOutput = $parserCache->get($this, $parserOptions);
                         if ($this->mParserOutput) {
                             wfDebug(__METHOD__ . ": showing parser cache for current rev permalink\n");
                             $wgOut->addParserOutput($this->mParserOutput);
                             $wgOut->setRevisionId($this->mLatest);
                             $outputDone = true;
                             break;
                         }
                     }
                 }
                 # Ensure that UI elements requiring revision ID have
                 # the correct version information.
                 $wgOut->setRevisionId($this->getRevIdFetched());
                 # Pages containing custom CSS or JavaScript get special treatment
                 if ($this->mTitle->isCssOrJsPage() || $this->mTitle->isCssJsSubpage()) {
                     wfDebug(__METHOD__ . ": showing CSS/JS source\n");
                     $this->showCssOrJsPage();
                     $outputDone = true;
                 } else {
                     $rt = Title::newFromRedirectArray($text);
                     if ($rt) {
                         wfDebug(__METHOD__ . ": showing redirect=no page\n");
                         # Viewing a redirect page (e.g. with parameter redirect=no)
                         # Don't append the subtitle if this was an old revision
                         $wgOut->addHTML($this->viewRedirect($rt, !$wasRedirected && $this->isCurrent()));
                         # Parse just to get categories, displaytitle, etc.
                         $this->mParserOutput = $wgParser->parse($text, $this->mTitle, $parserOptions);
                         $wgOut->addParserOutputNoText($this->mParserOutput);
                         $outputDone = true;
                     }
                 }
                 break;
             case 4:
                 # Run the parse, protected by a pool counter
                 wfDebug(__METHOD__ . ": doing uncached parse\n");
                 $key = $parserCache->getKey($this, $parserOptions);
                 $poolArticleView = new PoolWorkArticleView($this, $key, $useParserCache, $parserOptions);
                 if (!$poolArticleView->execute()) {
                     # Connection or timeout error
                     wfProfileOut(__METHOD__);
                     return;
                 } else {
                     $outputDone = true;
                 }
                 break;
                 # Should be unreachable, but just in case...
             # Should be unreachable, but just in case...
             default:
                 break 2;
         }
     }
     # Adjust the title if it was set by displaytitle, -{T|}- or language conversion
     if ($this->mParserOutput) {
         $titleText = $this->mParserOutput->getTitleText();
         if (strval($titleText) !== '') {
             $wgOut->setPageTitle($titleText);
         }
     }
     # 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->mTitle->equals(Title::newMainPage()) && ($m = wfMsgForContent('pagetitle-view-mainpage')) !== '') {
         $wgOut->setHTMLTitle($m);
     }
     # Now that we've filled $this->mParserOutput, we know whether
     # there are any __NOINDEX__ tags on the page
     $policy = $this->getRobotPolicy('view');
     $wgOut->setIndexPolicy($policy['index']);
     $wgOut->setFollowPolicy($policy['follow']);
     $this->showViewFooter();
     $this->viewUpdates();
     wfProfileOut(__METHOD__);
 }
 protected function getRedirectHtml($text)
 {
     $rTargets = Title::newFromRedirectArray($text);
     if ($rTargets) {
         $article = new Article($this->article->getTitle());
         return $article->viewRedirect($rTargets);
     }
     return '';
 }
Example #4
0
 /**
  * Get the rendered text for previewing.
  * @return string
  */
 function getPreviewText()
 {
     global $wgOut, $wgUser, $wgParser, $wgRawHtml;
     wfProfileIn(__METHOD__);
     if ($wgRawHtml && !$this->mTokenOk) {
         // Could be an offsite preview attempt. This is very unsafe if
         // HTML is enabled, as it could be an attack.
         $parsedNote = '';
         if ($this->textbox1 !== '') {
             // Do not put big scary notice, if previewing the empty
             // string, which happens when you initially edit
             // a category page, due to automatic preview-on-open.
             $parsedNote = $wgOut->parse("<div class='previewnote'>" . wfMsg('session_fail_preview_html') . "</div>", true, true);
         }
         wfProfileOut(__METHOD__);
         return $parsedNote;
     }
     if ($this->mTriedSave && !$this->mTokenOk) {
         if ($this->mTokenOkExceptSuffix) {
             $note = wfMsg('token_suffix_mismatch');
         } else {
             $note = wfMsg('session_fail_preview');
         }
     } elseif ($this->incompleteForm) {
         $note = wfMsg('edit_form_incomplete');
     } else {
         $note = wfMsg('previewnote');
     }
     $parserOptions = ParserOptions::newFromUser($wgUser);
     $parserOptions->setEditSection(false);
     $parserOptions->setTidy(true);
     $parserOptions->setIsPreview(true);
     $parserOptions->setIsSectionPreview(!is_null($this->section) && $this->section !== '');
     # don't parse non-wikitext pages, show message about preview
     # XXX: stupid php bug won't let us use $this->getContextTitle()->isCssJsSubpage() here -- This note has been there since r3530. Sure the bug was fixed time ago?
     if ($this->isCssJsSubpage || !$this->mTitle->isWikitextPage()) {
         if ($this->mTitle->isCssJsSubpage()) {
             $level = 'user';
         } elseif ($this->mTitle->isCssOrJsPage()) {
             $level = 'site';
         } else {
             $level = false;
         }
         # Used messages to make sure grep find them:
         # Messages: usercsspreview, userjspreview, sitecsspreview, sitejspreview
         if ($level) {
             if (preg_match("/\\.css\$/", $this->mTitle->getText())) {
                 $previewtext = "<div id='mw-{$level}csspreview'>\n" . wfMsg("{$level}csspreview") . "\n</div>";
                 $class = "mw-code mw-css";
             } elseif (preg_match("/\\.js\$/", $this->mTitle->getText())) {
                 $previewtext = "<div id='mw-{$level}jspreview'>\n" . wfMsg("{$level}jspreview") . "\n</div>";
                 $class = "mw-code mw-js";
             } else {
                 throw new MWException('A CSS/JS (sub)page but which is not css nor js!');
             }
         }
         $parserOutput = $wgParser->parse($previewtext, $this->mTitle, $parserOptions);
         $previewHTML = $parserOutput->mText;
         $previewHTML .= "<pre class=\"{$class}\" dir=\"ltr\">\n" . htmlspecialchars($this->textbox1) . "\n</pre>\n";
     } else {
         $rt = Title::newFromRedirectArray($this->textbox1);
         if ($rt) {
             $previewHTML = $this->mArticle->viewRedirect($rt, false);
         } else {
             $toparse = $this->textbox1;
             # If we're adding a comment, we need to show the
             # summary as the headline
             if ($this->section == "new" && $this->summary != "") {
                 $toparse = wfMsgForContent('newsectionheaderdefaultlevel', $this->summary) . "\n\n" . $toparse;
             }
             wfRunHooks('EditPageGetPreviewText', array($this, &$toparse));
             $parserOptions->enableLimitReport();
             $toparse = $wgParser->preSaveTransform($toparse, $this->mTitle, $wgUser, $parserOptions);
             $parserOutput = $wgParser->parse($toparse, $this->mTitle, $parserOptions);
             $previewHTML = $parserOutput->getText();
             $this->mParserOutput = $parserOutput;
             $wgOut->addParserOutputNoText($parserOutput);
             if (count($parserOutput->getWarnings())) {
                 $note .= "\n\n" . implode("\n\n", $parserOutput->getWarnings());
             }
         }
     }
     if ($this->isConflict) {
         $conflict = '<h2 id="mw-previewconflict">' . htmlspecialchars(wfMsg('previewconflict')) . "</h2>\n";
     } else {
         $conflict = '<hr />';
     }
     $previewhead = "<div class='previewnote'>\n" . '<h2 id="mw-previewheader">' . htmlspecialchars(wfMsg('preview')) . "</h2>" . $wgOut->parse($note, true, true) . $conflict . "</div>\n";
     $pageLang = $this->mTitle->getPageLanguage();
     $attribs = array('lang' => $pageLang->getCode(), 'dir' => $pageLang->getDir(), 'class' => 'mw-content-' . $pageLang->getDir());
     $previewHTML = Html::rawElement('div', $attribs, $previewHTML);
     wfProfileOut(__METHOD__);
     return $previewhead . $previewHTML . $this->previewTextAfterContent;
 }
Example #5
0
 /**
  * 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__);
 }
Example #6
0
 /**
  * Get the rendered text for previewing.
  * @return string
  */
 function getPreviewText()
 {
     global $wgOut, $wgUser, $wgTitle, $wgParser, $wgLang, $wgContLang, $wgMessageCache;
     wfProfileIn(__METHOD__);
     if ($this->mTriedSave && !$this->mTokenOk) {
         if ($this->mTokenOkExceptSuffix) {
             $note = wfMsg('token_suffix_mismatch');
         } else {
             $note = wfMsg('session_fail_preview');
         }
     } else {
         $note = wfMsg('previewnote');
     }
     $parserOptions = ParserOptions::newFromUser($wgUser);
     $parserOptions->setEditSection(false);
     $parserOptions->setIsPreview(true);
     $parserOptions->setIsSectionPreview(!is_null($this->section) && $this->section !== '');
     global $wgRawHtml;
     if ($wgRawHtml && !$this->mTokenOk) {
         // Could be an offsite preview attempt. This is very unsafe if
         // HTML is enabled, as it could be an attack.
         return $wgOut->parse("<div class='previewnote'>" . wfMsg('session_fail_preview_html') . "</div>");
     }
     # don't parse user css/js, show message about preview
     # XXX: stupid php bug won't let us use $wgTitle->isCssJsSubpage() here
     if ($this->isCssJsSubpage) {
         if (preg_match("/\\.css\$/", $this->mTitle->getText())) {
             $previewtext = wfMsg('usercsspreview');
         } else {
             if (preg_match("/\\.js\$/", $this->mTitle->getText())) {
                 $previewtext = wfMsg('userjspreview');
             }
         }
         $parserOptions->setTidy(true);
         $parserOutput = $wgParser->parse($previewtext, $this->mTitle, $parserOptions);
         $previewHTML = $parserOutput->mText;
     } elseif ($rt = Title::newFromRedirectArray($this->textbox1)) {
         $previewHTML = $this->mArticle->viewRedirect($rt, false);
     } else {
         $toparse = $this->textbox1;
         # If we're adding a comment, we need to show the
         # summary as the headline
         if ($this->section == "new" && $this->summary != "") {
             $toparse = "== {$this->summary} ==\n\n" . $toparse;
         }
         if ($this->mMetaData != "") {
             $toparse .= "\n" . $this->mMetaData;
         }
         // Parse mediawiki messages with correct target language
         if ($this->mTitle->getNamespace() == NS_MEDIAWIKI) {
             list(, $lang) = $wgMessageCache->figureMessage($this->mTitle->getText());
             $obj = wfGetLangObj($lang);
             $parserOptions->setTargetLanguage($obj);
         }
         $parserOptions->setTidy(true);
         $parserOptions->enableLimitReport();
         $parserOutput = $wgParser->parse($this->mArticle->preSaveTransform($toparse), $this->mTitle, $parserOptions);
         $previewHTML = $parserOutput->getText();
         $this->mParserOutput = $parserOutput;
         $wgOut->addParserOutputNoText($parserOutput);
         if (count($parserOutput->getWarnings())) {
             $note .= "\n\n" . implode("\n\n", $parserOutput->getWarnings());
         }
     }
     $previewhead = '<h2>' . htmlspecialchars(wfMsg('preview')) . "</h2>\n" . "<div class='previewnote'>" . $wgOut->parse($note) . "</div>\n";
     if ($this->isConflict) {
         $previewhead .= '<h2>' . htmlspecialchars(wfMsg('previewconflict')) . "</h2>\n";
     }
     wfProfileOut(__METHOD__);
     return $previewhead . $previewHTML;
 }
Example #7
0
 /**
  * Get the rendered text for previewing.
  * @return string
  */
 function getPreviewText()
 {
     global $wgOut, $wgUser, $wgParser, $wgMessageCache;
     wfProfileIn(__METHOD__);
     if ($this->mTriedSave && !$this->mTokenOk) {
         if ($this->mTokenOkExceptSuffix) {
             $note = wfMsg('token_suffix_mismatch');
         } else {
             $note = wfMsg('session_fail_preview');
         }
     } else {
         $note = wfMsg('previewnote');
     }
     $parserOptions = ParserOptions::newFromUser($wgUser);
     $parserOptions->setEditSection(false);
     $parserOptions->setIsPreview(true);
     $parserOptions->setIsSectionPreview(!is_null($this->section) && $this->section !== '');
     global $wgRawHtml;
     if ($wgRawHtml && !$this->mTokenOk) {
         // Could be an offsite preview attempt. This is very unsafe if
         // HTML is enabled, as it could be an attack.
         $parsedNote = $wgOut->parse("<div class='previewnote'>" . wfMsg('session_fail_preview_html') . "</div>");
         wfProfileOut(__METHOD__);
         return $parsedNote;
     }
     # don't parse user css/js, show message about preview
     # XXX: stupid php bug won't let us use $wgTitle->isCssJsSubpage() here -- This note has been there since r3530. Sure the bug was fixed time ago?
     if ($this->isCssJsSubpage || $this->mTitle->isCssOrJsPage()) {
         $level = 'user';
         if ($this->mTitle->getNamespace() == NS_MEDIAWIKI) {
             $level = 'site';
         }
         # Used messages to make sure grep find them:
         # Messages: usercsspreview, userjspreview, sitecsspreview, sitejspreview
         if (preg_match("/\\.css\$/", $this->mTitle->getText())) {
             $previewtext = "<div id='mw-{$level}csspreview'>\n" . wfMsg("{$level}csspreview") . "\n</div>";
             $class = "mw-code mw-css";
         } elseif (preg_match("/\\.js\$/", $this->mTitle->getText())) {
             $previewtext = "<div id='mw-{$level}jspreview'>\n" . wfMsg("{$level}jspreview") . "\n</div>";
             $class = "mw-code mw-js";
         } else {
             throw new MWException('A CSS/JS (sub)page but which is not css nor js!');
         }
         $parserOptions->setTidy(true);
         $parserOutput = $wgParser->parse($previewtext, $this->mTitle, $parserOptions);
         $previewHTML = $parserOutput->mText;
         $previewHTML .= "<pre class=\"{$class}\" dir=\"ltr\">\n" . htmlspecialchars($this->textbox1) . "\n</pre>\n";
     } else {
         $rt = Title::newFromRedirectArray($this->textbox1);
         if ($rt) {
             $previewHTML = $this->mArticle->viewRedirect($rt, false);
         } else {
             $toparse = $this->textbox1;
             # If we're adding a comment, we need to show the
             # summary as the headline
             if ($this->section == "new" && $this->summary != "") {
                 $toparse = "== {$this->summary} ==\n\n" . $toparse;
             }
             wfRunHooks('EditPageGetPreviewText', array($this, &$toparse));
             // Parse mediawiki messages with correct target language
             if ($this->mTitle->getNamespace() == NS_MEDIAWIKI) {
                 list(, $lang) = $wgMessageCache->figureMessage($this->mTitle->getText());
                 $obj = wfGetLangObj($lang);
                 $parserOptions->setTargetLanguage($obj);
             }
             $parserOptions->setTidy(true);
             $parserOptions->enableLimitReport();
             $parserOutput = $wgParser->parse($this->mArticle->preSaveTransform($toparse), $this->mTitle, $parserOptions);
             $previewHTML = $parserOutput->getText();
             $this->mParserOutput = $parserOutput;
             $wgOut->addParserOutputNoText($parserOutput);
             if (count($parserOutput->getWarnings())) {
                 $note .= "\n\n" . implode("\n\n", $parserOutput->getWarnings());
             }
         }
     }
     if ($this->isConflict) {
         $conflict = '<h2 id="mw-previewconflict">' . htmlspecialchars(wfMsg('previewconflict')) . "</h2>\n";
     } else {
         $conflict = '<hr />';
     }
     $previewhead = "<div class='previewnote'>\n" . '<h2 id="mw-previewheader">' . htmlspecialchars(wfMsg('preview')) . "</h2>" . $wgOut->parse($note) . $conflict . "</div>\n";
     wfProfileOut(__METHOD__);
     return $previewhead . $previewHTML . $this->previewTextAfterContent;
 }
Example #8
0
 /**
  * This is the default action of the script: just view the page of
  * the given title.
  */
 public function view()
 {
     global $wgUser, $wgOut, $wgRequest, $wgContLang;
     global $wgEnableParserCache, $wgStylePath, $wgParser;
     global $wgUseTrackbacks, $wgNamespaceRobotPolicies, $wgArticleRobotPolicies;
     global $wgDefaultRobotPolicy;
     # Let the parser know if this is the printable version
     if ($wgOut->isPrintable()) {
         $wgOut->parserOptions()->setIsPrintable(true);
     }
     wfProfileIn(__METHOD__);
     # Get variables from query string
     $oldid = $this->getOldID();
     # Try client and file cache
     if ($oldid === 0 && $this->checkTouched()) {
         global $wgUseETag;
         if ($wgUseETag) {
             $parserCache = ParserCache::singleton();
             $wgOut->setETag($parserCache->getETag($this, $wgOut->parserOptions()));
         }
         # Is is client cached?
         if ($wgOut->checkLastModified($this->getTouched())) {
             wfProfileOut(__METHOD__);
             return;
             # Try file cache
         } else {
             if ($this->tryFileCache()) {
                 # tell wgOut that output is taken care of
                 $wgOut->disable();
                 $this->viewUpdates();
                 wfProfileOut(__METHOD__);
                 return;
             }
         }
     }
     $ns = $this->mTitle->getNamespace();
     # shortcut
     $sk = $wgUser->getSkin();
     # getOldID may want us to redirect somewhere else
     if ($this->mRedirectUrl) {
         $wgOut->redirect($this->mRedirectUrl);
         wfProfileOut(__METHOD__);
         return;
     }
     $diff = $wgRequest->getVal('diff');
     $rcid = $wgRequest->getVal('rcid');
     $rdfrom = $wgRequest->getVal('rdfrom');
     $diffOnly = $wgRequest->getBool('diffonly', $wgUser->getOption('diffonly'));
     $purge = $wgRequest->getVal('action') == 'purge';
     $return404 = false;
     $wgOut->setArticleFlag(true);
     # Discourage indexing of printable versions, but encourage following
     if ($wgOut->isPrintable()) {
         $policy = 'noindex,follow';
     } elseif (isset($wgArticleRobotPolicies[$this->mTitle->getPrefixedText()])) {
         $policy = $wgArticleRobotPolicies[$this->mTitle->getPrefixedText()];
     } elseif (isset($wgNamespaceRobotPolicies[$ns])) {
         # Honour customised robot policies for this namespace
         $policy = $wgNamespaceRobotPolicies[$ns];
     } else {
         $policy = $wgDefaultRobotPolicy;
     }
     $wgOut->setRobotPolicy($policy);
     # Allow admins to see deleted content if explicitly requested
     $delId = $diff ? $diff : $oldid;
     $unhide = $wgRequest->getInt('unhide') == 1 && $wgUser->matchEditToken($wgRequest->getVal('token'), $delId);
     # If we got diff and oldid in the query, we want to see a
     # diff page instead of the article.
     if (!is_null($diff)) {
         $wgOut->setPageTitle($this->mTitle->getPrefixedText());
         $htmldiff = $wgRequest->getVal('htmldiff', false);
         $de = new DifferenceEngine($this->mTitle, $oldid, $diff, $rcid, $purge, $htmldiff, $unhide);
         // DifferenceEngine directly fetched the revision:
         $this->mRevIdFetched = $de->mNewid;
         $de->showDiffPage($diffOnly);
         // Needed to get the page's current revision
         $this->loadPageData();
         if ($diff == 0 || $diff == $this->mLatest) {
             # Run view updates for current revision only
             $this->viewUpdates();
         }
         wfProfileOut(__METHOD__);
         return;
     }
     if ($ns == NS_USER || $ns == NS_USER_TALK) {
         # User/User_talk subpages are not modified. (bug 11443)
         if (!$this->mTitle->isSubpage()) {
             $block = new Block();
             if ($block->load($this->mTitle->getBaseText())) {
                 $wgOut->setRobotpolicy('noindex,nofollow');
             }
         }
     }
     # Should the parser cache be used?
     $pcache = $this->useParserCache($oldid);
     wfDebug('Article::view using parser cache: ' . ($pcache ? 'yes' : 'no') . "\n");
     if ($wgUser->getOption('stubthreshold')) {
         wfIncrStats('pcache_miss_stub');
     }
     $wasRedirected = false;
     if (isset($this->mRedirectedFrom)) {
         // This is an internally redirected page view.
         // We'll need a backlink to the source page for navigation.
         if (wfRunHooks('ArticleViewRedirect', array(&$this))) {
             $redir = $sk->makeKnownLinkObj($this->mRedirectedFrom, '', 'redirect=no');
             $s = wfMsgExt('redirectedfrom', array('parseinline', 'replaceafter'), $redir);
             $wgOut->setSubtitle($s);
             // Set the fragment if one was specified in the redirect
             if (strval($this->mTitle->getFragment()) != '') {
                 $fragment = Xml::escapeJsString($this->mTitle->getFragmentForURL());
                 $wgOut->addInlineScript("redirectToFragment(\"{$fragment}\");");
             }
             // Add a <link rel="canonical"> tag
             $wgOut->addLink(array('rel' => 'canonical', 'href' => $this->mTitle->getLocalURL()));
             $wasRedirected = true;
         }
     } elseif (!empty($rdfrom)) {
         // This is an externally redirected view, from some other wiki.
         // If it was reported from a trusted site, supply a backlink.
         global $wgRedirectSources;
         if ($wgRedirectSources && preg_match($wgRedirectSources, $rdfrom)) {
             $redir = $sk->makeExternalLink($rdfrom, $rdfrom);
             $s = wfMsgExt('redirectedfrom', array('parseinline', 'replaceafter'), $redir);
             $wgOut->setSubtitle($s);
             $wasRedirected = true;
         }
     }
     $outputDone = false;
     wfRunHooks('ArticleViewHeader', array(&$this, &$outputDone, &$pcache));
     if ($pcache && $wgOut->tryParserCache($this)) {
         // Ensure that UI elements requiring revision ID have
         // the correct version information.
         $wgOut->setRevisionId($this->mLatest);
         $outputDone = true;
     }
     # Fetch content and check for errors
     if (!$outputDone) {
         # If the article does not exist and was deleted, show the log
         if ($this->getID() == 0) {
             $this->showDeletionLog();
         }
         $text = $this->getContent();
         // For now, check also for ID until getContent actually returns
         // false for pages that do not exists
         if ($text === false || $this->getID() === 0) {
             # Failed to load, replace text with error message
             $t = $this->mTitle->getPrefixedText();
             if ($oldid) {
                 $d = wfMsgExt('missingarticle-rev', 'escape', $oldid);
                 $text = wfMsgExt('missing-article', 'parsemag', $t, $d);
                 // Always use page content for pages in the MediaWiki namespace
                 // since it contains the default message
             } elseif ($this->mTitle->getNamespace() != NS_MEDIAWIKI) {
                 $text = wfMsgExt('noarticletext', 'parsemag');
             }
         }
         # Non-existent pages
         if ($this->getID() === 0) {
             $wgOut->setRobotPolicy('noindex,nofollow');
             $text = "<div class='noarticletext'>\n{$text}\n</div>";
             if (!$this->hasViewableContent()) {
                 // If there's no backing content, send a 404 Not Found
                 // for better machine handling of broken links.
                 $return404 = true;
             }
         }
         if ($return404) {
             $wgRequest->response()->header("HTTP/1.x 404 Not Found");
         }
         # Another whitelist check in case oldid is altering the title
         if (!$this->mTitle->userCanRead()) {
             $wgOut->loginToUse();
             $wgOut->output();
             $wgOut->disable();
             wfProfileOut(__METHOD__);
             return;
         }
         # For ?curid=x urls, disallow indexing
         if ($wgRequest->getInt('curid')) {
             $wgOut->setRobotPolicy('noindex,follow');
         }
         # We're looking at an old revision
         if (!empty($oldid)) {
             $wgOut->setRobotPolicy('noindex,nofollow');
             if (is_null($this->mRevision)) {
                 // FIXME: This would be a nice place to load the 'no such page' text.
             } else {
                 $this->setOldSubtitle(isset($this->mOldId) ? $this->mOldId : $oldid);
                 # Allow admins to see deleted content if explicitly requested
                 if ($this->mRevision->isDeleted(Revision::DELETED_TEXT)) {
                     if (!$unhide || !$this->mRevision->userCan(Revision::DELETED_TEXT)) {
                         $wgOut->wrapWikiMsg("<div class='mw-warning plainlinks'>\n\$1</div>\n", 'rev-deleted-text-permission');
                         $wgOut->setPageTitle($this->mTitle->getPrefixedText());
                         wfProfileOut(__METHOD__);
                         return;
                     } else {
                         $wgOut->wrapWikiMsg("<div class='mw-warning plainlinks'>\n\$1</div>\n", 'rev-deleted-text-view');
                         // and we are allowed to see...
                     }
                 }
                 // Is this the current revision and otherwise cacheable? Try the parser cache...
                 if ($oldid === $this->getLatest() && $this->useParserCache(false) && $wgOut->tryParserCache($this)) {
                     $outputDone = true;
                 }
             }
         }
         // Ensure that UI elements requiring revision ID have
         // the correct version information.
         $wgOut->setRevisionId($this->getRevIdFetched());
         if ($outputDone) {
             // do nothing...
             // Pages containing custom CSS or JavaScript get special treatment
         } else {
             if ($this->mTitle->isCssOrJsPage() || $this->mTitle->isCssJsSubpage()) {
                 $wgOut->addHTML(wfMsgExt('clearyourcache', 'parse'));
                 // Give hooks a chance to customise the output
                 if (wfRunHooks('ShowRawCssJs', array($this->mContent, $this->mTitle, $wgOut))) {
                     // Wrap the whole lot in a <pre> and don't parse
                     $m = array();
                     preg_match('!\\.(css|js)$!u', $this->mTitle->getText(), $m);
                     $wgOut->addHTML("<pre class=\"mw-code mw-{$m[1]}\" dir=\"ltr\">\n");
                     $wgOut->addHTML(htmlspecialchars($this->mContent));
                     $wgOut->addHTML("\n</pre>\n");
                 }
             } else {
                 if ($rt = Title::newFromRedirectArray($text)) {
                     # get an array of redirect targets
                     # Don't append the subtitle if this was an old revision
                     $wgOut->addHTML($this->viewRedirect($rt, !$wasRedirected && $this->isCurrent()));
                     $parseout = $wgParser->parse($text, $this->mTitle, ParserOptions::newFromUser($wgUser));
                     $wgOut->addParserOutputNoText($parseout);
                 } else {
                     if ($pcache) {
                         # Display content and save to parser cache
                         $this->outputWikiText($text);
                     } else {
                         # Display content, don't attempt to save to parser cache
                         # Don't show section-edit links on old revisions... this way lies madness.
                         if (!$this->isCurrent()) {
                             $oldEditSectionSetting = $wgOut->parserOptions()->setEditSection(false);
                         }
                         # Display content and don't save to parser cache
                         # With timing hack -- TS 2006-07-26
                         $time = -wfTime();
                         $this->outputWikiText($text, false);
                         $time += wfTime();
                         # Timing hack
                         if ($time > 3) {
                             wfDebugLog('slow-parse', sprintf("%-5.2f %s", $time, $this->mTitle->getPrefixedDBkey()));
                         }
                         if (!$this->isCurrent()) {
                             $wgOut->parserOptions()->setEditSection($oldEditSectionSetting);
                         }
                     }
                 }
             }
         }
     }
     /* title may have been set from the cache */
     $t = $wgOut->getPageTitle();
     if (empty($t)) {
         $wgOut->setPageTitle($this->mTitle->getPrefixedText());
         # 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).
         if ($this->mTitle->equals(Title::newMainPage()) && wfMsgForContent('pagetitle-view-mainpage') !== '') {
             $wgOut->setHTMLTitle(wfMsgForContent('pagetitle-view-mainpage'));
         }
     }
     # check if we're displaying a [[User talk:x.x.x.x]] anonymous talk page
     if ($ns == NS_USER_TALK && IP::isValid($this->mTitle->getText())) {
         $wgOut->addWikiMsg('anontalkpagetext');
     }
     # If we have been passed an &rcid= parameter, we want to give the user a
     # chance to mark this new article as patrolled.
     if (!empty($rcid) && $this->mTitle->exists() && $this->mTitle->quickUserCan('patrol')) {
         $wgOut->addHTML("<div class='patrollink'>" . wfMsgHtml('markaspatrolledlink', $sk->makeKnownLinkObj($this->mTitle, wfMsgHtml('markaspatrolledtext'), "action=markpatrolled&rcid={$rcid}")) . '</div>');
     }
     # Trackbacks
     if ($wgUseTrackbacks) {
         $this->addTrackbacks();
     }
     $this->viewUpdates();
     wfProfileOut(__METHOD__);
 }