public function execute() { global $wgContLang; $pageSet = $this->getPageSet(); $pageids = array_keys($pageSet->getGoodTitles()); if (!$pageids) { return true; } // Construct SQL Query $this->addTables('flaggedpages'); $this->addFields(array('fp_page_id', 'fp_stable', 'fp_quality', 'fp_pending_since')); $this->addWhereFld('fp_page_id', $pageids); $res = $this->select(__METHOD__); $result = $this->getResult(); foreach ($res as $row) { $data = array('stable_revid' => intval($row->fp_stable), 'level' => intval($row->fp_quality), 'level_text' => FlaggedRevs::getQualityLevelText($row->fp_quality)); if ($row->fp_pending_since) { $data['pending_since'] = wfTimestamp(TS_ISO_8601, $row->fp_pending_since); } $result->addValue(array('query', 'pages', $row->fp_page_id), 'flagged', $data); } $this->resetQueryParams(); $this->addTables('flaggedpage_config'); $this->addFields(array('fpc_page_id', 'fpc_level', 'fpc_expiry')); $this->addWhereFld('fpc_page_id', $pageids); foreach ($this->select(__METHOD__) as $row) { $result->addValue(array('query', 'pages', $row->fpc_page_id, 'flagged'), 'protection_level', $row->fpc_level); $result->addValue(array('query', 'pages', $row->fpc_page_id, 'flagged'), 'protection_expiry', $wgContLang->formatExpiry($row->fpc_expiry, TS_ISO_8601)); } return true; }
protected function autoreview_current(User $user) { $this->output("Auto-reviewing all current page versions...\n"); if (!$user->getID()) { $this->output("Invalid user specified.\n"); return; } elseif (!$user->isAllowed('review')) { $this->output("User specified (id: {$user->getID()}) does not have \"review\" rights.\n"); return; } $db = wfGetDB(DB_MASTER); $this->output("Reviewer username: "******"\n"); $start = $db->selectField('page', 'MIN(page_id)', false, __METHOD__); $end = $db->selectField('page', 'MAX(page_id)', false, __METHOD__); if (is_null($start) || is_null($end)) { $this->output("...page table seems to be empty.\n"); return; } # Do remaining chunk $end += $this->mBatchSize - 1; $blockStart = $start; $blockEnd = $start + $this->mBatchSize - 1; $count = 0; $changed = 0; $flags = FlaggedRevs::quickTags(FR_CHECKED); // Assume basic level while ($blockEnd <= $end) { $this->output("...doing page_id from {$blockStart} to {$blockEnd}\n"); $res = $db->select(array('page', 'revision'), '*', array("page_id BETWEEN {$blockStart} AND {$blockEnd}", 'page_namespace' => FlaggedRevs::getReviewNamespaces(), 'rev_id = page_latest'), __METHOD__); # Go through and autoreview the current version of every page... foreach ($res as $row) { $title = Title::newFromRow($row); $rev = Revision::newFromRow($row); # Is it already reviewed? $frev = FlaggedRevision::newFromTitle($title, $row->page_latest, FR_MASTER); # Rev should exist, but to be safe... if (!$frev && $rev) { $article = new Article($title); $db->begin(); FlaggedRevs::autoReviewEdit($article, $user, $rev, $flags, true); FlaggedRevs::HTMLCacheUpdates($article->getTitle()); $db->commit(); $changed++; } $count++; } $db->freeResult($res); $blockStart += $this->mBatchSize - 1; $blockEnd += $this->mBatchSize - 1; // XXX: Don't let deferred jobs array get absurdly large (bug 24375) DeferredUpdates::doUpdates('commit'); wfWaitForSlaves(5); } $this->output("Auto-reviewing of all pages complete ..." . "{$count} rows [{$changed} changed]\n"); }
public static function addApiRevisionData(&$module) { if (!$module instanceof ApiQueryRevisions) { return true; } $params = $module->extractRequestParams(false); if (empty($params['prop']) || !in_array('flagged', $params['prop'])) { return true; } if (!in_array('ids', $params['prop'])) { $module->dieUsage('if rvprop=flagged is set, you must also set rvprop=ids', 'missingparam'); } // Get all requested pageids/revids in a mapping: // pageid => revid => array_index of the revision // we will need this later to add data to the result array $result = $module->getResult(); $data = $result->getData(); if (!isset($data['query']) || !isset($data['query']['pages'])) { return true; } foreach ($data['query']['pages'] as $pageid => $page) { if (array_key_exists('revisions', (array) $page)) { foreach ($page['revisions'] as $index => $rev) { if (array_key_exists('revid', (array) $rev)) { $pageids[$pageid][$rev['revid']] = $index; } } } } if (empty($pageids)) { return true; } // Construct SQL Query $db = $module->getDB(); $module->resetQueryParams(); $module->addTables(array('flaggedrevs', 'user')); $module->addFields(array('fr_page_id', 'fr_rev_id', 'fr_timestamp', 'fr_quality', 'fr_tags', 'user_name')); $module->addWhere('fr_user=user_id'); $where = array(); // Construct WHERE-clause to avoid multiplying the number of scanned rows // as flaggedrevs table has composite primary key (fr_page_id,fr_rev_id) foreach ($pageids as $pageid => $revids) { $where[] = $db->makeList(array('fr_page_id' => $pageid, 'fr_rev_id' => array_keys($revids)), LIST_AND); } $module->addWhere($db->makeList($where, LIST_OR)); //$module->addOption( 'USE INDEX', array( 'flaggedrevs' => 'page_rev' ) ); $res = $module->select(__METHOD__); // Add flagging data to result array foreach ($res as $row) { $index = $pageids[$row->fr_page_id][$row->fr_rev_id]; $data = array('user' => $row->user_name, 'timestamp' => wfTimestamp(TS_ISO_8601, $row->fr_timestamp), 'level' => intval($row->fr_quality), 'level_text' => FlaggedRevs::getQualityLevelText($row->fr_quality), 'tags' => FlaggedRevision::expandRevisionTags($row->fr_tags)); $result->addValue(array('query', 'pages', $row->fr_page_id, 'revisions', $index), 'flagged', $data); } return true; }
public function execute() { $this->getMain()->setCacheMode('public'); $minQLTags = FlaggedRevs::quickTags(FR_QUALITY); $minPLTags = FlaggedRevs::quickTags(FR_PRISTINE); $data = array(); foreach (FlaggedRevs::getDimensions() as $tag => $levels) { $data[] = array('name' => $tag, 'levels' => count($levels) - 1, 'tier1' => 1, 'tier2' => $minQLTags[$tag], 'tier3' => $minPLTags[$tag]); } $result = $this->getResult(); $result->setIndexedTagName($data, 'tag'); $result->addValue(null, $this->getModuleName(), $data); }
protected function showStableList() { $out = $this->getOutput(); # Must be a content page if (!FlaggedRevs::inReviewNamespace($this->page)) { $out->addWikiMsg('reviewedversions-none', $this->page->getPrefixedText()); return; } $pager = new ReviewedVersionsPager($this, array(), $this->page); $num = $pager->getNumRows(); if ($num) { $out->addWikiMsg('reviewedversions-list', $this->page->getPrefixedText(), $this->getLang()->formatNum($num)); $out->addHTML($pager->getNavigationBar()); $out->addHTML("<ul>" . $pager->getBody() . "</ul>"); $out->addHTML($pager->getNavigationBar()); } else { $out->addHTML(wfMsgExt('reviewedversions-none', array('parse'), $this->page->getPrefixedText())); } }
/** * (a) Stabilize inclusions in Parser output * (b) Load all of the "review time" versions of template/files from $frev * (c) Load their stable version counterparts (avoids DB hits) * Note: Used when calling FlaggedRevs::parseStableText(). * @param FlaggedRevision $frev * @return void */ public function stabilizeParserOutput(FlaggedRevision $frev) { $tStbVersions = $fStbVersions = array(); // stable versions $tRevVersions = $frev->getTemplateVersions(); $fRevVersions = $frev->getFileVersions(); # We can preload *most* of the stable version IDs the parser will need... if (FlaggedRevs::inclusionSetting() == FR_INCLUDES_STABLE) { $tStbVersions = $frev->getStableTemplateVersions(); $fStbVersions = $frev->getStableFileVersions(); } $this->setReviewedVersions($tRevVersions, $fRevVersions); $this->setStableVersionCache($tStbVersions, $fStbVersions); }
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; }
/** * If this edit will be auto-reviewed on submit * Note: checking wpReviewEdit does not count as auto-reviewed * @param EditPage $editPage * @return bool */ protected function editWillBeAutoreviewed(EditPage $editPage) { $title = $this->article->getTitle(); // convenience if (!$this->article->isReviewable()) { return false; } if ($title->quickUserCan('autoreview')) { if (FlaggedRevs::autoReviewNewPages() && !$this->article->exists()) { return true; // edit will be autoreviewed } if (!isset($editPage->fr_baseFRev)) { $baseRevId = self::getBaseRevId($editPage, $this->getRequest()); $editPage->fr_baseFRev = FlaggedRevision::newFromTitle($title, $baseRevId); } if ($editPage->fr_baseFRev) { return true; // edit will be autoreviewed } } return false; // edit won't be autoreviewed }
/** * 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; }
/** * Updates the flaggedpage_pending table * @param int $pageId Page ID * @abstract int $latest Latest revision * @return void */ protected static function updatePendingList($pageId, $latest) { $data = array(); # Get the highest tier used on this wiki $level = FlaggedRevs::highestReviewTier(); $dbw = wfGetDB(DB_MASTER); # Update pending times for each level, going from highest to lowest $higherLevelId = 0; $higherLevelTS = ''; while ($level >= 0) { # Get the latest revision of this level... # Any revision of one tier is also a revision of lower tiers. # Instead of doing fr_quality > X queries we do exact comparisons # for better INDEX usage. However, in order to treat a rev as the # latest tier X rev, we make sure it is newer than all tier (X+1) revs. $row = $dbw->selectRow(array('flaggedrevs', 'revision'), array('fr_rev_id', 'rev_timestamp'), array('fr_page_id' => $pageId, 'fr_quality' => $level, 'fr_rev_timestamp > ' . $dbw->addQuotes($higherLevelTS), 'rev_id = fr_rev_id', 'rev_page = fr_page_id', 'rev_deleted & ' . Revision::DELETED_TEXT => 0), __METHOD__, array('ORDER BY' => 'fr_rev_timestamp DESC', 'LIMIT' => 1)); # If there is a revision of this level, track it... # Revisions accepted to one tier count as accepted # at the lower tiers (i.e. quality -> checked). if ($row) { $id = $row->fr_rev_id; $ts = $row->rev_timestamp; } else { // use previous rev of higher tier (if any) $id = $higherLevelId; $ts = $higherLevelTS; } # Get edits that actually are pending... if ($id && $latest > $id) { # Get the timestamp of the edit after this version (if any) $nextTimestamp = $dbw->selectField('revision', 'rev_timestamp', array('rev_page' => $pageId, "rev_timestamp > " . $dbw->addQuotes($ts)), __METHOD__, array('ORDER BY' => 'rev_timestamp ASC', 'LIMIT' => 1)); $data[] = array('fpp_page_id' => $pageId, 'fpp_quality' => $level, 'fpp_rev_id' => $id, 'fpp_pending_since' => $nextTimestamp); $higherLevelId = $id; $higherLevelTS = $ts; } $level--; } # Clear any old junk, and insert new rows $dbw->delete('flaggedpage_pending', array('fpp_page_id' => $pageId), __METHOD__); $dbw->insert('flaggedpage_pending', $data, __METHOD__); }
/** * 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; }
function __construct($form, $namespace, $level = -1, $category = '', $size = null, $watched = false, $stable = false) { $this->mForm = $form; # Must be a content page... $vnamespaces = FlaggedRevs::getReviewNamespaces(); if (is_null($namespace)) { $namespace = $vnamespaces; } else { $namespace = intval($namespace); } # Sanity check if (!in_array($namespace, $vnamespaces)) { $namespace = $vnamespaces; } $this->namespace = $namespace; # Sanity check level: 0 = checked; 1 = quality; 2 = pristine $this->level = $level >= 0 && $level <= 2 ? $level : -1; $this->category = $category ? str_replace(' ', '_', $category) : null; $this->size = $size !== null ? intval($size) : null; $this->watched = (bool) $watched; $this->stable = $stable && !FlaggedRevs::isStableShownByDefault() && !FlaggedRevs::useOnlyIfProtected(); parent::__construct(); # Don't get too expensive $this->mLimitsShown = array(20, 50, 100); $this->setLimit($this->mLimit); // apply max limit }
/** * @param int $namespace (null for "all") * @param string $autoreview ('' for "all", 'none' for no restriction) */ function __construct($form, $conds = array(), $namespace, $autoreview, $indef) { $this->mForm = $form; $this->mConds = $conds; $this->indef = $indef; // Must be content pages... $validNS = FlaggedRevs::getReviewNamespaces(); if (is_integer($namespace)) { if (!in_array($namespace, $validNS)) { $namespace = $validNS; // fallback to "all" } } else { $namespace = $validNS; // "all" } $this->namespace = $namespace; if ($autoreview === 'none') { $autoreview = ''; // 'none' => '' } elseif ($autoreview === '') { $autoreview = null; // '' => null } $this->autoreview = $autoreview; parent::__construct(); }
function __construct($form, $live, $namespace, $redirs = false, $category = null, $level = 0) { $this->mForm = $form; $this->live = (bool) $live; # Must be a content page... if (!is_null($namespace)) { $namespace = (int) $namespace; } $vnamespaces = FlaggedRevs::getReviewNamespaces(); # Must be a single NS for perfomance reasons if (is_null($namespace) || !in_array($namespace, $vnamespaces)) { $namespace = !$vnamespaces ? -1 : $vnamespaces[0]; } $this->namespace = $namespace; $this->category = $category ? str_replace(' ', '_', $category) : null; $this->level = intval($level); $this->showredirs = (bool) $redirs; parent::__construct(); // Don't get too expensive $this->mLimitsShown = array(20, 50); $this->setLimit($this->mLimit); // apply max limit }
/** * 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); }
function __construct($form, $level = -1, $category = '', $tag = '') { $this->mForm = $form; # Must be a content page... $this->namespace = FlaggedRevs::getReviewNamespaces(); # Sanity check level: 0 = checked; 1 = quality; 2 = pristine $this->level = $level >= 0 && $level <= 2 ? $level : -1; $this->tag = $tag; $this->category = $category ? str_replace(' ', '_', $category) : null; parent::__construct(); // Don't get to expensive $this->mLimitsShown = array(20, 50, 100); $this->setLimit($this->mLimit); // apply max limit }
/** * Purge expired restrictions from the flaggedpage_config table. * The stable version of pages may change and invalidation may be required. */ public static function purgeExpiredConfigurations() { if (wfReadOnly()) { return; } $dbw = wfGetDB(DB_MASTER); # Find pages with expired configs... $config = self::getDefaultVisibilitySettings(); // config is to be reset $encCutoff = $dbw->addQuotes($dbw->timestamp()); $ret = $dbw->select(array('flaggedpage_config', 'page'), array('fpc_page_id', 'page_namespace', 'page_title'), array('page_id = fpc_page_id', 'fpc_expiry < ' . $encCutoff), __METHOD__); # Figured out to do with each page... $pagesClearConfig = array(); $pagesClearTracking = $titlesClearTracking = array(); foreach ($ret as $row) { # If FlaggedRevs got "turned off" (in protection config) # for this page, then clear it from the tracking tables... if (FlaggedRevs::useOnlyIfProtected() && !$config['override']) { $pagesClearTracking[] = $row->fpc_page_id; // no stable version $titlesClearTracking[] = Title::newFromRow($row); // no stable version } $pagesClearConfig[] = $row->fpc_page_id; // page with expired config } # Clear the expired config for these pages... if (count($pagesClearConfig)) { $dbw->delete('flaggedpage_config', array('fpc_page_id' => $pagesClearConfig, 'fpc_expiry < ' . $encCutoff), __METHOD__); } # Clear the tracking rows and update page_touched for the # pages in $pagesClearConfig that do now have a stable version... if (count($pagesClearTracking)) { FlaggedRevs::clearTrackingRows($pagesClearTracking); $dbw->update('page', array('page_touched' => $dbw->timestamp()), array('page_id' => $pagesClearTracking), __METHOD__); } # Also, clear their squid caches and purge other pages that use this page. # NOTE: all of these updates are deferred via $wgDeferredUpdateList. foreach ($titlesClearTracking as $title) { FlaggedRevs::purgeSquid($title); if (FlaggedRevs::inclusionSetting() == FR_INCLUDES_STABLE) { FlaggedRevs::HTMLCacheUpdates($title); // purge pages that use this page } } }
/** * @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; }
public static function AjaxReview() { global $wgUser, $wgOut, $wgRequest; $args = func_get_args(); if (wfReadOnly()) { return '<err#>' . wfMsgExt('revreview-failed', 'parseinline') . wfMsgExt('revreview-submission-invalid', 'parseinline'); } $tags = FlaggedRevs::getTags(); // Make review interface object $form = new RevisionReviewForm($wgUser); $title = null; // target page $editToken = ''; // edit token // Each ajax url argument is of the form param|val. // This means that there is no ugly order dependance. foreach ($args as $arg) { $set = explode('|', $arg, 2); if (count($set) != 2) { return '<err#>' . wfMsgExt('revreview-failed', 'parseinline') . wfMsgExt('revreview-submission-invalid', 'parseinline'); } list($par, $val) = $set; switch ($par) { case "target": $title = Title::newFromURL($val); break; case "oldid": $form->setOldId($val); break; case "refid": $form->setRefId($val); break; case "validatedParams": $form->setValidatedParams($val); break; case "templateParams": $form->setTemplateParams($val); break; case "imageParams": $form->setFileParams($val); break; case "fileVersion": $form->setFileVersion($val); break; case "wpApprove": $form->setApprove($val); break; case "wpUnapprove": $form->setUnapprove($val); break; case "wpReject": $form->setReject($val); break; case "wpReason": $form->setComment($val); break; case "changetime": $form->setLastChangeTime($val); break; case "wpEditToken": $editToken = $val; break; default: $p = preg_replace('/^wp/', '', $par); // kill any "wp" prefix if (in_array($p, $tags)) { $form->setDim($p, $val); } break; } } # Valid target title? if (!$title) { return '<err#>' . wfMsgExt('notargettext', 'parseinline'); } $form->setPage($title); $form->setSessionKey($wgRequest->getSessionData('wsFlaggedRevsKey')); $status = $form->ready(); // all params loaded # Check session via user token if (!$wgUser->matchEditToken($editToken)) { return '<err#>' . wfMsgExt('sessionfailure', 'parseinline'); } # Basic permission checks... $permErrors = $title->getUserPermissionsErrors('review', $wgUser, false); if (!$permErrors) { $permErrors = $title->getUserPermissionsErrors('edit', $wgUser, false); } if ($permErrors) { return '<err#>' . $wgOut->parse($wgOut->formatPermissionsErrorMessage($permErrors, 'review')); } # Try submission... $status = $form->submit(); # Success... if ($status === true) { # Sent new lastChangeTime TS to client for later submissions... $changeTime = $form->getNewLastChangeTime(); if ($form->getAction() === 'approve') { // approve return "<suc#><lct#{$changeTime}>"; } elseif ($form->getAction() === 'unapprove') { // de-approve return "<suc#><lct#{$changeTime}>"; } elseif ($form->getAction() === 'reject') { // revert return "<suc#><lct#{$changeTime}>"; } # Failure... } else { return '<err#>' . wfMsgExt('revreview-failed', 'parse') . '<p>' . wfMsgHtml($status) . '</p>'; } }
/** * 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; }
/** * Get flags for a revision * @param array $tags * @return string */ public static function flattenRevisionTags(array $tags) { $flags = ''; foreach ($tags as $tag => $value) { # Add only currently recognized ones if (FlaggedRevs::getTagLevels($tag)) { $flags .= $tag . ':' . intval($value) . "\n"; } } return $flags; }
/** * Set template and image versions from parsing a revision * @param Title $title * @param int $revId * @param ParserOutput $rev * @return void */ public static function setRevIncludes(Title $title, $revId, ParserOutput $pOut) { global $wgMemc; $key = self::getCacheKey($title, $revId); # Get the template/file versions used... $versions = array($pOut->getTemplateIds(), $pOut->getFileSearchOptions()); # Save to cache (check cache expiry for dynamic elements)... $data = FlaggedRevs::makeMemcObj($versions); $wgMemc->set($key, $data, $pOut->getCacheExpiry()); }
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')); }
function __construct($form, $conds = array(), $type = 0, $namespace = 0, $hideRedirs = 1) { $this->mForm = $form; $this->mConds = $conds; $this->type = $type; # Must be a content page... if (!is_null($namespace)) { $namespace = intval($namespace); } $vnamespaces = FlaggedRevs::getReviewNamespaces(); if (is_null($namespace) || !in_array($namespace, $vnamespaces)) { $namespace = !$vnamespaces ? -1 : $vnamespaces[0]; } $this->namespace = $namespace; $this->hideRedirs = $hideRedirs; parent::__construct(); }
public function getAllowedParams() { $namespaces = FlaggedRevs::getReviewNamespaces(); // Replace '' with more readable 'none' in autoreview restiction levels $autoreviewLevels = FlaggedRevs::getRestrictionLevels(); $autoreviewLevels[] = 'none'; return array('start' => array(ApiBase::PARAM_TYPE => 'integer'), 'end' => array(ApiBase::PARAM_TYPE => 'integer'), 'dir' => array(ApiBase::PARAM_DFLT => 'newer', ApiBase::PARAM_TYPE => array('newer', 'older')), 'namespace' => array(ApiBase::PARAM_DFLT => null, ApiBase::PARAM_TYPE => 'namespace', ApiBase::PARAM_ISMULTI => true), 'default' => array(ApiBase::PARAM_DFLT => null, ApiBase::PARAM_TYPE => array('latest', 'stable')), 'autoreview' => array(ApiBase::PARAM_DFLT => null, ApiBase::PARAM_TYPE => $autoreviewLevels), 'limit' => array(ApiBase::PARAM_DFLT => 10, ApiBase::PARAM_TYPE => 'limit', ApiBase::PARAM_MIN => 1, ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG1, ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2)); }
/** * Get log params (associate array) from a stability config * @param array $config * @return array (associative) */ public static function stabilityLogParams(array $config) { $params = $config; if (!FlaggedRevs::useOnlyIfProtected()) { $params['precedence'] = 1; // b/c hack for presenting log params... } return $params; }
public function getAllowedParams() { $namespaces = FlaggedRevs::getReviewNamespaces(); return array('start' => array(ApiBase::PARAM_TYPE => 'integer'), 'end' => array(ApiBase::PARAM_TYPE => 'integer'), 'dir' => array(ApiBase::PARAM_DFLT => 'newer', ApiBase::PARAM_TYPE => array('newer', 'older')), 'namespace' => array(ApiBase::PARAM_DFLT => !$namespaces ? NS_MAIN : $namespaces[0], ApiBase::PARAM_TYPE => 'namespace', ApiBase::PARAM_ISMULTI => true), 'filterredir' => array(ApiBase::PARAM_DFLT => 'all', ApiBase::PARAM_TYPE => array('redirects', 'nonredirects', 'all')), 'filterlevel' => array(ApiBase::PARAM_DFLT => null, ApiBase::PARAM_TYPE => 'integer', ApiBase::PARAM_MIN => 0, ApiBase::PARAM_MAX => 2), 'limit' => array(ApiBase::PARAM_DFLT => 10, ApiBase::PARAM_TYPE => 'limit', ApiBase::PARAM_MIN => 1, ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG1, ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2)); }
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; }
public function getAllowedParams() { // Replace '' with more readable 'none' in autoreview restiction levels $autoreviewLevels = FlaggedRevs::getRestrictionLevels(); $autoreviewLevels[] = 'none'; return array('protectlevel' => array(ApiBase::PARAM_TYPE => $autoreviewLevels, ApiBase::PARAM_DFLT => 'none'), 'expiry' => 'infinite', 'reason' => '', 'watch' => null, 'token' => null, 'title' => null); }
/** * 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; }