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; }
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"); }
/** * 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 }
/** * @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; }
/** * Updates the flagging tracking tables for this page * @param FlaggedRevision $srev The new stable version * @param int|null $latest The latest rev ID (optional) * @return bool Updates were done */ public function updateStableVersion(FlaggedRevision $srev, $latest = null) { $rev = $srev->getRevision(); if (!$this->exists() || !$rev) { return false; // no bogus entries } # Get the latest revision ID if not set if (!$latest) { $latest = $this->mTitle->getLatestRevID(Title::GAID_FOR_UPDATE); } $dbw = wfGetDB(DB_MASTER); # Get the highest quality revision (not necessarily this one)... if ($srev->getQuality() === FlaggedRevs::highestReviewTier()) { $maxQuality = $srev->getQuality(); // save a query } else { $maxQuality = $dbw->selectField(array('flaggedrevs', 'revision'), 'fr_quality', array('fr_page_id' => $this->getId(), 'rev_id = fr_rev_id', 'rev_page = fr_page_id', 'rev_deleted & ' . Revision::DELETED_TEXT => 0), __METHOD__, array('ORDER BY' => 'fr_quality DESC', 'LIMIT' => 1)); $maxQuality = max($maxQuality, $srev->getQuality()); // sanity } # Get the timestamp of the first edit after the stable version (if any)... $nextTimestamp = null; if ($rev->getId() != $latest) { $timestamp = $dbw->timestamp($rev->getTimestamp()); $nextEditTS = $dbw->selectField('revision', 'rev_timestamp', array('rev_page' => $this->getId(), "rev_timestamp > " . $dbw->addQuotes($timestamp)), __METHOD__, array('ORDER BY' => 'rev_timestamp ASC', 'LIMIT' => 1)); if ($nextEditTS) { // sanity check $nextTimestamp = $nextEditTS; } } # Get the new page sync status... $synced = !($nextTimestamp !== null || $srev->findPendingTemplateChanges() || $srev->findPendingFileChanges('noForeign')); # Alter table metadata $dbw->replace('flaggedpages', array('fp_page_id'), array('fp_page_id' => $this->getId(), 'fp_stable' => $rev->getId(), 'fp_reviewed' => $synced ? 1 : 0, 'fp_quality' => $maxQuality === false ? null : $maxQuality, 'fp_pending_since' => $dbw->timestampOrNull($nextTimestamp)), __METHOD__); # Update pending edit tracking table self::updatePendingList($this->getId(), $latest); return true; }
/** * Get the stable version of a file * @param Title $title * @return array (MW timestamp/'0', sha1/'') */ public function getStableFileVersion(Title $title) { $dbKey = $title->getDBkey(); $time = '0'; // missing $sha1 = false; # All NS_FILE, no need to check namespace if (isset($this->stableVersions['files'][$dbKey])) { $time = $this->stableVersions['files'][$dbKey]['time']; $sha1 = $this->stableVersions['files'][$dbKey]['sha1']; return array($time, $sha1); } $srev = FlaggedRevision::newFromStable($title); if ($srev && $srev->getFileTimestamp()) { $time = $srev->getFileTimestamp(); $sha1 = $srev->getFileSha1(); } $this->stableVersions['files'][$dbKey] = array(); $this->stableVersions['files'][$dbKey]['time'] = $time; $this->stableVersions['files'][$dbKey]['sha1'] = $sha1; return array($time, $sha1); }
/** * 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; }
/** * 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; }
/** * Hook-Handler for Hook 'BSStateBarBeforeBodyViewAdd' * @param StateBar $oStateBar * @param array $aBodyViews * @return boolean Always true to keep hook running */ public function onStateBarBeforeBodyViewAdd($oStateBar, &$aBodyViews, $oUser, $oTitle) { $text = ''; $oRev = BsReviewProcess::newFromPid($oTitle->getArticleID()); $pages = BsReviewProcess::listReviews($oUser->getId()); if ($oRev === false) { return true; } $oReviewView = new ViewStateBarBodyElementReview(); $oReviewView->setReview($oRev); $oReviewView->addButton('bs-review-dismiss', 'bs-icon-decline', wfMessage('bs-review-i-dismiss')->plain(), wfMessage('bs-review-i-dismiss')->plain()); $oReviewView->addButton('bs-review-ok', 'bs-icon-accept', wfMessage('bs-review-i-agree')->plain(), wfMessage('bs-review-i-agree')->plain()); if ($res = $oRev->isFinished()) { //$text = wfMessage( 'bs-review-review-finished' )->plain(); $oReviewView->setStatusText(wfMessage('bs-review-review-finished')->plain()); if ($oRev->isSequential()) { switch ($res) { case 'date': $text .= wfMessage('bs-review-date')->plain(); break; case 'status': $text .= wfMessage('bs-review-agreed')->plain(); break; case 'denied': $text .= wfMessage('bs-review-denied-disagreed')->plain(); break; } } else { $res = $oRev->currentStatus(); $res = explode(';', $res); if ($res[2]) { $text .= "<br />" . wfMessage('bs-review-accepted', $res[2])->plain(); } if ($res[1]) { $text .= "<br />" . wfMessage('bs-review-rejected', $res[1])->plain(); } if ($res[0]) { $text .= "<br />" . wfMessage('bs-review-abstain', $res[0])->plain(); } } $oReviewView->setStatusReasonText($text); } else { $text = wfMessage('bs-review-reviewed-till', $oRev->getStartdate(), $oRev->getEnddate())->plain(); $user = User::newFromId($oRev->owner); $sName = BsCore::getUserDisplayName($user); $text .= '<br />' . wfMessage('bs-review-reviewed-till-extra', $user->getName(), $sName)->text(); $oReviewView->setStatusText($text); } // Flagged Revision: Only show the "not accepted" icon on the template page an not on the released page, which is accepted. $obj = false; $bResult = false; wfRunHooks('checkPageIsReviewable', array($oTitle, &$bResult)); if ($bResult) { $obj = FlaggedRevision::newFromStable($oTitle); } $aComments = array(); foreach ($oRev->steps as $_step) { if (!empty($_step->comment) && $_step->status != -1) { $aComments[] = $_step->comment; } } $oReviewView->setPreceedingCommentsList($aComments); if (empty($pages) || !in_array($oTitle->getArticleID(), $pages)) { $aBodyViews['statebarbodyreview'] = $oReviewView; return true; } $step = $oRev->currentStep($oUser->getId()); if (!is_object($step)) { return true; } $oReviewView->setVotable(true); $sUserName = BsCore::getUserDisplayName($oUser); $oReviewView->setComment("<em>{$sUserName}:</em> {$step->comment}"); wfRunHooks('BsReview::checkStatus::afterMessage', array($step, $oReviewView)); if ($oTitle->userCan("workflowview", $oUser)) { $aBodyViews['statebarbodyreview'] = $oReviewView; } return true; }
/** * Generates a brief review form for a page * @return array (html string, error string or true) */ public function getHtml() { global $wgLang; $revId = $this->rev->getId(); if ($this->rev->isDeleted(Revision::DELETED_TEXT)) { return array('', 'review_bad_oldid'); # The revision must be valid and public } $article = $this->article; // convenience $srev = $article->getStableRev(); # See if the version being displayed is flagged... if ($revId == $article->getStable()) { $frev = $srev; // avoid query } else { $frev = FlaggedRevision::newFromTitle($article->getTitle(), $revId); } $oldFlags = $frev ? $frev->getTags() : FlaggedRevs::quickTags(FR_CHECKED); // basic tags $reviewTime = $frev ? $frev->getTimestamp() : ''; // last review of rev $priorRevId = $this->refRev ? $this->refRev->getId() : 0; # If we are reviewing updates to a page, start off with the stable revision's # flags. Otherwise, we just fill them in with the selected revision's flags. # @TODO: do we want to carry over info for other diffs? if ($srev && $srev->getRevId() == $priorRevId) { // diff-to-stable $flags = $srev->getTags(); # Check if user is allowed to renew the stable version. # If not, then get the flags for the new revision itself. if (!FlaggedRevs::userCanSetFlags($this->user, $oldFlags)) { $flags = $oldFlags; } # Re-review button is need for template/file only review case $reviewIncludes = $srev->getRevId() == $revId && !$article->stableVersionIsSynced(); } else { // views $flags = $oldFlags; $reviewIncludes = false; // re-review button not needed } # Disable form for unprivileged users $disabled = array(); if (!$article->getTitle()->quickUserCan('review') || !FlaggedRevs::userCanSetFlags($this->user, $flags)) { $disabled = array('disabled' => 'disabled'); } # Begin form... $reviewTitle = SpecialPage::getTitleFor('RevisionReview'); $action = $reviewTitle->getLocalUrl('action=submit'); $params = array('method' => 'post', 'action' => $action, 'id' => 'mw-fr-reviewform'); $form = Xml::openElement('form', $params) . "\n"; $form .= Xml::openElement('fieldset', array('class' => 'flaggedrevs_reviewform noprint')) . "\n"; # Add appropriate legend text $legendMsg = $frev ? 'revreview-reflag' : 'revreview-flag'; $form .= Xml::openElement('legend', array('id' => 'mw-fr-reviewformlegend')); $form .= "<strong>" . wfMessage($legendMsg)->escaped() . "</strong>"; $form .= Xml::closeElement('legend') . "\n"; # Show explanatory text $form .= $this->topNotice; # Check if anyone is reviewing this already and # show a conflict warning message as needed... if ($priorRevId) { list($u, $ts) = FRUserActivity::getUserReviewingDiff($priorRevId, $this->rev->getId()); } else { list($u, $ts) = FRUserActivity::getUserReviewingPage($this->rev->getPage()); } $form .= Xml::openElement('p'); // Page under review (and not by this user)... if ($u !== null && $u != $this->user->getName()) { $form .= '<span class="fr-under-review">'; $msg = $priorRevId ? 'revreview-poss-conflict-c' : 'revreview-poss-conflict-p'; $form .= wfMessage($msg, $u, $wgLang->date($ts, true), $wgLang->time($ts, true))->parse(); $form .= "</span>"; // Page not under review or under review by this user... } elseif (!$frev) { // rev not already reviewed $form .= '<span id="mw-fr-reviewing-status" style="display:none;"></span>'; // JS widget } $form .= Xml::closeElement('p') . "\n"; # Start rating controls $css = $disabled ? 'fr-rating-controls-disabled' : 'fr-rating-controls'; $form .= Xml::openElement('p', array('class' => $css, 'id' => 'fr-rating-controls')) . "\n"; # Add main checkboxes/selects $form .= Xml::openElement('span', array('id' => 'mw-fr-ratingselects', 'class' => 'fr-rating-options')) . "\n"; $form .= self::ratingInputs($this->user, $flags, (bool) $disabled, (bool) $frev) . "\n"; $form .= Xml::closeElement('span') . "\n"; # Don't put buttons & comment field on the same line as tag inputs. if (!$disabled && !FlaggedRevs::binaryFlagging()) { // $disabled => no comment/buttons $form .= "<br />"; } # Start comment & buttons $form .= Xml::openElement('span', array('id' => 'mw-fr-confirmreview')) . "\n"; # Hide comment input if needed if (!$disabled) { $form .= Xml::inputLabel(wfMessage('revreview-log')->text(), 'wpReason', 'mw-fr-commentbox', 40, '', array('maxlength' => 255, 'class' => 'fr-comment-box')); } # Add the submit buttons... $rejectId = $this->rejectRefRevId(); // determine if there will be reject button $form .= self::submitButtons($rejectId, $frev, (bool) $disabled, $reviewIncludes); # Show stability log if there is anything interesting... if ($article->isPageLocked()) { $form .= ' ' . FlaggedRevsXML::logToggle('revreview-log-toggle-show'); } # End comment & buttons $form .= Xml::closeElement('span') . "\n"; # ..add the actual stability log body here if ($article->isPageLocked()) { $form .= FlaggedRevsXML::stabilityLogExcerpt($article); } # End rating controls $form .= Xml::closeElement('p') . "\n"; # Show explanatory text $form .= $this->bottomNotice; # Get the file version used for File: pages as needed $fileKey = $this->getFileVersion(); # Get template/file version info as needed list($templateIDs, $imageSHA1Keys) = $this->getIncludeVersions(); # Convert these into flat string params list($templateParams, $imageParams, $fileVersion) = RevisionReviewForm::getIncludeParams($templateIDs, $imageSHA1Keys, $fileKey); # Hidden params $form .= Html::hidden('title', $reviewTitle->getPrefixedText()) . "\n"; $form .= Html::hidden('target', $article->getTitle()->getPrefixedDBKey()) . "\n"; $form .= Html::hidden('refid', $priorRevId, array('id' => 'mw-fr-input-refid')) . "\n"; $form .= Html::hidden('oldid', $revId, array('id' => 'mw-fr-input-oldid')) . "\n"; $form .= Html::hidden('wpEditToken', $this->user->getEditToken()) . "\n"; $form .= Html::hidden('changetime', $reviewTime, array('id' => 'mw-fr-input-changetime')) . "\n"; // id for JS $form .= Html::hidden('userreviewing', (int) ($u === $this->user->getName()), array('id' => 'mw-fr-user-reviewing')) . "\n"; // id for JS # Add review parameters $form .= Html::hidden('templateParams', $templateParams) . "\n"; $form .= Html::hidden('imageParams', $imageParams) . "\n"; $form .= Html::hidden('fileVersion', $fileVersion) . "\n"; # Special token to discourage fiddling... $key = $this->request->getSessionData('wsFlaggedRevsKey'); $checkCode = RevisionReviewForm::validationKey($templateParams, $imageParams, $fileVersion, $revId, $key); $form .= Html::hidden('validatedParams', $checkCode) . "\n"; $form .= Xml::closeElement('fieldset') . "\n"; $form .= Xml::closeElement('form') . "\n"; return array($form, true); }
/** * Mark auto-reviewed edits as patrolled */ public static function autoMarkPatrolled(RecentChange &$rc) { if (empty($rc->mAttribs['rc_this_oldid'])) { return true; } $fa = FlaggableWikiPage::getTitleInstance($rc->getTitle()); $fa->loadPageData('fromdbmaster'); // Is the page reviewable? if ($fa->isReviewable()) { $revId = $rc->mAttribs['rc_this_oldid']; // If the edit we just made was reviewed, then it's the stable rev $frev = FlaggedRevision::newFromTitle($rc->getTitle(), $revId, FR_MASTER); // Reviewed => patrolled if ($frev) { RevisionReviewForm::updateRecentChanges($rc, 'patrol', $frev); $rc->mAttribs['rc_patrolled'] = 1; // make sure irc/email notifs know status } return true; } return true; }
/** * Submit the form parameters for the page config to the DB. * * @return mixed (true on success, error string on failure) */ public function doSubmit() { # Double-check permissions if (!$this->isAllowed()) { return 'stablize_denied'; } # Parse and cleanup the expiry time given... $expiry = $this->getExpiry(); if ($expiry === false) { return 'stabilize_expiry_invalid'; } elseif ($expiry !== Block::infinity() && $expiry < wfTimestampNow()) { return 'stabilize_expiry_old'; } # Update the DB row with the new config... $changed = FRPageConfig::setStabilitySettings($this->page, $this->getNewConfig()); # Log if this actually changed anything... if ($changed) { $article = new FlaggableWikiPage($this->page); if (FlaggedRevs::useOnlyIfProtected()) { # Config may have changed to allow stable versions, so refresh # the tracking table to account for any hidden reviewed versions... $frev = FlaggedRevision::determineStable($this->page, FR_MASTER); if ($frev) { $article->updateStableVersion($frev); } else { $article->clearStableVersion(); } } # Update logs and make a null edit $nullRev = $this->updateLogsAndHistory($article); # Null edit may have been auto-reviewed already $frev = FlaggedRevision::newFromTitle($this->page, $nullRev->getId(), FR_MASTER); $updatesDone = (bool) $frev; // stableVersionUpdates() already called? # Check if this null edit is to be reviewed... if ($this->reviewThis && !$frev) { $flags = null; # Review this revision of the page... $ok = FlaggedRevs::autoReviewEdit($article, $this->user, $nullRev, $flags, true); if ($ok) { FlaggedRevs::markRevisionPatrolled($nullRev); // reviewed -> patrolled $updatesDone = true; // stableVersionUpdates() already called } } # Update page and tracking tables and clear cache. if (!$updatesDone) { FlaggedRevs::stableVersionUpdates($this->page); } } # Apply watchlist checkbox value (may be NULL) $this->updateWatchlist(); # Take this opportunity to purge out expired configurations FRPageConfig::purgeExpiredConfigurations(); return true; }
protected function update_flaggedpages($start = null) { $this->output("Populating and correcting flaggedpages/flaggedpage_config columns\n"); $BATCH_SIZE = 300; $db = wfGetDB(DB_MASTER); if ($start === null) { $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("...flaggedpages table seems to be empty.\n"); return; } # Do remaining chunk $end += $BATCH_SIZE - 1; $blockStart = $start; $blockEnd = $start + $BATCH_SIZE - 1; $count = $deleted = $fixed = 0; while ($blockEnd <= $end) { $this->output("...doing page_id from {$blockStart} to {$blockEnd}\n"); $cond = "page_id BETWEEN {$blockStart} AND {$blockEnd}"; $res = $db->select('page', array('page_id', 'page_namespace', 'page_title', 'page_latest'), $cond, __METHOD__); # Go through and update the de-normalized references... $db->begin(); foreach ($res as $row) { $title = Title::newFromRow($row); $article = new FlaggableWikiPage($title); $oldFrev = FlaggedRevision::newFromStable($title, FR_MASTER); $frev = FlaggedRevision::determineStable($title, FR_MASTER); # Update fp_stable, fp_quality, and fp_reviewed if ($frev) { $article->updateStableVersion($frev, $row->page_latest); $changed = !$oldFrev || $oldFrev->getRevId() != $frev->getRevId(); # Somethings broke? Delete the row... } else { $article->clearStableVersion(); if ($db->affectedRows() > 0) { $deleted++; } $changed = (bool) $oldFrev; } # Get the latest revision $revRow = $db->selectRow('revision', '*', array('rev_page' => $row->page_id), __METHOD__, array('ORDER BY' => 'rev_timestamp DESC')); # Correct page_latest if needed (import/files made plenty of bad rows) if ($revRow) { $revision = new Revision($revRow); if ($article->updateIfNewerOn($db, $revision)) { $fixed++; } } if ($changed) { # Lazily rebuild dependancies on next parse (we invalidate below) FlaggedRevs::clearStableOnlyDeps($title); $title->invalidateCache(); } $count++; } $db->freeResult($res); # Remove manual config settings that simply restate the site defaults $db->delete('flaggedpage_config', array("fpc_page_id BETWEEN {$blockStart} AND {$blockEnd}", 'fpc_override' => intval(FlaggedRevs::isStableShownByDefault()), 'fpc_level' => ''), __METHOD__); $deleted = $deleted + $db->affectedRows(); $db->commit(); $blockStart += $BATCH_SIZE; $blockEnd += $BATCH_SIZE; wfWaitForSlaves(5); } $this->output("flaggedpage columns update complete ..." . " {$count} rows [{$fixed} fixed] [{$deleted} deleted]\n"); }
public static function checkDiffUrl($titleObj, &$mOldid, &$mNewid, $old, $new) { if ($new === 'review' && isset($titleObj)) { $sRevId = FlaggedRevision::getStableRevId($titleObj); if ($sRevId) { $mOldid = $sRevId; // stable $mNewid = 0; // cur } } return true; }
/** * When an edit is made to a page: * (a) If the page is reviewable, silently mark the edit patrolled if it was auto-reviewed * (b) If the page can be patrolled, auto-patrol the edit patrolled as normal * (c) If the page is new and $wgUseNPPatrol is on, auto-patrol the edit patrolled as normal * (d) If the edit is neither reviewable nor patrolleable, silently mark it patrolled */ public static function autoMarkPatrolled(RecentChange &$rc) { if (empty($rc->mAttribs['rc_this_oldid'])) { return true; } $fa = FlaggableWikiPage::getTitleInstance($rc->getTitle()); $fa->loadPageData('fromdbmaster'); // Is the page reviewable? if ($fa->isReviewable()) { $revId = $rc->mAttribs['rc_this_oldid']; $quality = FlaggedRevision::getRevQuality($revId, FR_MASTER); // Reviewed => patrolled if ($quality !== false && $quality >= FR_CHECKED) { RevisionReviewForm::updateRecentChanges($rc, 'patrol', $fa->getStableRev()); $rc->mAttribs['rc_patrolled'] = 1; // make sure irc/email notifs know status } return true; } return true; }