/** * 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); }
public function getParamDescription() { $desc = array('revid' => 'The revision ID for which to set the flags', 'token' => 'An edit token retrieved through prop=info', 'comment' => 'Comment for the review (optional)', 'unapprove' => 'If set, revision will be unapproved rather than approved.'); if (!FlaggedRevs::binaryFlagging()) { foreach (FlaggedRevs::getTags() as $flagname) { $desc['flag_' . $flagname] = "Set the flag ''{$flagname}'' to the specified value"; } } return $desc; }
protected static function load() { global $wgFlaggedRevsTags, $wgFlaggedRevTags; if (self::$loaded) { return true; } if (!FlaggedRevsSetup::isReady()) { // sanity throw new MWException('FlaggedRevs config loaded too soon! Possibly before LocalSettings.php!'); } self::$loaded = true; $flaggedRevsTags = null; if (isset($wgFlaggedRevTags)) { $flaggedRevsTags = $wgFlaggedRevTags; // b/c wfWarn('Please use $wgFlaggedRevsTags instead of $wgFlaggedRevTags in config.'); } elseif (isset($wgFlaggedRevsTags)) { $flaggedRevsTags = $wgFlaggedRevsTags; } # Assume true, then set to false if needed if (!empty($flaggedRevsTags)) { self::$qualityVersions = true; self::$pristineVersions = true; self::$binaryFlagging = count($flaggedRevsTags) <= 1; } foreach ($flaggedRevsTags as $tag => $levels) { # Sanity checks $safeTag = htmlspecialchars($tag); if (!preg_match('/^[a-zA-Z]{1,20}$/', $tag) || $safeTag !== $tag) { throw new MWException('FlaggedRevs given invalid tag name!'); } # Define "quality" and "pristine" reqs if (is_array($levels)) { $minQL = $levels['quality']; $minPL = $levels['pristine']; $ratingLevels = $levels['levels']; # B/C, $levels is just an integer (minQL) } else { global $wgFlaggedRevPristine, $wgFlaggedRevValues; $ratingLevels = isset($wgFlaggedRevValues) ? $wgFlaggedRevValues : 1; $minQL = $levels; // an integer $minPL = isset($wgFlaggedRevPristine) ? $wgFlaggedRevPristine : $ratingLevels + 1; wfWarn('Please update the format of $wgFlaggedRevsTags in config.'); } # Set FlaggedRevs tags self::$dimensions[$tag] = array(); for ($i = 0; $i <= $ratingLevels; $i++) { self::$dimensions[$tag][$i] = "{$tag}-{$i}"; } if ($ratingLevels > 1) { self::$binaryFlagging = false; // more than one level } # Sanity checks if (!is_integer($minQL) || !is_integer($minPL)) { throw new MWException('FlaggedRevs given invalid tag value!'); } if ($minQL > $ratingLevels) { self::$qualityVersions = false; self::$pristineVersions = false; } if ($minPL > $ratingLevels) { self::$pristineVersions = false; } self::$minQL[$tag] = max($minQL, 1); self::$minPL[$tag] = max($minPL, 1); self::$minSL[$tag] = 1; } global $wgFlaggedRevsTagsRestrictions, $wgFlagRestrictions; if (isset($wgFlagRestrictions)) { self::$tagRestrictions = $wgFlagRestrictions; // b/c wfWarn('Please use $wgFlaggedRevsTagsRestrictions instead of $wgFlagRestrictions in config.'); } else { self::$tagRestrictions = $wgFlaggedRevsTagsRestrictions; } # Make sure that the restriction levels are unique global $wgFlaggedRevsRestrictionLevels; self::$restrictionLevels = array_unique($wgFlaggedRevsRestrictionLevels); self::$restrictionLevels = array_filter(self::$restrictionLevels, 'strlen'); # Make sure no talk namespaces are in review namespace global $wgFlaggedRevsNamespaces; foreach ($wgFlaggedRevsNamespaces as $ns) { if (MWNamespace::isTalk($ns)) { throw new MWException('FlaggedRevs given talk namespace in $wgFlaggedRevsNamespaces!'); } elseif ($ns == NS_MEDIAWIKI) { throw new MWException('FlaggedRevs given NS_MEDIAWIKI in $wgFlaggedRevsNamespaces!'); } } self::$reviewNamespaces = $wgFlaggedRevsNamespaces; # Handle $wgFlaggedRevsAutoReview settings global $wgFlaggedRevsAutoReview, $wgFlaggedRevsAutoReviewNew; if (is_int($wgFlaggedRevsAutoReview)) { self::$autoReviewConfig = $wgFlaggedRevsAutoReview; } else { // b/c if ($wgFlaggedRevsAutoReview) { self::$autoReviewConfig = FR_AUTOREVIEW_CHANGES; } wfWarn('$wgFlaggedRevsAutoReview is now a bitfield instead of a boolean.'); } if (isset($wgFlaggedRevsAutoReviewNew)) { // b/c self::$autoReviewConfig = $wgFlaggedRevsAutoReviewNew ? self::$autoReviewConfig |= FR_AUTOREVIEW_CREATION : self::$autoReviewConfig & ~FR_AUTOREVIEW_CREATION; wfWarn('$wgFlaggedRevsAutoReviewNew is deprecated; use $wgFlaggedRevsAutoReview.'); } 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; }
/** * Generates review form submit buttons * @param int $rejectId left rev ID for "reject" on diffs * @param FlaggedRevision $frev, the flagged revision, if any * @param bool $disabled, is the form disabled? * @param bool $reviewIncludes, force the review button to be usable? * @return string */ protected static function submitButtons($rejectId, $frev, $disabled, $reviewIncludes = false) { $disAttrib = array('disabled' => 'disabled'); # ACCEPT BUTTON: accept a revision # We may want to re-review to change: # (a) notes (b) tags (c) pending template/file changes if (FlaggedRevs::binaryFlagging()) { // just the buttons $applicable = !$frev || $reviewIncludes; // no tags/notes $needsChange = false; // no state change possible } else { // buttons + ratings $applicable = true; // tags might change $needsChange = $frev && !$reviewIncludes; } $s = Xml::submitButton(wfMessage('revreview-submit-review')->escaped(), array('name' => 'wpApprove', 'id' => 'mw-fr-submit-accept', 'accesskey' => wfMessage('revreview-ak-review')->text(), 'title' => wfMessage('revreview-tt-flag')->text() . ' [' . wfMessage('revreview-ak-review')->text() . ']') + ($disabled || !$applicable ? $disAttrib : array())); # REJECT BUTTON: revert from a pending revision to the stable if ($rejectId) { $s .= ' '; $s .= Xml::submitButton(wfMessage('revreview-submit-reject')->escaped(), array('name' => 'wpReject', 'id' => 'mw-fr-submit-reject', 'title' => wfMessage('revreview-tt-reject')->text()) + ($disabled ? $disAttrib : array())); } # UNACCEPT BUTTON: revoke a revisions acceptance # Hide if revision is not flagged $s .= ' '; $s .= Xml::submitButton(wfMessage('revreview-submit-unreview')->escaped(), array('name' => 'wpUnapprove', 'id' => 'mw-fr-submit-unaccept', 'title' => wfMessage('revreview-tt-unflag')->text(), 'style' => $frev ? '' : 'display:none') + ($disabled ? $disAttrib : array())) . "\n"; // Disable buttons unless state changes in some cases (non-JS compatible) $s .= '<script type="text/javascript">var jsReviewNeedsChange = ' . (int) $needsChange . "</script>\n"; return $s; }