/** * Record a log entry on the review action * @param Title $title * @param array $dims * @param array $oldDims * @param string $comment * @param int $revId, revision ID * @param int $stableId, prior stable revision ID * @param bool $approve, approved? (otherwise unapproved) * @param bool $auto */ public static function updateReviewLog(Title $title, array $dims, array $oldDims, $comment, $revId, $stableId, $approve, $auto = false) { $log = new LogPage('review', false, $auto ? "skipUDP" : "UDP"); # Tag rating list (e.g. accuracy=x, depth=y, style=z) $ratings = array(); # Skip rating list if flagging is just an 0/1 feature... if (!FlaggedRevs::binaryFlagging()) { // Give grep a chance to find the usages: // revreview-accuracy, revreview-depth, revreview-style, // revreview-accuracy-0, revreview-accuracy-1, revreview-accuracy-2, revreview-accuracy-3, revreview-accuracy-4, // revreview-depth-0, revreview-depth-1, revreview-depth-2, revreview-depth-3, revreview-depth-4, // revreview-style-0, revreview-style-1, revreview-style-2, revreview-style-3, revreview-style-4 foreach ($dims as $quality => $level) { $ratings[] = wfMessage("revreview-{$quality}")->inContentLanguage()->text() . wfMessage('colon-separator')->inContentLanguage()->text() . wfMessage("revreview-{$quality}-{$level}")->inContentLanguage()->text(); } } $isAuto = $auto && !FlaggedRevs::isQuality($dims); // Paranoid check // Approved revisions if ($approve) { if ($isAuto) { $comment = wfMessage('revreview-auto')->inContentLanguage()->text(); // override this } # Make comma-separated list of ratings $rating = !empty($ratings) ? '[' . implode(', ', $ratings) . ']' : ''; # Append comment with ratings if ($rating != '') { $comment .= $comment ? " {$rating}" : $rating; } # Sort into the proper action (useful for filtering) $action = FlaggedRevs::isQuality($dims) || FlaggedRevs::isQuality($oldDims) ? 'approve2' : 'approve'; if (!$stableId) { // first time $action .= $isAuto ? "-ia" : "-i"; } elseif ($isAuto) { // automatic $action .= "-a"; } // De-approved revisions } else { $action = FlaggedRevs::isQuality($oldDims) ? 'unapprove2' : 'unapprove'; } $ts = Revision::getTimestampFromId($title, $revId); # Param format is <rev id, old stable id, rev timestamp> $logid = $log->addEntry($action, $title, $comment, array($revId, $stableId, $ts)); # Make log easily searchable by rev_id $log->addRelations('rev_id', array($revId), $logid); }
/** * Tag output function must be called by caller * Parser cache control deferred to caller * @param $srev stable version * @param $tag review box/bar info * @param $prot protection notice * @return ParserOutput */ protected function showStableVersion(FlaggedRevision $srev, &$tag, $prot) { $reqUser = $this->getUser(); $this->load(); $flags = $srev->getTags(); $time = $this->getLang()->date($srev->getTimestamp(), true); # Set display revision ID $this->out->setRevisionId($srev->getRevId()); # Get quality level $quality = FlaggedRevs::isQuality($flags); $synced = $this->article->stableVersionIsSynced(); # Construct some tagging if (!$this->out->isPrintable() && !($this->article->lowProfileUI() && $synced)) { $revsSince = $this->article->getPendingRevCount(); // Simple icon-based UI if ($this->useSimpleUI()) { $icon = ''; # For protection based configs, show lock only if it's not redundant. if ($this->showRatingIcon()) { $icon = FlaggedRevsXML::stableStatusIcon($quality); } if (!$reqUser->getId()) { $msgHTML = ''; // Anons just see simple icons } else { $msg = $quality ? 'revreview-quick-quality' : 'revreview-quick-basic'; # Uses messages 'revreview-quick-quality-same', 'revreview-quick-basic-same' $msg = $synced ? "{$msg}-same" : $msg; $msgHTML = wfMsgExt($msg, 'parseinline', $srev->getRevId(), $revsSince); } $msgHTML = $prot . $icon . $msgHTML; $tag = FlaggedRevsXML::prettyRatingBox($srev, $msgHTML, $revsSince, 'stable', $synced); // Standard UI } else { $icon = FlaggedRevsXML::stableStatusIcon($quality); $msg = $quality ? 'revreview-quality' : 'revreview-basic'; if ($synced) { # uses messages 'revreview-quality-same', 'revreview-basic-same' $msg .= '-same'; } elseif ($revsSince == 0) { # uses messages 'revreview-quality-i', 'revreview-basic-i' $msg .= '-i'; } $tag = $prot . $icon; $tag .= wfMsgExt($msg, 'parseinline', $srev->getRevId(), $time, $revsSince); if (!empty($flags)) { $tag .= FlaggedRevsXML::ratingToggle(); $tag .= "<div id='mw-fr-revisiondetails' style='display:block;'>" . FlaggedRevsXML::addTagRatings($flags) . '</div>'; } } } # Get parsed stable version and output HTML $pOpts = $this->article->makeParserOptions($reqUser); $parserCache = FRParserCacheStable::singleton(); $parserOut = $parserCache->get($this->article, $pOpts); # Do not use the parser cache if it lacks mImageTimeKeys and there is a # chance that a review form will be added to this page (which requires the versions). $canReview = $this->article->getTitle()->userCan('review'); if ($parserOut && (!$canReview || FlaggedRevs::parserOutputIsVersioned($parserOut))) { # Cache hit. Note that redirects are not cached. $this->out->addParserOutput($parserOut); } else { $text = $srev->getRevText(); # Get the new stable parser output... $parserOut = FlaggedRevs::parseStableText($this->article->getTitle(), $text, $srev->getRevId(), $pOpts); $redirHtml = $this->getRedirectHtml($text); if ($redirHtml == '') { // page is not a redirect... # Update the stable version cache $parserCache->save($parserOut, $this->article, $pOpts); # Add the stable output to the page view $this->out->addParserOutput($parserOut); } else { // page is a redirect... $this->out->addHtml($redirHtml); # Add output to set categories, displaytitle, etc. $this->out->addParserOutputNoText($parserOut); } # Update the stable version dependancies FlaggedRevs::updateStableOnlyDeps($this->article, $parserOut); } # Update page sync status for tracking purposes. # NOTE: avoids master hits and doesn't have to be perfect for what it does if ($this->article->syncedInTracking() != $synced) { if (wfGetLB()->safeGetLag(wfGetDB(DB_SLAVE)) <= 5) { // avoid write-delay cycles $this->article->updateSyncStatus($synced); } } return $parserOut; }
/** * 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; }
public static function pendingEditNotice($flaggedArticle, $frev, $revsSince) { global $wgLang; $flags = $frev->getTags(); $time = $wgLang->date($frev->getTimestamp(), true); # Add message text for pending edits $msg = FlaggedRevs::isQuality($flags) ? 'revreview-pending-quality' : 'revreview-pending-basic'; $tag = wfMsgExt($msg, 'parseinline', $frev->getRevId(), $time, $revsSince); return $tag; }
/** * Same as pendingEditNotice(), but returns a Message object. */ public static function pendingEditNoticeMessage($flaggedArticle, $frev, $revsSince) { global $wgLang; $flags = $frev->getTags(); $time = $wgLang->date($frev->getTimestamp(), true); # Add message text for pending edits $msg = FlaggedRevs::isQuality($flags) ? 'revreview-pending-quality' : 'revreview-pending-basic'; return wfMessage($msg, $frev->getRevId(), $time)->numParams($revsSince); }