/** * Get template and image versions from parsing a revision * @param Page $article * @param Revision $rev * @param User $user * @param string $regen use 'regen' to force regeneration * @return array( templateIds, fileSHA1Keys ) * templateIds like ParserOutput->mTemplateIds * fileSHA1Keys like ParserOutput->mImageTimeKeys */ public static function getRevIncludes(Page $article, Revision $rev, User $user, $regen = '') { global $wgMemc; wfProfileIn(__METHOD__); $key = self::getCacheKey($article->getTitle(), $rev->getId()); if ($regen === 'regen') { $versions = false; // skip cache } elseif ($rev->isCurrent()) { // Check cache entry against page_touched $versions = FlaggedRevs::getMemcValue($wgMemc->get($key), $article); } else { // Old revs won't always be invalidated with template/file changes. // Also, we don't care if page_touched changed due to a direct edit. $versions = FlaggedRevs::getMemcValue($wgMemc->get($key), $article, 'allowStale'); if (is_array($versions)) { // entry exists // Sanity check that the cache is reasonably up to date list($templates, $files) = $versions; if (self::templatesStale($templates) || self::filesStale($files)) { $versions = false; // no good } } } if (!is_array($versions)) { // cache miss $pOut = false; if ($rev->isCurrent()) { $parserCache = ParserCache::singleton(); # Try current version parser cache for this user... $pOut = $parserCache->get($article, $article->makeParserOptions($user)); if ($pOut == false) { # Try current version parser cache for the revision author... $optsUser = $rev->getUser() ? User::newFromId($rev->getUser()) : 'canonical'; $pOut = $parserCache->get($article, $article->makeParserOptions($optsUser)); } } // ParserOutput::mImageTimeKeys wasn't always there if ($pOut == false || !FlaggedRevs::parserOutputIsVersioned($pOut)) { $content = $rev->getContent(Revision::RAW); if (!$content) { // Just for extra sanity $pOut = new ParserOutput(); } else { $pOut = $content->getParserOutput($article->getTitle(), $rev->getId(), ParserOptions::newFromUser($user)); } } # Get the template/file versions used... $versions = array($pOut->getTemplateIds(), $pOut->getFileSearchOptions()); # Save to cache (check cache expiry for dynamic elements)... $data = FlaggedRevs::makeMemcObj($versions); $wgMemc->set($key, $data, $pOut->getCacheExpiry()); } wfProfileOut(__METHOD__); return $versions; }
/** * Returns true if the currently-referenced revision is the current edit * to this page (and it exists). * @return bool */ public function isCurrent() { # If no oldid, this is the current version. if ($this->getOldID() == 0) { return true; } return $this->mPage->exists() && $this->mRevision && $this->mRevision->isCurrent(); }
/** * Get template and image versions from parsing a revision * @param Page $article * @param Revision $rev * @param User $user * @param string $regen use 'regen' to force regeneration * @return array( templateIds, fileSHA1Keys ) * templateIds like ParserOutput->mTemplateIds * fileSHA1Keys like ParserOutput->mImageTimeKeys */ public static function getRevIncludes(Page $article, Revision $rev, User $user, $regen = '') { global $wgParser, $wgMemc; wfProfileIn(__METHOD__); $versions = false; $key = self::getCacheKey($article->getTitle(), $rev->getId()); if ($regen !== 'regen') { // check cache $versions = FlaggedRevs::getMemcValue($wgMemc->get($key), $article, 'allowStale'); } if (!is_array($versions)) { // cache miss $pOut = false; if ($rev->isCurrent()) { $parserCache = ParserCache::singleton(); # Try current version parser cache (as anon)... $pOut = $parserCache->get($article, $article->makeParserOptions($user)); if ($pOut == false && $rev->getUser()) { // try the user who saved the change $author = User::newFromId($rev->getUser()); $pOut = $parserCache->get($article, $article->makeParserOptions($author)); } } // ParserOutput::mImageTimeKeys wasn't always there if ($pOut == false || !FlaggedRevs::parserOutputIsVersioned($pOut)) { $title = $article->getTitle(); $pOpts = ParserOptions::newFromUser($user); // Note: tidy off $pOut = $wgParser->parse($rev->getText(), $title, $pOpts, true, true, $rev->getId()); } # Get the template/file versions used... $versions = array($pOut->getTemplateIds(), $pOut->getFileSearchOptions()); # Save to cache (check cache expiry for dynamic elements)... $data = FlaggedRevs::makeMemcObj($versions); $wgMemc->set($key, $data, $pOut->getCacheExpiry()); } else { $tVersions =& $versions[0]; // templates # Do a link batch query for page_latest... $lb = new LinkBatch(); foreach ($tVersions as $ns => $tmps) { foreach ($tmps as $dbKey => $revIdDraft) { $lb->add($ns, $dbKey); } } $lb->execute(); # Update array with the current page_latest values. # This kludge is there since $newTemplates (thus $revIdDraft) is cached. foreach ($tVersions as $ns => &$tmps) { foreach ($tmps as $dbKey => &$revIdDraft) { $title = Title::makeTitle($ns, $dbKey); $revIdDraft = (int) $title->getLatestRevID(); } } } wfProfileOut(__METHOD__); return $versions; }
/** * Get a header for a specified revision. * * @param Revision $rev * @param string $complete 'complete' to get the header wrapped depending * the visibility of the revision and a link to edit the page. * * @return string HTML fragment */ protected function getRevisionHeader(Revision $rev, $complete = '') { $lang = $this->getLanguage(); $user = $this->getUser(); $revtimestamp = $rev->getTimestamp(); $timestamp = $lang->userTimeAndDate($revtimestamp, $user); $dateofrev = $lang->userDate($revtimestamp, $user); $timeofrev = $lang->userTime($revtimestamp, $user); $header = $this->msg($rev->isCurrent() ? 'currentrev-asof' : 'revisionasof', $timestamp, $dateofrev, $timeofrev)->escaped(); if ($complete !== 'complete') { return $header; } $title = $rev->getTitle(); $header = Linker::linkKnown($title, $header, array(), array('oldid' => $rev->getID())); if ($rev->userCan(Revision::DELETED_TEXT, $user)) { $editQuery = array('action' => 'edit'); if (!$rev->isCurrent()) { $editQuery['oldid'] = $rev->getID(); } $key = $title->quickUserCan('edit', $user) ? 'editold' : 'viewsourceold'; $msg = $this->msg($key)->escaped(); $editLink = $this->msg('parentheses')->rawParams(Linker::linkKnown($title, $msg, array(), $editQuery))->escaped(); $header .= ' ' . Html::rawElement('span', array('class' => 'mw-diff-edit'), $editLink); if ($rev->isDeleted(Revision::DELETED_TEXT)) { $header = Html::rawElement('span', array('class' => 'history-deleted'), $header); } } else { $header = Html::rawElement('span', array('class' => 'history-deleted'), $header); } return $header; }
/** * Add a link to diff-to-stable for reviewable pages */ protected static function diffToStableLink(FlaggableWikiPage $article, $oldRev, Revision $newRev) { $srev = $article->getStableRev(); if (!$srev) { return ''; // nothing to do } $review = ''; # Is this already the full diff-to-stable? $fullStableDiff = $newRev->isCurrent() && self::isDiffToStable($srev, $oldRev, $newRev); # Make a link to the full diff-to-stable if: # (a) Actual revs are pending and (b) We are not viewing the full diff-to-stable if ($article->revsArePending() && !$fullStableDiff) { $review = Linker::linkKnown($article->getTitle(), wfMsgHtml('review-diff2stable'), array(), array('oldid' => $srev->getRevId(), 'diff' => 'cur') + FlaggedRevs::diffOnlyCGI()); $review = wfMsgHtml('parentheses', $review); $review = "<div class='fr-diff-to-stable' align='center'>{$review}</div>"; } return $review; }
/** * @param Skin $skin * @param Title $title * @param Revision $revision * @param Revision $undoAfterRevision * @return String Undo Link */ public static function generateUndoLink($skin, $title, $revision, $undoAfterRevision) { if (!$revision instanceof Revision || !$undoAfterRevision instanceof Revision || !$title instanceof Title || !$skin instanceof Skin) { return null; } # Create undo tooltip for the first (=latest) line only $undoTooltip = $revision->isCurrent() ? array('title' => wfMsg('tooltip-undo')) : array(); $undolink = $skin->link($title, wfMsgHtml('editundo'), $undoTooltip, array('action' => 'edit', 'undoafter' => $undoAfterRevision->getId(), 'undo' => $revision->getId()), array('known', 'noclasses')); return "<span class=\"mw-history-undo\">{$undolink}</span>"; }
/** * Get a header for a specified revision. * * @param $rev Revision * @param $complete String: 'complete' to get the header wrapped depending * the visibility of the revision and a link to edit the page. * @return String HTML fragment */ private function getRevisionHeader(Revision $rev, $complete = '') { $lang = $this->getLanguage(); $user = $this->getUser(); $revtimestamp = $rev->getTimestamp(); $timestamp = $lang->userTimeAndDate($revtimestamp, $user); $dateofrev = $lang->userDate($revtimestamp, $user); $timeofrev = $lang->userTime($revtimestamp, $user); $header = $this->msg($rev->isCurrent() ? 'currentrev-asof' : 'revisionasof', $timestamp, $dateofrev, $timeofrev)->escaped(); if ($complete !== 'complete') { return $header; } $title = $rev->getTitle(); $header = Linker::linkKnown($title, $header, array(), array('oldid' => $rev->getID())); if ($rev->userCan(Revision::DELETED_TEXT, $user)) { $editQuery = array('action' => 'edit'); if (!$rev->isCurrent()) { $editQuery['oldid'] = $rev->getID(); } $msg = $this->msg($title->userCan('edit', $user) ? 'editold' : 'viewsourceold')->escaped(); /* Wikia Change begin */ $header .= ' <span class="mw-rev-head-action">(' . Linker::linkKnown($title, $msg, array(), $editQuery) . ')</span>'; /* Wikia Change end */ if ($rev->isDeleted(Revision::DELETED_TEXT)) { $header = Html::rawElement('span', array('class' => 'history-deleted'), $header); } } else { $header = Html::rawElement('span', array('class' => 'history-deleted'), $header); } return $header; }