public function execute() { global $wgUser; $dbr = wfGetDB(DB_SLAVE); $ret = $dbr->select(array('flaggedpages', 'revision', 'page'), array_merge(Revision::selectFields(), array($dbr->tableName('page') . '.*')), array('fp_pending_since IS NOT NULL', 'page_id = fp_page_id', 'rev_page = fp_page_id', 'rev_timestamp >= fp_pending_since'), __METHOD__, array('ORDER BY' => 'fp_pending_since DESC')); foreach ($ret as $row) { $title = Title::newFromRow($row); $article = new Article($title); $rev = new Revision($row); // Trigger cache regeneration $start = microtime(true); FRInclusionCache::getRevIncludes($article, $rev, $wgUser, 'regen'); $elapsed = intval((microtime(true) - $start) * 1000); $this->cachePendingRevsLog($title->getPrefixedDBkey() . " rev:" . $rev->getId() . " {$elapsed}ms"); } }
/** * This function does essentially the same as RevisionReview::AjaxReview, * except that it generates the template and image parameters itself. */ public function execute() { global $wgUser; $params = $this->extractRequestParams(); // Check basic permissions if (!$wgUser->isAllowed('review')) { $this->dieUsage("You don't have the right to review revisions.", 'permissiondenied'); } elseif ($wgUser->isBlocked(false)) { $this->dieUsageMsg(array('blockedtext')); } // Get target rev and title $revid = (int) $params['revid']; $rev = Revision::newFromId($revid); if (!$rev) { $this->dieUsage("Cannot find a revision with the specified ID.", 'notarget'); } $title = $rev->getTitle(); // Construct submit form... $form = new RevisionReviewForm($wgUser); $form->setPage($title); $form->setOldId($revid); $form->setApprove(empty($params['unapprove'])); $form->setUnapprove(!empty($params['unapprove'])); if (isset($params['comment'])) { $form->setComment($params['comment']); } // The flagging parameters have the form 'flag_$name'. // Extract them and put the values into $form->dims foreach (FlaggedRevs::getTags() as $tag) { $form->setDim($tag, (int) $params['flag_' . $tag]); } if ($form->getAction() === 'approve') { $article = new FlaggableWikiPage($title); // Get the file version used for File: pages $file = $article->getFile(); if ($file) { $fileVer = array('time' => $file->getTimestamp(), 'sha1' => $file->getSha1()); } else { $fileVer = null; } // Now get the template and image parameters needed list($templateIds, $fileTimeKeys) = FRInclusionCache::getRevIncludes($article, $rev, $wgUser); // Get version parameters for review submission (flat strings) list($templateParams, $imageParams, $fileParam) = RevisionReviewForm::getIncludeParams($templateIds, $fileTimeKeys, $fileVer); // Set the version parameters... $form->setTemplateParams($templateParams); $form->setFileParams($imageParams); $form->setFileVersion($fileParam); $form->bypassValidationKey(); // always OK; uses current templates/files } $status = $form->ready(); // all params set # Try to do the actual review $status = $form->submit(); # Approve/de-approve success if ($status === true) { $this->getResult()->addValue(null, $this->getModuleName(), array('result' => 'Success')); # Approve-specific failures } elseif ($form->getAction() === 'approve') { if ($status === 'review_denied') { $this->dieUsage("You don't have the necessary rights to set the specified flags.", 'permissiondenied'); } elseif ($status === 'review_too_low') { $this->dieUsage("Either all or none of the flags have to be set to zero.", 'mixedapproval'); } elseif ($status === 'review_bad_key') { $this->dieUsage("You don't have the necessary rights to set the specified flags.", 'permissiondenied'); } elseif ($status === 'review_bad_tags') { $this->dieUsage("The specified flags are not valid.", 'invalidtags'); } elseif ($status === 'review_bad_oldid') { $this->dieUsage("No revision with the specified ID.", 'notarget'); } else { // FIXME: review_param_missing? better msg? $this->dieUsageMsg(array('unknownerror', '')); } # De-approve specific failure } elseif ($form->getAction() === 'unapprove') { if ($status === 'review_denied') { $this->dieUsage("You don't have the necessary rights to remove the flags.", 'permissiondenied'); } elseif ($status === 'review_not_flagged') { $this->dieUsage("No flagged revision with the specified ID.", 'notarget'); } else { // FIXME: review_param_missing? better msg? $this->dieUsageMsg(array('unknownerror', '')); } # Generic failures } else { if ($status === 'review_page_unreviewable') { $this->dieUsage("Provided page is not reviewable.", 'notreviewable'); } elseif ($status === 'review_page_notexists') { $this->dieUsage("Provided page does not exist.", 'notarget'); } } }
/** * When viewing a diff: * (a) Add the review form to the top of the page * (b) Mark off which versions are checked or not * (c) When comparing the stable revision to the current: * (i) Show a tag with some explanation for the diff * (ii) List any template/file changes pending review */ public function addToDiffView($diff, $oldRev, $newRev) { global $wgMemc, $wgParserCacheExpireTime; $request = $this->getRequest(); $reqUser = $this->getUser(); $this->load(); # Exempt printer-friendly output if ($this->out->isPrintable()) { return true; # Multi-page diffs are useless and misbehave (bug 19327). Sanity check $newRev. } elseif ($this->isMultiPageDiff || !$newRev) { return true; # Page must be reviewable. } elseif (!$this->article->isReviewable()) { return true; } $srev = $this->article->getStableRev(); if ($srev && $this->isReviewableDiff) { $this->reviewFormRev = $newRev; } # Check if this is a diff-to-stable. If so: # (a) prompt reviewers to review the changes # (b) list template/file changes if only includes are pending if ($srev && $this->isDiffFromStable && !$this->article->stableVersionIsSynced()) { $changeText = ''; $changeList = array(); # Page not synced only due to includes? if (!$this->article->revsArePending()) { # Add a list of links to each changed template... $changeList = self::fetchTemplateChanges($srev); # Add a list of links to each changed file... $changeList = array_merge($changeList, self::fetchFileChanges($srev)); # Correct bad cache which said they were not synced... if (!count($changeList)) { $key = wfMemcKey('flaggedrevs', 'includesSynced', $this->article->getId()); $data = FlaggedRevs::makeMemcObj("true"); $wgMemc->set($key, $data, $wgParserCacheExpireTime); } # Otherwise, check for includes pending on top of edits pending... } else { $incs = FRInclusionCache::getRevIncludes($this->article, $newRev, $reqUser); $this->oldRevIncludes = $incs; // process cache # Add a list of links to each changed template... $changeList = self::fetchTemplateChanges($srev, $incs[0]); # Add a list of links to each changed file... $changeList = array_merge($changeList, self::fetchFileChanges($srev, $incs[1])); } # If there are pending revs or templates/files changes, notify the user... if ($this->article->revsArePending() || count($changeList)) { # If the user can review then prompt them to review them... if ($reqUser->isAllowed('review')) { // Reviewer just edited... if ($request->getInt('shownotice') && $newRev->isCurrent() && $newRev->getRawUserText() == $reqUser->getName()) { $title = $this->article->getTitle(); // convenience // @TODO: make diff class cache this $n = $title->countRevisionsBetween($oldRev, $newRev); if ($n) { $msg = 'revreview-update-edited-prev'; // previous pending edits } else { $msg = 'revreview-update-edited'; // just couldn't autoreview } // All other cases... } else { $msg = 'revreview-update'; // generic "please review" notice... } $this->diffNoticeBox = wfMsgExt($msg, 'parse'); // add as part of form } # Add include change list... if (count($changeList)) { // just inclusion changes $changeText .= "<p>" . wfMsgExt('revreview-update-includes', 'parseinline') . ' ' . implode(', ', $changeList) . "</p>\n"; } } # template/file change list if ($changeText != '') { if ($reqUser->isAllowed('review')) { $this->diffIncChangeBox = "<p>{$changeText}</p>"; } else { $css = 'flaggedrevs_diffnotice plainlinks'; $this->out->addHTML("<div id='mw-fr-difftostable' class='{$css}'>{$changeText}</div>\n"); } } } # Add a link to diff from stable to current as needed. # Show review status of the diff revision(s). Uses a <table>. $this->out->addHTML('<div id="mw-fr-diff-headeritems">' . self::diffLinkAndMarkers($this->article, $oldRev, $newRev) . '</div>'); return true; }
/** * Update the page tables with a new stable version. * @param WikiPage|Title $page * @param FlaggedRevision|null $sv, the new stable version (optional) * @param FlaggedRevision|null $oldSv, the old stable version (optional) * @param Object editInfo Article edit info about the current revision (optional) * @return bool stable version text/file changed and FR_INCLUDES_STABLE */ public static function stableVersionUpdates($page, $sv = null, $oldSv = null, $editInfo = null) { if ($page instanceof FlaggableWikiPage) { $article = $page; } elseif ($page instanceof WikiPage) { $article = FlaggableWikiPage::getTitleInstance($page->getTitle()); } elseif ($page instanceof Title) { $article = FlaggableWikiPage::getTitleInstance($page); } else { throw new MWException("First argument must be a Title or WikiPage."); } $title = $article->getTitle(); $changed = false; if ($oldSv === null) { // optional $oldSv = FlaggedRevision::newFromStable($title, FR_MASTER); } if ($sv === null) { // optional $sv = FlaggedRevision::determineStable($title, FR_MASTER); } if (!$sv) { # Empty flaggedrevs data for this page if there is no stable version $article->clearStableVersion(); # Check if pages using this need to be refreshed... if (FlaggedRevs::inclusionSetting() == FR_INCLUDES_STABLE) { $changed = (bool) $oldSv; } } else { # Update flagged page related fields $article->updateStableVersion($sv, $editInfo ? $editInfo->revid : null); # Check if pages using this need to be invalidated/purged... if (FlaggedRevs::inclusionSetting() == FR_INCLUDES_STABLE) { $changed = !$oldSv || $sv->getRevId() != $oldSv->getRevId() || $sv->getFileTimestamp() != $oldSv->getFileTimestamp() || $sv->getFileSha1() != $oldSv->getFileSha1(); } # Update template/file version cache... if ($editInfo && $sv->getRevId() != $editInfo->revid) { FRInclusionCache::setRevIncludes($title, $editInfo->revid, $editInfo->output); } } # Lazily rebuild dependancies on next parse (we invalidate below) FlaggedRevs::clearStableOnlyDeps($title->getArticleID()); # Clear page cache $title->invalidateCache(); self::purgeSquid($title); return $changed; }