/**
  * @param FlaggedRevision $frev
  * Removes flagged revision data for this page/id set
  * @return bool
  */
 private function unapproveRevision(FlaggedRevision $frev)
 {
     wfProfileIn(__METHOD__);
     # Get current stable version ID (for logging)
     $oldSv = FlaggedRevision::newFromStable($this->page, FR_MASTER);
     # Delete from flaggedrevs table
     $frev->delete();
     # Update the article review log
     $oldSvId = $oldSv ? $oldSv->getRevId() : 0;
     FlaggedRevsLog::updateReviewLog($this->page, $this->dims, $this->oldFlags, $this->comment, $this->oldid, $oldSvId, false);
     # Get the new stable version as of now
     $sv = FlaggedRevision::determineStable($this->page, FR_MASTER);
     # Update recent changes
     self::updateRecentChanges($frev->getRevision(), 'unpatrol', $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 = '';
     wfProfileOut(__METHOD__);
     return true;
 }
 /**
  * Create revision, diff, and history links for log line entry
  */
 public static function reviewLogLinks($action, $title, $params)
 {
     global $wgLang;
     $links = '';
     # Show link to page with oldid=x as well as the diff to the former stable rev.
     # Param format is <rev id, last stable id, rev timestamp>.
     if (isset($params[0])) {
         $revId = (int) $params[0];
         // the revision reviewed
         $oldStable = isset($params[1]) ? (int) $params[1] : 0;
         # Show diff to changes since the prior stable version
         if ($oldStable && $revId > $oldStable) {
             $msg = FlaggedRevsLog::isReviewDeapproval($action) ? 'review-logentry-diff2' : 'review-logentry-diff';
             // reviewed
             $links .= '(';
             $links .= Linker::linkKnown($title, wfMessage($msg)->escaped(), array(), array('oldid' => $oldStable, 'diff' => $revId));
             $links .= ')';
         }
         # Show a diff link to this revision
         $ts = empty($params[2]) ? Revision::getTimestampFromId($title, $revId) : $params[2];
         $time = $wgLang->timeanddate($ts, true);
         $links .= ' (';
         $links .= Linker::linkKnown($title, wfMessage('review-logentry-id', $revId, $time)->escaped(), array(), array('oldid' => $revId, 'diff' => 'prev') + FlaggedRevs::diffOnlyCGI());
         $links .= ')';
     }
     return $links;
 }
 /**
  * Automatically review an revision and add a log entry in the review log.
  *
  * This is called during edit operations after the new revision is added
  * and the page tables updated, but before LinksUpdate is called.
  *
  * $auto is here for revisions checked off to be reviewed. Auto-review
  * triggers on edit, but we don't want those to count as just automatic.
  * This also makes it so the user's name shows up in the page history.
  *
  * If $flags is given, then they will be the review tags. If not, the one
  * from the stable version will be used or minimal tags if that's not possible.
  * If no appropriate tags can be found, then the review will abort.
  */
 public static function autoReviewEdit(WikiPage $article, $user, Revision $rev, array $flags = null, $auto = true)
 {
     wfProfileIn(__METHOD__);
     $title = $article->getTitle();
     // convenience
     # Get current stable version ID (for logging)
     $oldSv = FlaggedRevision::newFromStable($title, FR_MASTER);
     $oldSvId = $oldSv ? $oldSv->getRevId() : 0;
     # Set the auto-review tags from the prior stable version.
     # Normally, this should already be done and given here...
     if (!is_array($flags)) {
         if ($oldSv) {
             # Use the last stable version if $flags not given
             if ($user->isAllowed('bot')) {
                 $flags = $oldSv->getTags();
                 // no change for bot edits
             } else {
                 # Account for perms/tags...
                 $flags = self::getAutoReviewTags($user, $oldSv->getTags());
             }
         } else {
             // new page?
             $flags = self::quickTags(FR_CHECKED);
             // use minimal level
         }
         if (!is_array($flags)) {
             wfProfileOut(__METHOD__);
             return false;
             // can't auto-review this revision
         }
     }
     # Get review property flags
     $propFlags = $auto ? array('auto') : array();
     # Note: this needs to match the prepareContentForEdit() call WikiPage::doEditContent.
     # This is for consistency and also to avoid triggering a second parse otherwise.
     $editInfo = $article->prepareContentForEdit($rev->getContent(), null, $user, $rev->getContentFormat());
     $poutput = $editInfo->output;
     // revision HTML output
     # Get the "review time" versions of templates and files.
     # This tries to make sure each template/file version either came from the stable
     # version of that template/file or was a "review time" version used in the stable
     # version of this page. If a pending version of a template/file is currently vandalism,
     # we try to avoid storing its ID as the "review time" version so it won't show up when
     # someone views the page. If not possible, this stores the current template/file.
     if (FlaggedRevs::inclusionSetting() === FR_INCLUDES_CURRENT) {
         $tVersions = $poutput->getTemplateIds();
         $fVersions = $poutput->getFileSearchOptions();
     } else {
         $tVersions = $oldSv ? $oldSv->getTemplateVersions() : array();
         $fVersions = $oldSv ? $oldSv->getFileVersions() : array();
         foreach ($poutput->getTemplateIds() as $ns => $pages) {
             foreach ($pages as $dbKey => $revId) {
                 if (!isset($tVersions[$ns][$dbKey])) {
                     $srev = FlaggedRevision::newFromStable(Title::makeTitle($ns, $dbKey));
                     if ($srev) {
                         // use stable
                         $tVersions[$ns][$dbKey] = $srev->getRevId();
                     } else {
                         // use current
                         $tVersions[$ns][$dbKey] = $revId;
                     }
                 }
             }
         }
         foreach ($poutput->getFileSearchOptions() as $dbKey => $info) {
             if (!isset($fVersions[$dbKey])) {
                 $srev = FlaggedRevision::newFromStable(Title::makeTitle(NS_FILE, $dbKey));
                 if ($srev && $srev->getFileTimestamp()) {
                     // use stable
                     $fVersions[$dbKey]['time'] = $srev->getFileTimestamp();
                     $fVersions[$dbKey]['sha1'] = $srev->getFileSha1();
                 } else {
                     // use current
                     $fVersions[$dbKey]['time'] = $info['time'];
                     $fVersions[$dbKey]['sha1'] = $info['sha1'];
                 }
             }
         }
     }
     # If this is an image page, get the corresponding file version info...
     $fileData = array('name' => null, 'timestamp' => null, 'sha1' => null);
     if ($title->getNamespace() == NS_FILE) {
         # We must use WikiFilePage process cache on upload or get bitten by slave lag
         $file = $article instanceof WikiFilePage || $article instanceof ImagePage ? $article->getFile() : wfFindFile($title, array('bypassCache' => true));
         // skip cache; bug 31056
         if (is_object($file) && $file->exists()) {
             $fileData['name'] = $title->getDBkey();
             $fileData['timestamp'] = $file->getTimestamp();
             $fileData['sha1'] = $file->getSha1();
         }
     }
     # Our review entry
     $flaggedRevision = new FlaggedRevision(array('rev' => $rev, 'user_id' => $user->getId(), 'timestamp' => $rev->getTimestamp(), 'quality' => FlaggedRevs::getQualityTier($flags, 0), 'tags' => FlaggedRevision::flattenRevisionTags($flags), 'img_name' => $fileData['name'], 'img_timestamp' => $fileData['timestamp'], 'img_sha1' => $fileData['sha1'], 'templateVersions' => $tVersions, 'fileVersions' => $fVersions, 'flags' => implode(',', $propFlags)));
     $flaggedRevision->insert();
     # Update the article review log
     FlaggedRevsLog::updateReviewLog($title, $flags, array(), '', $rev->getId(), $oldSvId, true, $auto);
     # Update page and tracking tables and clear cache
     FlaggedRevs::stableVersionUpdates($article);
     wfProfileOut(__METHOD__);
     return true;
 }
 /**
  * Record a log entry on the stability config change action
  * @param Title $title
  * @param array $config
  * @param array $oldConfig
  * @param string $reason
  */
 public static function updateStabilityLog(Title $title, array $config, array $oldConfig, $reason)
 {
     $log = new LogPage('stable');
     if (FRPageConfig::configIsReset($config)) {
         # We are going back to default settings
         $log->addEntry('reset', $title, $reason);
     } else {
         # We are changing to non-default settings
         $action = $oldConfig === FRPageConfig::getDefaultVisibilitySettings() ? 'config' : 'modify';
         // modified an existing custom configuration
         $log->addEntry($action, $title, $reason, FlaggedRevsLog::collapseParams(self::stabilityLogParams($config)));
     }
 }
 /**
  * Automatically review an revision and add a log entry in the review log.
  *
  * This is called during edit operations after the new revision is added
  * and the page tables updated, but before LinksUpdate is called.
  *
  * $auto is here for revisions checked off to be reviewed. Auto-review
  * triggers on edit, but we don't want those to count as just automatic.
  * This also makes it so the user's name shows up in the page history.
  *
  * If $flags is given, then they will be the review tags. If not, the one
  * from the stable version will be used or minimal tags if that's not possible.
  * If no appropriate tags can be found, then the review will abort.
  */
 public static function autoReviewEdit(Page $article, $user, Revision $rev, array $flags = null, $auto = true)
 {
     wfProfileIn(__METHOD__);
     $title = $article->getTitle();
     // convenience
     # Get current stable version ID (for logging)
     $oldSv = FlaggedRevision::newFromStable($title, FR_MASTER);
     $oldSvId = $oldSv ? $oldSv->getRevId() : 0;
     # Set the auto-review tags from the prior stable version.
     # Normally, this should already be done and given here...
     if (!is_array($flags)) {
         if ($oldSv) {
             # Use the last stable version if $flags not given
             if ($user->isAllowed('bot')) {
                 $flags = $oldSv->getTags();
                 // no change for bot edits
             } else {
                 # Account for perms/tags...
                 $flags = self::getAutoReviewTags($user, $oldSv->getTags());
             }
         } else {
             // new page?
             $flags = self::quickTags(FR_CHECKED);
             // use minimal level
         }
         if (!is_array($flags)) {
             wfProfileOut(__METHOD__);
             return false;
             // can't auto-review this revision
         }
     }
     # Get review property flags
     $propFlags = $auto ? array('auto') : array();
     # Rev ID is not put into parser on edit, so do the same here.
     # Also, a second parse would be triggered otherwise.
     $editInfo = $article->prepareTextForEdit($rev->getText());
     $poutput = $editInfo->output;
     // revision HTML output
     # If this is an image page, store corresponding file info
     $fileData = array('name' => null, 'timestamp' => null, 'sha1' => null);
     if ($title->getNamespace() == NS_FILE) {
         # We must use WikiFilePage process cache on upload or get bitten by slave lag
         $file = $article instanceof WikiFilePage || $article instanceof ImagePage ? $article->getFile() : wfFindFile($title, array('bypassCache' => true));
         // skip cache; bug 31056
         if (is_object($file) && $file->exists()) {
             $fileData['name'] = $title->getDBkey();
             $fileData['timestamp'] = $file->getTimestamp();
             $fileData['sha1'] = $file->getSha1();
         }
     }
     # Our review entry
     $flaggedRevision = new FlaggedRevision(array('rev' => $rev, 'user_id' => $user->getId(), 'timestamp' => $rev->getTimestamp(), 'quality' => FlaggedRevs::getQualityTier($flags, 0), 'tags' => FlaggedRevision::flattenRevisionTags($flags), 'img_name' => $fileData['name'], 'img_timestamp' => $fileData['timestamp'], 'img_sha1' => $fileData['sha1'], 'templateVersions' => $poutput->getTemplateIds(), 'fileVersions' => $poutput->getFileSearchOptions(), 'flags' => implode(',', $propFlags)));
     $flaggedRevision->insert();
     # Update the article review log
     FlaggedRevsLog::updateReviewLog($title, $flags, array(), '', $rev->getId(), $oldSvId, true, $auto);
     # Update page and tracking tables and clear cache
     FlaggedRevs::stableVersionUpdates($title);
     wfProfileOut(__METHOD__);
     return true;
 }
 protected function updateLogsAndHistory(FlaggableWikiPage $article)
 {
     global $wgContLang;
     $newConfig = $this->getNewConfig();
     $oldConfig = $this->getOldConfig();
     $reason = $this->getReason();
     # Insert stability log entry...
     FlaggedRevsLog::updateStabilityLog($this->page, $newConfig, $oldConfig, $reason);
     # Build null-edit comment...<action: reason [settings] (expiry)>
     if (FRPageConfig::configIsReset($newConfig)) {
         $type = "stable-logentry-reset";
         $settings = '';
         // no level, expiry info
     } else {
         $type = "stable-logentry-config";
         // Settings message in text form (e.g. [x=a,y=b,z])
         $params = FlaggedRevsLog::stabilityLogParams($newConfig);
         $settings = FlaggedRevsLogView::stabilitySettings($params, true);
     }
     $comment = $wgContLang->ucfirst(wfMsgForContent($type, $this->page->getPrefixedText()));
     // action
     if ($reason != '') {
         $comment .= wfMsgForContent('colon-separator') . $reason;
         // add reason
     }
     if ($settings != '') {
         $comment .= " {$settings}";
         // add settings
     }
     # Insert a null revision...
     $dbw = wfGetDB(DB_MASTER);
     $nullRev = Revision::newNullRevision($dbw, $article->getId(), $comment, true);
     $nullRev->insertOn($dbw);
     # Update page record and touch page
     $oldLatest = $nullRev->getParentId();
     $article->updateRevisionOn($dbw, $nullRev, $oldLatest);
     wfRunHooks('NewRevisionFromEditComplete', array($article, $nullRev, $oldLatest, $this->user));
     # Return null Revision object for autoreview check
     return $nullRev;
 }
 public static function logLineLinks($type, $action, $title, $params, &$comment, &$rv, $ts)
 {
     if (!$title) {
         return true;
         // sanity check
     }
     // Stability log
     if ($type == 'stable' && FlaggedRevsLog::isStabilityAction($action)) {
         $rv .= FlaggedRevsLogView::stabilityLogLinks($title, $ts, $params);
         // Review log
     } elseif ($type == 'review' && FlaggedRevsLog::isReviewAction($action)) {
         $rv .= FlaggedRevsLogView::reviewLogLinks($action, $title, $params);
     }
     return true;
 }