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())); } }
/** * Modify an array of tab links to include flagged revs UI elements * @param string $type ('flat' for SkinTemplateTabs, 'nav' for SkinTemplateNavigation) */ public function setViewTabs(Skin $skin, array &$views, $type) { $this->load(); if (!FlaggedRevs::inReviewNamespace($this->article->getTitle())) { return true; // short-circuit for non-reviewable pages } # Hack for bug 16734 (some actions update and view all at once) if ($this->pageWriteOpRequested() && wfGetDB(DB_MASTER)->doneWrites()) { # Tabs need to reflect the new stable version so users actually # see the results of their action (i.e. "delete"/"rollback") $this->article->loadPageData('fromdbmaster'); } $srev = $this->article->getStableRev(); if (!$srev) { return true; // No stable revision exists } $synced = $this->article->stableVersionIsSynced(); $pendingEdits = !$synced && $this->article->isStableShownByDefault(); // Set the edit tab names as needed... if ($pendingEdits) { if (isset($views['edit'])) { $views['edit']['text'] = wfMsg('revreview-edit'); if ($this->showingStable()) { // bug 31489; direct user to current $views['edit']['href'] = $skin->getTitle()->getFullURL('action=edit'); } } if (isset($views['viewsource'])) { $views['viewsource']['text'] = wfMsg('revreview-source'); if ($this->showingStable()) { // bug 31489; direct user to current $views['viewsource']['href'] = $skin->getTitle()->getFullURL('action=edit'); } } } # Add "pending changes" tab if the page is not synced if (!$synced) { $this->addDraftTab($views, $srev, $type); } return true; }
/** * Set the page field data loaded from some source * @param $data Database row object or "fromdb" * @return void */ public function loadPageData($data = 'fromdb') { $this->mDataLoaded = true; // sanity # Fetch data from DB as needed... if ($data === 'fromdb' || $data === 'fromdbmaster') { $db = $data == 'fromdbmaster' ? wfGetDB(DB_MASTER) : wfGetDB(DB_SLAVE); $data = $this->pageDataFromTitle($db, $this->mTitle); } # Load in primary page data... parent::loadPageData($data); # Load in FlaggedRevs page data... $this->stable = 0; // 0 => "found nothing" $this->stableRev = null; // defer this one... $this->revsArePending = false; // false => "found nothing" or "none pending" $this->pendingRevCount = null; // defer this one... $this->pageConfig = FRPageConfig::getDefaultVisibilitySettings(); // default $this->syncedInTracking = true; // false => "unreviewed" or "synced" # Load in flaggedrevs Row data if the page exists...(sanity check NS) if ($data && FlaggedRevs::inReviewNamespace($this->mTitle)) { if ($data->fpc_override !== null) { // page config row found $this->pageConfig = FRPageConfig::getVisibilitySettingsFromRow($data); } if ($data->fp_stable !== null) { // stable rev found $this->stable = (int) $data->fp_stable; $this->revsArePending = $data->fp_pending_since !== null; // revs await review $this->syncedInTracking = (bool) $data->fp_reviewed; } } }
/** * Get a FlaggedRevision of the stable version of a title. * Skips tracking tables to figure out new stable version. * @param Title $title, page title * @param int $flags (FR_MASTER, FR_FOR_UPDATE) * @param array $config, optional page config (use to skip queries) * @param string $precedence (latest,quality,pristine) * @return FlaggedRevision|null (null on failure) */ public static function determineStable(Title $title, $flags = 0, $config = array(), $precedence = 'latest') { if (!FlaggedRevs::inReviewNamespace($title)) { return null; // short-circuit } $options = array(); # User master/slave as appropriate... if ($flags & FR_FOR_UPDATE || $flags & FR_MASTER) { $db = wfGetDB(DB_MASTER); if ($flags & FR_FOR_UPDATE) { $options[] = 'FOR UPDATE'; } $pageId = $title->getArticleID(Title::GAID_FOR_UPDATE); } else { $db = wfGetDB(DB_SLAVE); $pageId = $title->getArticleID(); } if (!$pageId) { return null; // short-circuit query } # Get visiblity settings to see if page is reviewable... if (FlaggedRevs::useOnlyIfProtected()) { if (empty($config)) { $config = FRPageConfig::getStabilitySettings($title, $flags); } if (!$config['override']) { return null; // page is not reviewable; no stable version } } $baseConds = array('fr_page_id' => $pageId, 'rev_id = fr_rev_id', 'rev_page = fr_page_id', $db->bitAnd('rev_deleted', Revision::DELETED_TEXT) . ' = 0'); $options['ORDER BY'] = 'fr_rev_timestamp DESC'; $row = null; if ($precedence !== 'latest') { # Look for the latest pristine revision... if (FlaggedRevs::pristineVersions()) { $prow = $db->selectRow(array('flaggedrevs', 'revision'), self::selectFields(), array_merge($baseConds, array('fr_quality' => FR_PRISTINE)), __METHOD__, $options); # Looks like a plausible revision $row = $prow ? $prow : $row; } if ($row && $precedence === 'pristine') { // we have what we want already # Look for the latest quality revision... } elseif (FlaggedRevs::qualityVersions()) { // If we found a pristine rev above, this one must be newer... $newerClause = $row ? array('fr_rev_timestamp > ' . $db->addQuotes($row->fr_rev_timestamp)) : array(); $qrow = $db->selectRow(array('flaggedrevs', 'revision'), self::selectFields(), array_merge($baseConds, array('fr_quality' => FR_QUALITY), $newerClause), __METHOD__, $options); $row = $qrow ? $qrow : $row; } } # Do we have one? If not, try the latest reviewed revision... if (!$row) { $row = $db->selectRow(array('flaggedrevs', 'revision'), self::selectFields(), $baseConds, __METHOD__, $options); if (!$row) { return null; } } $frev = new self($row); $frev->mTitle = $title; return $frev; }
/** * Check page move and patrol permissions for FlaggedRevs */ public static function onGetUserPermissionsErrors(Title $title, $user, $action, &$result) { if ($result === false) { return true; // nothing to do } # Don't let users vandalize pages by moving them... if ($action === 'move') { if (!FlaggedRevs::inReviewNamespace($title) || !$title->exists()) { return true; // extra short-circuit } $flaggedArticle = FlaggableWikiPage::getTitleInstance($title); # If the draft shows by default anyway, nothing to do... if (!$flaggedArticle->isStableShownByDefault()) { return true; } $frev = $flaggedArticle->getStableRev(); if ($frev && !$user->isAllowed('review') && !$user->isAllowed('movestable')) { # Allow for only editors/reviewers to move this page $result = false; return false; } # Enforce autoreview/review restrictions } elseif ($action === 'autoreview' || $action === 'review') { # Get autoreview restriction settings... $fa = FlaggableWikiPage::getTitleInstance($title); $config = $fa->getStabilitySettings(); # Convert Sysop -> protect $right = $config['autoreview']; if ($right === 'sysop') { // Backwards compatibility, rewrite sysop -> editprotected $right = 'editprotected'; } if ($right === 'autoconfirmed') { // Backwards compatibility, rewrite autoconfirmed -> editsemiprotected $right = 'editsemiprotected'; } # Check if the user has the required right, if any if ($right != '' && !$user->isAllowed($right)) { $result = false; return false; } # Respect page protection to handle cases of "review wars". # If a page is restricted from editing such that a user cannot # edit it, then said user should not be able to review it. foreach ($title->getRestrictions('edit') as $right) { if ($right === 'sysop') { // Backwards compatibility, rewrite sysop -> editprotected $right = 'editprotected'; } if ($right === 'autoconfirmed') { // Backwards compatibility, rewrite autoconfirmed -> editsemiprotected $right = 'editsemiprotected'; } if ($right != '' && !$user->isAllowed($right)) { $result = false; return false; } } } return true; }
protected function doCheckTarget($flags = 0) { $flgs = $flags & self::FOR_SUBMISSION ? Title::GAID_FOR_UPDATE : 0; if (!$this->page->getArticleId($flgs)) { return 'stabilize_page_notexists'; } elseif (!FlaggedRevs::inReviewNamespace($this->page)) { return 'stabilize_page_unreviewable'; } return true; }
public static function onProtectionSave(Page $article, &$errorMsg) { global $wgUser, $wgRequest; if (!$article->exists()) { return true; // simple custom levels set for action=protect } elseif (!FlaggedRevs::inReviewNamespace($article->getTitle())) { return true; // not a reviewable page } elseif (wfReadOnly() || !$wgUser->isAllowed('stablesettings')) { return true; // user cannot change anything } $form = new PageStabilityProtectForm($wgUser); $form->setPage($article->getTitle()); // target page $permission = $wgRequest->getVal('mwStabilityLevel'); if ($permission == "none") { $permission = ''; // 'none' => '' } $form->setAutoreview($permission); // protection level (autoreview restriction) $form->setWatchThis(null); // protection form already has a watch check $form->setReasonExtra($wgRequest->getText('mwProtect-reason')); // manual $form->setReasonSelection($wgRequest->getVal('wpProtectReasonSelection')); // dropdown $form->setExpiryCustom($wgRequest->getVal('mwStabilizeExpiryOther')); // manual $form->setExpirySelection($wgRequest->getVal('mwStabilizeExpirySelection')); // dropdown $form->ready(); // params all set if ($wgRequest->wasPosted() && $form->isAllowed()) { $status = $form->submit(); if ($status !== true) { $errorMsg = wfMsg($status); // some error message } } return true; }
/** * Check page move and patrol permissions for FlaggedRevs */ public static function onUserCan(Title $title, $user, $action, &$result) { if ($result === false) { return true; // nothing to do } # Don't let users vandalize pages by moving them... if ($action === 'move') { if (!FlaggedRevs::inReviewNamespace($title) || !$title->exists()) { return true; // extra short-circuit } $flaggedArticle = FlaggableWikiPage::getTitleInstance($title); # If the draft shows by default anyway, nothing to do... if (!$flaggedArticle->isStableShownByDefault()) { return true; } $frev = $flaggedArticle->getStableRev(); if ($frev && !$user->isAllowed('review') && !$user->isAllowed('movestable')) { # Allow for only editors/reviewers to move this page $result = false; return false; } # Don't let users patrol reviewable pages (where reviewed <=> patrolled) } elseif ($action === 'patrol' || $action === 'autopatrol') { $flaggedArticle = FlaggableWikiPage::getTitleInstance($title); # For a page to be patrollable it must not be reviewable. if ($flaggedArticle->isReviewable()) { $result = false; return false; // patrol by "accepting" } # Enforce autoreview/review restrictions } elseif ($action === 'autoreview' || $action === 'review') { # Get autoreview restriction settings... $fa = FlaggableWikiPage::getTitleInstance($title); $config = $fa->getStabilitySettings(); # Convert Sysop -> protect $right = $config['autoreview'] === 'sysop' ? 'protect' : $config['autoreview']; # Check if the user has the required right, if any if ($right != '' && !$user->isAllowed($right)) { $result = false; return false; } } return true; }