/**
  * Adds or updates the flagged revision table for this page/id set
  * @param Revision $rev The revision to be accepted
  * @param FlaggedRevision $oldFrev Currently accepted version of $rev or null
  * @throws MWException
  * @return bool|array true on success, array of errors on failure
  */
 private function approveRevision(Revision $rev, FlaggedRevision $oldFrev = null)
 {
     wfProfileIn(__METHOD__);
     # Revision rating flags
     $flags = $this->dims;
     $quality = 0;
     // quality tier from flags
     if (FlaggedRevs::isQuality($flags)) {
         $quality = FlaggedRevs::isPristine($flags) ? 2 : 1;
     }
     # Our template/file version pointers
     list($tmpVersions, $fileVersions) = self::getIncludeVersions($this->templateParams, $this->imageParams);
     # If this is an image page, store corresponding file info
     $fileData = array('name' => null, 'timestamp' => null, 'sha1' => null);
     if ($this->page->getNamespace() == NS_FILE && $this->fileVersion) {
         # Stable upload version for file pages...
         $data = explode('#', $this->fileVersion, 2);
         if (count($data) == 2) {
             $fileData['name'] = $this->page->getDBkey();
             $fileData['timestamp'] = $data[0];
             $fileData['sha1'] = $data[1];
         }
     }
     # Get current stable version ID (for logging)
     $oldSv = FlaggedRevision::newFromStable($this->page, FR_MASTER);
     # Is this a duplicate review?
     if ($oldFrev && $oldFrev->getTags() == $flags && $oldFrev->getFileSha1() == $fileData['sha1'] && $oldFrev->getFileTimestamp() == $fileData['timestamp'] && $oldFrev->getTemplateVersions(FR_MASTER) == $tmpVersions && $oldFrev->getFileVersions(FR_MASTER) == $fileVersions) {
         wfProfileOut(__METHOD__);
         return true;
         // don't record if the same
     }
     # The new review entry...
     $flaggedRevision = new FlaggedRevision(array('rev' => $rev, 'user_id' => $this->user->getId(), 'timestamp' => wfTimestampNow(), 'quality' => $quality, 'tags' => FlaggedRevision::flattenRevisionTags($flags), 'img_name' => $fileData['name'], 'img_timestamp' => $fileData['timestamp'], 'img_sha1' => $fileData['sha1'], 'templateVersions' => $tmpVersions, 'fileVersions' => $fileVersions, 'flags' => ''));
     # Delete the old review entry if it exists...
     if ($oldFrev) {
         $oldFrev->delete();
     }
     # Insert the new review entry...
     if (!$flaggedRevision->insert()) {
         throw new MWException("Flagged revision with ID {$rev->getId()} exists with unexpected fr_page_id");
     }
     # Update the article review log...
     $oldSvId = $oldSv ? $oldSv->getRevId() : 0;
     FlaggedRevsLog::updateReviewLog($this->page, $this->dims, $this->oldFlags, $this->comment, $this->oldid, $oldSvId, true);
     # Get the new stable version as of now
     $sv = FlaggedRevision::determineStable($this->page, FR_MASTER);
     # Update recent changes...
     self::updateRecentChanges($rev, 'patrol', $sv);
     # Update page and tracking tables and clear cache
     $changed = FlaggedRevs::stableVersionUpdates($this->page, $sv, $oldSv);
     if ($changed) {
         FlaggedRevs::HTMLCacheUpdates($this->page);
         // purge pages that use this page
     }
     # Caller may want to get the change time
     $this->newLastChangeTime = $flaggedRevision->getTimestamp();
     wfProfileOut(__METHOD__);
     return true;
 }
 /**
  * Replaces a page with the last stable version if possible
  * Adds stable version status/info tags and notes
  * Adds a quick review form on the bottom if needed
  */
 public function setPageContent(&$outputDone, &$useParserCache)
 {
     $request = $this->getRequest();
     $this->load();
     # Only trigger on page views with no oldid=x param
     if (!$this->isPageView($request) || $request->getVal('oldid')) {
         return true;
         # Only trigger for reviewable pages that exist
     } elseif (!$this->article->exists() || !$this->article->isReviewable()) {
         return true;
     }
     $tag = '';
     $old = $stable = false;
     # Check the newest stable version.
     $srev = $this->article->getStableRev();
     $stableId = $srev ? $srev->getRevId() : 0;
     $frev = $srev;
     // $frev is the revision we are looking at
     # Check for any explicitly requested reviewed version (stableid=X)...
     $reqId = $this->getRequestedStableId();
     if ($reqId) {
         if (!$stableId) {
             $reqId = false;
             // must be invalid
             # Treat requesting the stable version by ID as &stable=1
         } elseif ($reqId != $stableId) {
             $old = true;
             // old reviewed version requested by ID
             $frev = FlaggedRevision::newFromTitle($this->article->getTitle(), $reqId);
             if (!$frev) {
                 $reqId = false;
                 // invalid ID given
             }
         } else {
             $stable = true;
             // stable version requested by ID
         }
     }
     // $reqId is null if nothing requested, false if invalid
     if ($reqId === false) {
         $this->out->addWikiText(wfMsg('revreview-invalid'));
         $this->out->returnToMain(false, $this->article->getTitle());
         # Tell MW that parser output is done
         $outputDone = true;
         $useParserCache = false;
         return true;
     }
     // Is the page config altered?
     $prot = FlaggedRevsXML::lockStatusIcon($this->article);
     // Is there no stable version?
     if (!$frev) {
         # Add "no reviewed version" tag, but not for printable output
         $this->showUnreviewedPage($tag, $prot);
         return true;
     }
     # Get flags and date
     $flags = $frev->getTags();
     # Get quality level
     $quality = FlaggedRevs::isQuality($flags);
     $pristine = FlaggedRevs::isPristine($flags);
     // Looking at some specific old stable revision ("&stableid=x")
     // set to override given the relevant conditions. If the user is
     // requesting the stable revision ("&stableid=x"), defer to override
     // behavior below, since it is the same as ("&stable=1").
     if ($old) {
         # Tell MW that parser output is done by setting $outputDone
         $outputDone = $this->showOldReviewedVersion($frev, $tag, $prot);
         $useParserCache = false;
         // Stable version requested by ID or relevant conditions met to
         // to override page view with the stable version.
     } elseif ($stable || $this->showingStable()) {
         # Tell MW that parser output is done by setting $outputDone
         $outputDone = $this->showStableVersion($srev, $tag, $prot);
         $useParserCache = false;
         // Looking at some specific old revision (&oldid=x) or if FlaggedRevs is not
         // set to override given the relevant conditions (like &stable=0) or there
         // is no stable version.
     } else {
         $this->showDraftVersion($srev, $tag, $prot);
     }
     # Some checks for which tag CSS to use
     if ($this->useSimpleUI()) {
         $tagClass = 'flaggedrevs_short';
     } elseif ($pristine) {
         $tagClass = 'flaggedrevs_pristine';
     } elseif ($quality) {
         $tagClass = 'flaggedrevs_quality';
     } else {
         $tagClass = 'flaggedrevs_basic';
     }
     # Wrap tag contents in a div
     if ($tag != '') {
         $css = "{$tagClass} plainlinks noprint";
         $notice = "<div id=\"mw-fr-revisiontag\" class=\"{$css}\">{$tag}</div>\n";
         $this->reviewNotice .= $notice;
     }
     return true;
 }
 /**
  * @param FlaggedRevision $frev, the reviewed version
  * @param string $html, the short message HTML
  * @param int $revsSince, revisions since review
  * @param string $type (stable/draft/oldstable)
  * @param bool $stable, are we referring to the stable revision?
  * @param bool $synced, does stable=current and this is one of them?
  * @return string
  * Generates a review box using a table using FlaggedRevsXML::addTagRatings()
  */
 public static function prettyRatingBox($frev, $shtml, $revsSince, $type = 'oldstable', $synced = false)
 {
     global $wgLang;
     # Get quality level
     $flags = $frev->getTags();
     $quality = FlaggedRevs::isQuality($flags);
     $pristine = FlaggedRevs::isPristine($flags);
     $time = $wgLang->date($frev->getTimestamp(), true);
     # Some checks for which tag CSS to use
     if ($pristine) {
         $color = 'flaggedrevs-color-3';
     } elseif ($quality) {
         $color = 'flaggedrevs-color-2';
     } else {
         $color = 'flaggedrevs-color-1';
     }
     # Construct some tagging
     if ($synced && ($type == 'stable' || $type == 'draft')) {
         $msg = $quality ? 'revreview-quality-same' : 'revreview-basic-same';
         $html = wfMsgExt($msg, 'parseinline', $frev->getRevId(), $time, $revsSince);
     } elseif ($type == 'oldstable') {
         $msg = $quality ? 'revreview-quality-old' : 'revreview-basic-old';
         $html = wfMsgExt($msg, 'parseinline', $frev->getRevId(), $time);
     } else {
         if ($type == 'stable') {
             $msg = $quality ? 'revreview-quality' : 'revreview-basic';
         } else {
             // draft
             $msg = $quality ? 'revreview-newest-quality' : 'revreview-newest-basic';
         }
         # For searching: uses messages 'revreview-quality-i', 'revreview-basic-i',
         # 'revreview-newest-quality-i', 'revreview-newest-basic-i'
         $msg .= $revsSince == 0 ? '-i' : '';
         $html = wfMsgExt($msg, 'parseinline', $frev->getRevId(), $time, $revsSince);
     }
     # Make fancy box...
     $box = '<div class="flaggedrevs_short_basic">';
     $box .= $shtml . self::ratingArrow();
     $box .= "</div>\n";
     // For rel-absolute child div (the fly-out)
     $box .= '<div id="mw-fr-revisiondetails-wrapper" style="position:relative;">';
     $box .= Xml::openElement('div', array('id' => 'mw-fr-revisiondetails', 'class' => 'flaggedrevs_short_details', 'style' => 'display:none'));
     $box .= $html;
     // details text
     # Add any rating tags as needed...
     if ($flags && !FlaggedRevs::binaryFlagging()) {
         # Don't show the ratings on draft views
         if ($type == 'stable' || $type == 'oldstable') {
             $box .= '<p>' . self::addTagRatings($flags, true, $color) . '</p>';
         }
     }
     $box .= Xml::closeElement('div') . "\n";
     $box .= "</div>\n";
     return $box;
 }