/** * 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'); } } }
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>'; } }
/** * 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; }
public function __construct(RevisionReviewForm $form) { $this->form = $form; $this->newRev = Revision::newFromTitle($form->getPage(), $form->getOldId()); $this->oldRev = Revision::newFromTitle($form->getPage(), $form->getRefId()); }
/** * 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; }