/** * Get a selector of review levels. Used for filters. * @param int $selected, selected level * @param string $all, all selector msg? * @param int $max max level? * @return string */ public static function getLevelMenu($selected = null, $all = 'revreview-filter-all', $max = 2) { $s = "<label for='wpLevel'>" . wfMsgHtml('revreview-levelfilter') . "</label>\n"; $s .= Xml::openElement('select', array('name' => 'level', 'id' => 'wpLevel')); if ($all !== false) { $s .= Xml::option(wfMsg($all), -1, $selected === -1); } $s .= Xml::option(wfMsg('revreview-lev-basic'), 0, $selected === 0); if (FlaggedRevs::qualityVersions()) { $s .= Xml::option(wfMsg('revreview-lev-quality'), 1, $selected === 1); } if ($max >= 2 && FlaggedRevs::pristineVersions()) { $s .= Xml::option(wfMsg('revreview-lev-pristine'), 2, $selected === 2); } # Note: Pristine not tracked at sp:QualityOversight (counts as quality) $s .= Xml::closeElement('select') . "\n"; return $s; }
protected function showForm() { global $wgScript; # Add explanatory text $this->getOutput()->addWikiMsg('unreviewedpages-list', $this->getLanguage()->formatNum($this->pager->getNumRows())); # show/hide links $showhide = array($this->msg('show')->escaped(), $this->msg('hide')->escaped()); $onoff = 1 - $this->hideRedirs; $link = Linker::link($this->getPageTitle(), $showhide[$onoff], array(), array('hideredirs' => $onoff, 'category' => $this->category, 'namespace' => $this->namespace)); $showhideredirs = $this->msg('whatlinkshere-hideredirs')->rawParams($link)->escaped(); # Add form... $form = Html::openElement('form', array('name' => 'unreviewedpages', 'action' => $wgScript, 'method' => 'get')) . "\n"; $form .= "<fieldset><legend>" . $this->msg('unreviewedpages-legend')->escaped() . "</legend>\n"; $form .= Html::hidden('title', $this->getPageTitle()->getPrefixedDBKey()) . "\n"; # Add dropdowns as needed if (count(FlaggedRevs::getReviewNamespaces()) > 1) { $form .= FlaggedRevsXML::getNamespaceMenu($this->namespace) . ' '; } if (FlaggedRevs::qualityVersions()) { $form .= FlaggedRevsXML::getLevelMenu($this->level, false, 1) . ' '; } $form .= "<span style='white-space: nowrap;'>" . Xml::label($this->msg('unreviewedpages-category')->text(), 'category') . ' ' . Xml::input('category', 30, $this->category, array('id' => 'category')) . '</span><br />'; $form .= $showhideredirs . '  '; $form .= Xml::submitButton($this->msg('allpagessubmit')->text()); $form .= '</fieldset>'; $form .= Html::closeElement('form') . "\n"; # Query may get too slow to be live... if (!$this->live) { $dbr = wfGetDB(DB_SLAVE); $ts = $dbr->selectField('querycache_info', 'qci_timestamp', array('qci_type' => 'fr_unreviewedpages'), __METHOD__); if ($ts) { $ts = wfTimestamp(TS_MW, $ts); $td = $this->getLanguage()->timeanddate($ts); $d = $this->getLanguage()->date($ts); $t = $this->getLanguage()->time($ts); $form .= $this->msg('perfcachedts', $td, $d, $t)->parseAsBlock(); } else { $form .= $this->msg('perfcached')->parseAsBlock(); } } $this->getOutput()->addHTML($form); }
protected function showRatingIcon() { if (FlaggedRevs::useOnlyIfProtected()) { // If there is only one quality level and we have tabs to know // which version we are looking at, then just use the lock icon... return FlaggedRevs::qualityVersions(); } return true; }
private function showForm() { global $wgScript; $this->getOutput()->addHTML(Xml::openElement('form', array('name' => 'qualityoversight', 'action' => $wgScript, 'method' => 'get')) . '<fieldset><legend>' . $this->msg('qualityoversight-legend')->escaped() . '</legend><p>' . Html::hidden('title', $this->getPageTitle()->getPrefixedDBKey()) . FlaggedRevsXML::getNamespaceMenu($this->namespace) . ' ' . (FlaggedRevs::qualityVersions() ? FlaggedRevsXML::getLevelMenu($this->level, 'revreview-filter-all', 1) . ' ' : "") . Xml::inputLabel($this->msg('specialloguserlabel')->text(), 'user', 'user', 20, $this->user) . '<br />' . FlaggedRevsXML::getStatusFilterMenu($this->status) . ' ' . FlaggedRevsXML::getAutoFilterMenu($this->automatic) . ' ' . Xml::submitButton($this->msg('go')->text()) . '</p></fieldset>' . Xml::closeElement('form')); }
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; }
public function formatRow($row) { $title = Title::newFromRow($row); $link = Linker::link($title); # Link to page $dirmark = $this->getLanguage()->getDirMark(); # Direction mark $stxt = ''; # Size (bytes) if (!is_null($size = $row->page_len)) { if ($size == 0) { $stxt = ' <small>' . $this->msg('historyempty')->escaped() . '</small>'; } else { $stxt = ' <small>' . $this->msg('historysize')->numParams($size)->escaped() . '</small>'; } } # Link to list of reviewed versions for page $list = Linker::linkKnown(SpecialPage::getTitleFor('ReviewedVersions'), $this->msg('reviewedpages-all')->escaped(), array(), 'page=' . $title->getPrefixedUrl()); # Link to highest tier rev $best = ''; if (FlaggedRevs::qualityVersions()) { $best = Linker::linkKnown($title, $this->msg('reviewedpages-best')->escaped(), array(), 'stableid=best'); $best = " [{$best}]"; } return "<li>{$link} {$dirmark} {$stxt} ({$list}){$best}</li>"; }
/** * Get a FlaggedRevision of the stable version of a title. * Skips tracking tables to figure out new stable version. * @param Title $title, page title * @param int $flags (FR_MASTER, FR_FOR_UPDATE) * @param array $config, optional page config (use to skip queries) * @param string $precedence (latest,quality,pristine) * @return FlaggedRevision|null (null on failure) */ public static function determineStable(Title $title, $flags = 0, $config = array(), $precedence = 'latest') { if (!FlaggedRevs::inReviewNamespace($title)) { return null; // short-circuit } $options = array(); # User master/slave as appropriate... if ($flags & FR_FOR_UPDATE || $flags & FR_MASTER) { $db = wfGetDB(DB_MASTER); if ($flags & FR_FOR_UPDATE) { $options[] = 'FOR UPDATE'; } $pageId = $title->getArticleID(Title::GAID_FOR_UPDATE); } else { $db = wfGetDB(DB_SLAVE); $pageId = $title->getArticleID(); } if (!$pageId) { return null; // short-circuit query } # Get visiblity settings to see if page is reviewable... if (FlaggedRevs::useOnlyIfProtected()) { if (empty($config)) { $config = FRPageConfig::getStabilitySettings($title, $flags); } if (!$config['override']) { return null; // page is not reviewable; no stable version } } $baseConds = array('fr_page_id' => $pageId, 'rev_id = fr_rev_id', 'rev_page = fr_page_id', $db->bitAnd('rev_deleted', Revision::DELETED_TEXT) . ' = 0'); $options['ORDER BY'] = 'fr_rev_timestamp DESC'; $row = null; if ($precedence !== 'latest') { # Look for the latest pristine revision... if (FlaggedRevs::pristineVersions()) { $prow = $db->selectRow(array('flaggedrevs', 'revision'), self::selectFields(), array_merge($baseConds, array('fr_quality' => FR_PRISTINE)), __METHOD__, $options); # Looks like a plausible revision $row = $prow ? $prow : $row; } if ($row && $precedence === 'pristine') { // we have what we want already # Look for the latest quality revision... } elseif (FlaggedRevs::qualityVersions()) { // If we found a pristine rev above, this one must be newer... $newerClause = $row ? array('fr_rev_timestamp > ' . $db->addQuotes($row->fr_rev_timestamp)) : array(); $qrow = $db->selectRow(array('flaggedrevs', 'revision'), self::selectFields(), array_merge($baseConds, array('fr_quality' => FR_QUALITY), $newerClause), __METHOD__, $options); $row = $qrow ? $qrow : $row; } } # Do we have one? If not, try the latest reviewed revision... if (!$row) { $row = $db->selectRow(array('flaggedrevs', 'revision'), self::selectFields(), $baseConds, __METHOD__, $options); if (!$row) { return null; } } $frev = new self($row); $frev->mTitle = $title; return $frev; }
public function formatRow($row) { $css = $quality = $underReview = ''; $title = Title::newFromRow($row); $stxt = ChangesList::showCharacterDifference($row->rev_len, $row->page_len); # Page links... $link = Linker::link($title); $hist = Linker::linkKnown($title, wfMsgHtml('hist'), array(), 'action=history'); $review = Linker::linkKnown($title, wfMsg('pendingchanges-diff'), array(), array('diff' => 'cur', 'oldid' => $row->stable) + FlaggedRevs::diffOnlyCGI()); # Show quality level if there are several if (FlaggedRevs::qualityVersions()) { $quality = $row->quality ? wfMsgHtml('revreview-lev-quality') : wfMsgHtml('revreview-lev-basic'); $quality = " <b>[{$quality}]</b>"; } # Is anybody watching? if (!$this->including() && $this->getUser()->isAllowed('unreviewedpages')) { $uw = FRUserActivity::numUsersWatchingPage($title); $watching = $uw ? wfMsgExt('pendingchanges-watched', 'parsemag', $this->getLang()->formatNum($uw)) : wfMsgHtml('pendingchanges-unwatched'); $watching = " {$watching}"; } else { $uw = -1; $watching = ''; // leave out data } # Get how long the first unreviewed edit has been waiting... if ($row->pending_since) { $firstPendingTime = wfTimestamp(TS_UNIX, $row->pending_since); $hours = ($this->currentUnixTS - $firstPendingTime) / 3600; // After three days, just use days if ($hours > 3 * 24) { $days = round($hours / 24, 0); $age = wfMsgExt('pendingchanges-days', 'parsemag', $this->getLang()->formatNum($days)); // If one or more hours, use hours } elseif ($hours >= 1) { $hours = round($hours, 0); $age = wfMsgExt('pendingchanges-hours', 'parsemag', $this->getLang()->formatNum($hours)); } else { $age = wfMsg('pendingchanges-recent'); // hot off the press :) } // Oh-noes! $css = self::getLineClass($hours, $uw); $css = $css ? " class='{$css}'" : ""; } else { $age = ""; // wtf? } # Show if a user is looking at this page list($u, $ts) = FRUserActivity::getUserReviewingDiff($row->stable, $row->page_latest); if ($u !== null) { $underReview = ' <span class="fr-under-review">' . wfMsgHtml('pendingchanges-viewing') . '</span>'; } return "<li{$css}>{$link} ({$hist}) {$stxt} ({$review}) <i>{$age}</i>" . "{$quality}{$watching}{$underReview}</li>"; }