/** * @depends testImplementsSetMagic */ function testImplementsCallMagic() { $this->article->mLatest = 33; $this->article->mDataLoaded = true; $this->assertEquals(33, $this->article->getLatest(), "Article __call magic"); }
/** * Sets post-edit cookie indicating the user just saved a particular revision. * * This uses a temporary cookie for each revision ID so separate saves will never * interfere with each other. * * The cookie is deleted in the mediawiki.action.view.postEdit JS module after * the redirect. It must be clearable by JavaScript code, so it must not be * marked HttpOnly. The JavaScript code converts the cookie to a wgPostEdit config * variable. * * Since WebResponse::setcookie does not allow forcing HttpOnly for a single * cookie, we have to use PHP's setcookie() directly. * * We use a path of '/' since wgCookiePath is not exposed to JS * * If the variable were set on the server, it would be cached, which is unwanted * since the post-edit state should only apply to the load right after the save. */ protected function setPostEditCookie() { global $wgCookiePrefix, $wgCookieDomain; $revisionId = $this->mArticle->getLatest(); $postEditKey = self::POST_EDIT_COOKIE_KEY_PREFIX . $revisionId; setcookie($wgCookiePrefix . $postEditKey, '1', time() + self::POST_EDIT_COOKIE_DURATION, '/', $wgCookieDomain); }
/** * Sets post-edit cookie indicating the user just saved a particular revision. * * This uses a temporary cookie for each revision ID so separate saves will never * interfere with each other. * * The cookie is deleted in the mediawiki.action.view.postEdit JS module after * the redirect. It must be clearable by JavaScript code, so it must not be * marked HttpOnly. The JavaScript code converts the cookie to a wgPostEdit config * variable. * * If the variable were set on the server, it would be cached, which is unwanted * since the post-edit state should only apply to the load right after the save. * * @param int $statusValue The status value (to check for new article status) */ protected function setPostEditCookie($statusValue) { $revisionId = $this->mArticle->getLatest(); $postEditKey = self::POST_EDIT_COOKIE_KEY_PREFIX . $revisionId; $val = 'saved'; if ($statusValue == self::AS_SUCCESS_NEW_ARTICLE) { $val = 'created'; } elseif ($this->oldid) { $val = 'restored'; } $response = RequestContext::getMain()->getRequest()->response(); $response->setcookie($postEditKey, $val, time() + self::POST_EDIT_COOKIE_DURATION, array('httpOnly' => false)); }
function parseCollectionLine(&$collection, $line, $append) { $line = trim($line); if (!$append && preg_match('/^===\\s*(.*?)\\s*===$/', $line, $match)) { $collection['subtitle'] = $match[1]; } elseif (!$append && preg_match('/^==\\s*(.*?)\\s*==$/', $line, $match)) { $collection['title'] = $match[1]; } elseif (substr($line, 0, 1) == ';') { // chapter return array('type' => 'chapter', 'title' => trim(substr($line, 1))); } elseif (substr($line, 0, 1) == ':') { // article $articleTitle = trim(substr($line, 1)); if (preg_match('/^\\[\\[:?(.*?)(\\|(.*?))?\\]\\]$/', $articleTitle, $match)) { $articleTitle = $match[1]; if (isset($match[3])) { $displayTitle = $match[3]; } else { $displayTitle = null; } $oldid = -1; $currentVersion = 1; } elseif (preg_match('/^\\[\\{\\{fullurl:(.*?)\\|oldid=(.*?)\\}\\}\\s+(.*?)\\]$/', $articleTitle, $match)) { $articleTitle = $match[1]; if (isset($match[3])) { $displayTitle = $match[3]; } else { $displayTitle = null; } $oldid = $match[2]; $currentVersion = 0; } else { return null; } $articleTitle = Title::newFromText($articleTitle); if (!$articleTitle) { return null; } if ($oldid < 0) { $article = new Article($articleTitle); } else { $article = new Article($articleTitle, $oldid); } if (!$article->exists()) { return null; } $revision = Revision::newFromTitle($articleTitle, $article->getOldID()); $latest = $article->getLatest(); $oldid = $article->getOldID(); if (!$oldid) { $oldid = $latest; } $d = array('type' => 'article', 'content_type' => 'text/x-wiki', 'title' => $articleTitle->getPrefixedText(), 'latest' => $latest, 'revision' => $oldid, 'timestamp' => wfTimestamp(TS_UNIX, $revision->getTimestamp()), 'url' => $articleTitle->getCanonicalURL(), 'currentVersion' => $currentVersion); if ($displayTitle) { $d['displaytitle'] = $displayTitle; } return $d; } return null; }
static function util_ResolveRevSpec($page_title, $page_id = 0, $rev_id = 0) { global $wgTitle; $dbr =& wfGetDB(DB_SLAVE); if ($rev_id && !$page_id) { $rev = Revision::loadFromId($dbr, $rev_id); if ($rev) { $page_id = $rev->getPage(); } } if ($page_id && !$page_title) { $wgTitle = Title::newFromID($page_id); } if ($page_title) { $wgTitle = Title::newFromDBkey($page_title); } $article = new Article($wgTitle); $title_db = $wgTitle->getDBkey(); $page_id_db = $wgTitle->getArticleID(); $rev_id_db = $article->getLatest(); if (!$page_id) { $page_id = $page_id_db; } if (!$rev_id) { $rev_id = $rev_id_db; } if (!$page_title) { $page_title = $title_db; } if ($page_id != $page_id_db) { wfWikiTrustWarn(__FILE__ . ":" . __LINE__ . ": mismatched pageId: {$page_id} != {$page_id_db}"); } if ($page_title != $title_db) { wfWikiTrustWarn(__FILE__ . ":" . __LINE__ . ": mismatched title: {$page_title} != {$title_db}"); } return array($page_title, $page_id, $rev_id); }
/** * Sets post-edit cookie indicating the user just saved a particular revision. * * This uses a temporary cookie for each revision ID so separate saves will never * interfere with each other. * * The cookie is deleted in the mediawiki.action.view.postEdit JS module after * the redirect. It must be clearable by JavaScript code, so it must not be * marked HttpOnly. The JavaScript code converts the cookie to a wgPostEdit config * variable. * * We use a path of '/' since wgCookiePath is not exposed to JS * * If the variable were set on the server, it would be cached, which is unwanted * since the post-edit state should only apply to the load right after the save. */ protected function setPostEditCookie() { $revisionId = $this->mArticle->getLatest(); $postEditKey = self::POST_EDIT_COOKIE_KEY_PREFIX . $revisionId; $response = RequestContext::getMain()->getRequest()->response(); $response->setcookie($postEditKey, '1', time() + self::POST_EDIT_COOKIE_DURATION, array('path' => '/', 'httpOnly' => false)); }
public function execute() { $user = $this->getUser(); $params = $this->extractRequestParams(); if (is_null($params['text']) && is_null($params['appendtext']) && is_null($params['prependtext']) && $params['undo'] == 0) { $this->dieUsageMsg('missingtext'); } $pageObj = $this->getTitleOrPageId($params); $titleObj = $pageObj->getTitle(); if ($titleObj->isExternal()) { $this->dieUsageMsg(array('invalidtitle', $params['title'])); } if (!isset($params['contentmodel']) || $params['contentmodel'] == '') { $contentHandler = $pageObj->getContentHandler(); } else { $contentHandler = ContentHandler::getForModelID($params['contentmodel']); } // @todo ask handler whether direct editing is supported at all! make allowFlatEdit() method or some such if (!isset($params['contentformat']) || $params['contentformat'] == '') { $params['contentformat'] = $contentHandler->getDefaultFormat(); } $contentFormat = $params['contentformat']; if (!$contentHandler->isSupportedFormat($contentFormat)) { $name = $titleObj->getPrefixedDBkey(); $model = $contentHandler->getModelID(); $this->dieUsage("The requested format {$contentFormat} is not supported for content model " . " {$model} used by {$name}", 'badformat'); } $apiResult = $this->getResult(); if ($params['redirect']) { if ($titleObj->isRedirect()) { $oldTitle = $titleObj; $titles = Revision::newFromTitle($oldTitle, false, Revision::READ_LATEST)->getContent(Revision::FOR_THIS_USER, $user)->getRedirectChain(); // array_shift( $titles ); $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; } $apiResult->setIndexedTagName($redirValues, 'r'); $apiResult->addValue(null, 'redirects', $redirValues); } } if ($params['createonly'] && $titleObj->exists()) { $this->dieUsageMsg('createonly-exists'); } if ($params['nocreate'] && !$titleObj->exists()) { $this->dieUsageMsg('nocreate-missing'); } // Now let's check whether we're even allowed to do this $errors = $titleObj->getUserPermissionsErrors('edit', $user); if (!$titleObj->exists()) { $errors = array_merge($errors, $titleObj->getUserPermissionsErrors('create', $user)); } if (count($errors)) { $this->dieUsageMsg($errors[0]); } $toMD5 = $params['text']; if (!is_null($params['appendtext']) || !is_null($params['prependtext'])) { $content = $pageObj->getContent(); if (!$content) { if ($titleObj->getNamespace() == NS_MEDIAWIKI) { # If this is a MediaWiki:x message, then load the messages # and return the message value for x. $text = $titleObj->getDefaultMessageText(); if ($text === false) { $text = ''; } try { $content = ContentHandler::makeContent($text, $this->getTitle()); } catch (MWContentSerializationException $ex) { $this->dieUsage($ex->getMessage(), 'parseerror'); return; } } else { # Otherwise, make a new empty content. $content = $contentHandler->makeEmptyContent(); } } // @todo: Add support for appending/prepending to the Content interface if (!$content instanceof TextContent) { $mode = $contentHandler->getModelID(); $this->dieUsage("Can't append to pages using content model {$mode}", 'appendnotsupported'); } if (!is_null($params['section'])) { if (!$contentHandler->supportsSections()) { $modelName = $contentHandler->getModelID(); $this->dieUsage("Sections are not supported for this content model: {$modelName}.", 'sectionsnotsupported'); } // Process the content for section edits $section = intval($params['section']); $content = $content->getSection($section); if (!$content) { $this->dieUsage("There is no section {$section}.", 'nosuchsection'); } } if (!$content) { $text = ''; } else { $text = $content->serialize($contentFormat); } $params['text'] = $params['prependtext'] . $text . $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() != $pageObj->getID()) { $this->dieUsageMsg(array('revwrongpage', $undoRev->getID(), $titleObj->getPrefixedText())); } if ($undoafterRev->getPage() != $pageObj->getID()) { $this->dieUsageMsg(array('revwrongpage', $undoafterRev->getID(), $titleObj->getPrefixedText())); } $newContent = $contentHandler->getUndoContent($pageObj->getRevision(), $undoRev, $undoafterRev); if (!$newContent) { $this->dieUsageMsg('undo-failure'); } $params['text'] = $newContent->serialize($params['contentformat']); // 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'] = wfMessage('undo-summary', $params['undo'], $undoRev->getUserText())->inContentLanguage()->text(); } } // See if the MD5 hash checks out if (!is_null($params['md5']) && md5($toMD5) !== $params['md5']) { $this->dieUsageMsg('hashcheckfailed'); } // EditPage wants to parse its stuff from a WebRequest // That interface kind of sucks, but it's workable $requestArray = array('wpTextbox1' => $params['text'], 'format' => $contentFormat, 'model' => $contentHandler->getModelID(), 'wpEditToken' => $params['token'], 'wpIgnoreBlankSummary' => ''); if (!is_null($params['summary'])) { $requestArray['wpSummary'] = $params['summary']; } if (!is_null($params['sectiontitle'])) { $requestArray['wpSectionTitle'] = $params['sectiontitle']; } // TODO: Pass along information from 'undoafter' as well if ($params['undo'] > 0) { $requestArray['wpUndidRevision'] = $params['undo']; } // Watch out for basetimestamp == '' // wfTimestamp() treats it as NOW, almost certainly causing an edit conflict if (!is_null($params['basetimestamp']) && $params['basetimestamp'] != '') { $requestArray['wpEdittime'] = wfTimestamp(TS_MW, $params['basetimestamp']); } else { $requestArray['wpEdittime'] = $pageObj->getTimestamp(); } if (!is_null($params['starttimestamp']) && $params['starttimestamp'] != '') { $requestArray['wpStarttime'] = wfTimestamp(TS_MW, $params['starttimestamp']); } else { $requestArray['wpStarttime'] = wfTimestampNow(); // Fake wpStartime } if ($params['minor'] || !$params['notminor'] && $user->getOption('minordefault')) { $requestArray['wpMinoredit'] = ''; } if ($params['recreate']) { $requestArray['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"); } $requestArray['wpSection'] = $params['section']; } else { $requestArray['wpSection'] = ''; } $watch = $this->getWatchlistValue($params['watchlist'], $titleObj); // Deprecated parameters if ($params['watch']) { $watch = true; } elseif ($params['unwatch']) { $watch = false; } if ($watch) { $requestArray['wpWatchthis'] = ''; } global $wgTitle, $wgRequest; $req = new DerivativeRequest($this->getRequest(), $requestArray, true); // Some functions depend on $wgTitle == $ep->mTitle // TODO: Make them not or check if they still do $wgTitle = $titleObj; $articleObject = new Article($titleObj); $ep = new EditPage($articleObject); // allow editing of non-textual content. $ep->allowNonTextContent = true; $ep->setContextTitle($titleObj); $ep->importFormData($req); // Run hooks // Handle APIEditBeforeSave parameters $r = array(); if (!wfRunHooks('APIEditBeforeSave', array($ep, $ep->textbox1, &$r))) { if (count($r)) { $r['result'] = 'Failure'; $apiResult->addValue(null, $this->getModuleName(), $r); return; } else { $this->dieUsageMsg('hookaborted'); } } // Do the actual save $oldRevId = $articleObject->getRevIdFetched(); $result = null; // Fake $wgRequest for some hooks inside EditPage // @todo FIXME: This interface SUCKS $oldRequest = $wgRequest; $wgRequest = $req; $status = $ep->internalAttemptSave($result, $user->isAllowed('bot') && $params['bot']); $wgRequest = $oldRequest; global $wgMaxArticleSize; switch ($status->value) { case EditPage::AS_HOOK_ERROR: case EditPage::AS_HOOK_ERROR_EXPECTED: $this->dieUsageMsg('hookaborted'); case EditPage::AS_PARSE_ERROR: $this->dieUsage($status->getMessage(), 'parseerror'); case EditPage::AS_IMAGE_REDIRECT_ANON: $this->dieUsageMsg('noimageredirect-anon'); case EditPage::AS_IMAGE_REDIRECT_LOGGED: $this->dieUsageMsg('noimageredirect-logged'); case EditPage::AS_SPAM_ERROR: $this->dieUsageMsg(array('spamdetected', $result['spam'])); case EditPage::AS_BLOCKED_PAGE_FOR_USER: $this->dieUsageMsg('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('noedit-anon'); case EditPage::AS_READ_ONLY_PAGE_LOGGED: $this->dieUsageMsg('noedit'); case EditPage::AS_READ_ONLY_PAGE: $this->dieReadOnly(); case EditPage::AS_RATE_LIMITED: $this->dieUsageMsg('actionthrottledtext'); case EditPage::AS_ARTICLE_WAS_DELETED: $this->dieUsageMsg('wasdeleted'); case EditPage::AS_NO_CREATE_PERMISSION: $this->dieUsageMsg('nocreate-loggedin'); case EditPage::AS_BLANK_ARTICLE: $this->dieUsageMsg('blankpage'); case EditPage::AS_CONFLICT_DETECTED: $this->dieUsageMsg('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('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(); $r['contentmodel'] = $titleObj->getContentModel(); $newRevId = $articleObject->getLatest(); if ($newRevId == $oldRevId) { $r['nochange'] = ''; } else { $r['oldrevid'] = intval($oldRevId); $r['newrevid'] = intval($newRevId); $r['newtimestamp'] = wfTimestamp(TS_ISO_8601, $pageObj->getTimestamp()); } break; case EditPage::AS_SUMMARY_NEEDED: $this->dieUsageMsg('summaryrequired'); case EditPage::AS_END: default: // $status came from WikiPage::doEdit() $errors = $status->getErrorsArray(); $this->dieUsageMsg($errors[0]); // TODO: Add new errors to message map break; } $apiResult->addValue(null, $this->getModuleName(), $r); }
/** * Generate family tree page * * @param unknown_type $args user, name, ns, title * @return GE_SUCCESS, GE_INVALID_ARG, GE_NOT_LOGGED_IN, GE_NOT_AUTHORIZED, GE_NOT_FOUND, GE_DUP_KEY, GE_DB_ERROR */ function wfGenerateFamilyTreePage($args) { global $wgUser, $wgAjaxCachePolicy, $wrBotUserID, $wrIsGedcomUpload; // set cache policy $wgAjaxCachePolicy->setPolicy(0); $status = GE_SUCCESS; $ns = ''; $text = ''; $oldText = ''; $titleString = ''; $editFlags = 0; $wrIsGedcomUpload = true; if (!$wgUser->isLoggedIn()) { $status = GE_NOT_LOGGED_IN; } else { if (wfReadOnly() || $wgUser->getID() != $wrBotUserID) { $status = GE_NOT_AUTHORIZED; } else { $xml = simplexml_load_string($args); $ns = (int) $xml['namespace']; $titleString = (string) $xml['title']; PropagationManager::setWhitelist(); // only pages to propagate to are on the whitelist $existingTitles = (string) $xml['existing_titles']; if ($existingTitles) { $existingTitles = explode('|', $existingTitles); foreach ($existingTitles as $existingTitle) { PropagationManager::addWhitelistPage(Title::newFromText($existingTitle)); } } $treeId = (int) $xml['tree_id']; $uid = (string) $xml['uid']; // wfDebug("wfGenerateFamilyTreePage ns=$ns title=$titleString treeId=$treeId\n"); if (!$titleString || !$treeId) { //wfDebug("wfGenerate parmerr $treeId:$titleString\n"); $status = GE_INVALID_ARG; } } } if ($status == GE_SUCCESS) { $dbr =& wfGetDB(DB_SLAVE); $dbr->ignoreErrors(true); $userName = $dbr->selectField('familytree', 'ft_user', array('ft_tree_id' => $treeId)); $errno = $dbr->lastErrno(); if ($errno > 0) { $status = GE_DB_ERROR; } else { if ($userName === false) { $status = GE_NOT_FOUND; } else { $wgUser = User::newFromName($userName, false); // switch the global user if (!$wgUser) { $status = GE_NOT_FOUND; } } } } if ($status == GE_SUCCESS) { $title = Title::newFromText($titleString, $ns); $text = $xml->content; if ($title == null || !$treeId) { //wfDebug("wfGenerate error $treeId $ns $titleString\n"); $status = GE_INVALID_ARG; } else { $article = new Article($title, 0); if (!$article->exists()) { $editFlags = EDIT_NEW; } else { $oldText = $article->getContent(); $editFlags = EDIT_UPDATE; } // else if ($ns == NS_MYSOURCE) { // $existingMysource = true; // $revid = $title->getLatestRevID(GAID_FOR_UPDATE); // } // // TODO during re-upload, we need to notify users of changes if others are watching; should we not suppress RC in this case? // // also, decide whether FamilyTreePropagator should update ftp or not // // (FamilyTreePropagator also processes the tree checkboxes, so we probably don't want it called) // else { //// $editFlags = EDIT_UPDATE; // $status = GE_DUP_KEY; // } } } if ($status == GE_SUCCESS && ($editFlags == EDIT_NEW || $text != $oldText)) { $isUpdatable = true; if ($editFlags == EDIT_UPDATE) { $revision = Revision::newFromId($article->getLatest()); if ($revision && $revision->getComment() != 'gedcom upload') { $isUpdatable = false; error_log("Cannot update existing user-edited page: " . $article->getTitle()->getPrefixedText()); } } if ($isUpdatable) { // NOTE: This doesn't execute the code in FamilyTreePropagator to update familytree_page, so if you edit a page, you'll have to update // the familytree_page.fp_latest yourself. Also, FamilyTreePropagator adds the page to the tree (based upon request checkboxes), but we do this below if (!$article->doEdit($text, 'gedcom upload', $editFlags | EDIT_SUPPRESS_RC)) { $status = GE_WIKI_ERROR; } // TODO remove this if ($ns == NS_PERSON) { $xml = StructuredData::getXml('person', $text); $summaryFields = explode('|', Person::getSummary($xml, $title)); $birthDate = $summaryFields[3]; $deathDate = $summaryFields[5]; $birthYear = ''; $deathYear = ''; if (preg_match('/\\d\\d\\d\\d/', $birthDate, $matches)) { $birthYear = $matches[0]; } if (preg_match('/\\d\\d\\d\\d/', $deathDate, $matches)) { $deathYear = $matches[0]; } if (($birthYear && $birthYear < 1750 || $deathYear && $deathYear < 1750) && !in_array($wgUser->getName(), explode('|', wfMsg('trustedgedcomuploaders')))) { error_log($title->getPrefixedText() . "\n", 3, '/opt/wr/logs/earlypeople.txt'); } } } } if ($status == GE_SUCCESS) { $dbw =& wfGetDB(DB_MASTER); $dbw->ignoreErrors(true); $dbw->begin(); // if ($status == GE_SUCCESS) { // // save the data // $data = $xml->data->asXML(); // if ($data) { // $dataVersion = 1; // $status == fgSaveData($dbw, $treeId, $title, $data, true); // } // else { // $dataVersion = 0; // } // } // add the page to the tree if ($status == GE_SUCCESS) { if (!FamilyTreeUtil::addPage($dbw, $wgUser, $treeId, $title, 0, 0, 0, $uid, 0)) { $status = GE_DB_ERROR; } } // watch the page if ($status == GE_SUCCESS) { StructuredData::addWatch($wgUser, $article, true); } if ($status == GE_SUCCESS) { $dbw->commit(); } else { $dbw->rollback(); } } // return status $titleString = StructuredData::escapeXml($titleString); return "<generate status=\"{$status}\" ns=\"{$ns}\" title=\"{$titleString}\"></generate>"; }
public static function overrideRedirect(Title $title, WebRequest $request, &$ignoreRedirect, &$target, Article &$article) { global $wgMemc, $wgParserCacheExpireTime; $fa = FlaggableWikiPage::getTitleInstance($title); // on $wgTitle if (!$fa->isReviewable()) { return true; // nothing to do } # Viewing an old reviewed version... if ($request->getVal('stableid')) { $ignoreRedirect = true; // don't redirect (same as ?oldid=x) return true; } $srev = $fa->getStableRev(); $view = FlaggablePageView::singleton(); # Check if we are viewing an unsynced stable version... if ($srev && $view->showingStable() && $srev->getRevId() != $article->getLatest()) { # Check the stable redirect properties from the cache... $key = wfMemcKey('flaggedrevs', 'overrideRedirect', $article->getId()); $tuple = FlaggedRevs::getMemcValue($wgMemc->get($key), $article); if (is_array($tuple)) { // cache hit list($ignoreRedirect, $target) = $tuple; } else { // cache miss; fetch the stable rev text... $text = $srev->getRevText(); $redirect = $fa->getRedirectURL(Title::newFromRedirectRecurse($text)); if ($redirect) { $target = $redirect; // use stable redirect } else { $ignoreRedirect = true; // make MW skip redirection } $data = FlaggedRevs::makeMemcObj(array($ignoreRedirect, $target)); $wgMemc->set($key, $data, $wgParserCacheExpireTime); // cache results } $clearEnvironment = (bool) $target; # Check if the we are viewing a draft or synced stable version... } else { # In both cases, we can just let MW use followRedirect() # on the draft as normal, avoiding any page text hits. $clearEnvironment = $article->isRedirect(); } # Environment (e.g. $wgTitle) will change in MediaWiki::initializeArticle if ($clearEnvironment) { $view->clear(); } return true; }
function getCachedWork() { global $wgOut; $parserCache = ParserCache::singleton(); $this->mArticle->mParserOutput = $parserCache->get($this->mArticle, $this->parserOptions); if ($this->mArticle->mParserOutput !== false) { wfDebug(__METHOD__ . ": showing contents parsed by someone else\n"); $wgOut->addParserOutput($this->mArticle->mParserOutput); # Ensure that UI elements requiring revision ID have # the correct version information. $wgOut->setRevisionId($this->mArticle->getLatest()); return true; } return false; }