/** * Patrols the article or provides the reason the patrol failed. */ public function execute() { $params = $this->extractRequestParams(); $this->requireOnlyOneParameter($params, 'rcid', 'revid'); if (isset($params['rcid'])) { $rc = RecentChange::newFromId($params['rcid']); if (!$rc) { $this->dieUsageMsg(array('nosuchrcid', $params['rcid'])); } } else { $rev = Revision::newFromId($params['revid']); if (!$rev) { $this->dieUsageMsg(array('nosuchrevid', $params['revid'])); } $rc = $rev->getRecentChange(); if (!$rc) { $this->dieUsage('The revision ' . $params['revid'] . " can't be patrolled as it's too old", 'notpatrollable'); } } $retval = $rc->doMarkPatrolled($this->getUser()); if ($retval) { $this->dieUsageMsg(reset($retval)); } $result = array('rcid' => intval($rc->getAttribute('rc_id'))); ApiQueryBase::addTitleInfo($result, $rc->getTitle()); $this->getResult()->addValue(null, $this->getModuleName(), $result); }
/** * Record a log event for a change being patrolled * * @param mixed $rc Change identifier or RecentChange object * @param bool $auto Was this patrol event automatic? * @param User $user User performing the action or null to use $wgUser * * @return bool */ public static function record($rc, $auto = false, User $user = null) { global $wgLogAutopatrol; // do not log autopatrolled edits if setting disables it if ($auto && !$wgLogAutopatrol) { return false; } if (!$rc instanceof RecentChange) { $rc = RecentChange::newFromId($rc); if (!is_object($rc)) { return false; } } if (!$user) { global $wgUser; $user = $wgUser; } $entry = new ManualLogEntry('patrol', 'patrol'); $entry->setTarget($rc->getTitle()); $entry->setParameters(self::buildParams($rc, $auto)); $entry->setPerformer($user); $logid = $entry->insert(); if (!$auto) { $entry->publish($logid, 'udp'); } return true; }
public function onView() { $rc = RecentChange::newFromId($this->getRequest()->getInt('rcid')); if (is_null($rc)) { throw new ErrorPageError('markedaspatrollederror', 'markedaspatrollederrortext'); } $errors = $rc->doMarkPatrolled($this->getUser()); if (in_array(array('rcpatroldisabled'), $errors)) { throw new ErrorPageError('rcpatroldisabled', 'rcpatroldisabledtext'); } if (in_array(array('hookaborted'), $errors)) { // The hook itself has handled any output return; } # It would be nice to see where the user had actually come from, but for now just guess $returnto = $rc->getAttribute('rc_type') == RC_NEW ? 'Newpages' : 'Recentchanges'; $return = SpecialPage::getTitleFor($returnto); if (in_array(array('markedaspatrollederror-noautopatrol'), $errors)) { $this->getOutput()->setPageTitle(wfMsg('markedaspatrollederror')); $this->getOutput()->addWikiMsg('markedaspatrollederror-noautopatrol'); $this->getOutput()->returnToMain(null, $return); return; } if (!empty($errors)) { $this->getOutput()->showPermissionsErrorPage($errors); return; } # Inform the user $this->getOutput()->setPageTitle(wfMsg('markedaspatrolled')); $this->getOutput()->addWikiMsg('markedaspatrolledtext', $rc->getTitle()->getPrefixedText()); $this->getOutput()->returnToMain(null, $return); }
/** * Record a log event for a change being patrolled * * @param $rc Mixed: change identifier or RecentChange object * @param $auto Boolean: was this patrol event automatic? */ public static function record($rc, $auto = false) { if (!$rc instanceof RecentChange) { $rc = RecentChange::newFromId($rc); if (!is_object($rc)) { return false; } } $title = Title::makeTitleSafe($rc->getAttribute('rc_namespace'), $rc->getAttribute('rc_title')); if (is_object($title)) { $params = self::buildParams($rc, $auto); $log = new LogPage('patrol', false, $auto ? "skipUDP" : "UDP"); # False suppresses RC entries $log->addEntry('patrol', $title, '', $params); return true; } return false; }
public function onView() { $request = $this->getRequest(); $rcId = $request->getInt('rcid'); $rc = RecentChange::newFromId($rcId); if (is_null($rc)) { throw new ErrorPageError('markedaspatrollederror', 'markedaspatrollederrortext'); } $user = $this->getUser(); if (!$user->matchEditToken($request->getVal('token'), $rcId)) { throw new ErrorPageError('sessionfailure-title', 'sessionfailure'); } $errors = $rc->doMarkPatrolled($user); if (in_array(['rcpatroldisabled'], $errors)) { throw new ErrorPageError('rcpatroldisabled', 'rcpatroldisabledtext'); } if (in_array(['hookaborted'], $errors)) { // The hook itself has handled any output return; } # It would be nice to see where the user had actually come from, but for now just guess if ($rc->getAttribute('rc_type') == RC_NEW) { $returnTo = 'Newpages'; } elseif ($rc->getAttribute('rc_log_type') == 'upload') { $returnTo = 'Newfiles'; } else { $returnTo = 'Recentchanges'; } $return = SpecialPage::getTitleFor($returnTo); if (in_array(['markedaspatrollederror-noautopatrol'], $errors)) { $this->getOutput()->setPageTitle($this->msg('markedaspatrollederror')); $this->getOutput()->addWikiMsg('markedaspatrollederror-noautopatrol'); $this->getOutput()->returnToMain(null, $return); return; } if (count($errors)) { throw new PermissionsError('patrol', $errors); } # Inform the user $this->getOutput()->setPageTitle($this->msg('markedaspatrolled')); $this->getOutput()->addWikiMsg('markedaspatrolledtext', $rc->getTitle()->getPrefixedText()); $this->getOutput()->returnToMain(null, $return); }
protected function processIndividual($type, $params, $id) { $idResult = array($type => $id); // validate the ID $valid = false; switch ($type) { case 'rcid': $valid = RecentChange::newFromId($id); break; case 'revid': $valid = Revision::newFromId($id); break; case 'logid': $valid = self::validateLogId($id); break; } if (!$valid) { $idResult['status'] = 'error'; $idResult += $this->parseMsg(array("nosuch{$type}", $id)); return $idResult; } $status = ChangeTags::updateTagsWithChecks($params['add'], $params['remove'], $type === 'rcid' ? $id : null, $type === 'revid' ? $id : null, $type === 'logid' ? $id : null, null, $params['reason'], $this->getUser()); if (!$status->isOK()) { if ($status->hasMessage('actionthrottledtext')) { $idResult['status'] = 'skipped'; } else { $idResult['status'] = 'failure'; $idResult['errors'] = $this->getErrorFormatter()->arrayFromStatus($status, 'error'); } } else { $idResult['status'] = 'success'; if (is_null($status->value->logId)) { $idResult['noop'] = ''; } else { $idResult['actionlogid'] = $status->value->logId; $idResult['added'] = $status->value->addedTags; ApiResult::setIndexedTagName($idResult['added'], 't'); $idResult['removed'] = $status->value->removedTags; ApiResult::setIndexedTagName($idResult['removed'], 't'); } } return $idResult; }
/** * Record a log event for a change being patrolled * * @param $rc Mixed: change identifier or RecentChange object * @param $auto Boolean: was this patrol event automatic? * * @return bool */ public static function record($rc, $auto = false) { if (!$rc instanceof RecentChange) { $rc = RecentChange::newFromId($rc); if (!is_object($rc)) { return false; } } $title = Title::makeTitleSafe($rc->getAttribute('rc_namespace'), $rc->getAttribute('rc_title')); if ($title) { $entry = new ManualLogEntry('patrol', 'patrol'); $entry->setTarget($title); $entry->setParameters(self::buildParams($rc, $auto)); $entry->setPerformer(User::newFromName($rc->getAttribute('rc_user_text'), false)); $logid = $entry->insert(); if (!$auto) { $entry->publish($logid, 'udp'); } return true; } return false; }
/** * Patrols the article or provides the reason the patrol failed. */ public function execute() { $params = $this->extractRequestParams(); $this->requireOnlyOneParameter($params, 'rcid', 'revid'); if (isset($params['rcid'])) { $rc = RecentChange::newFromId($params['rcid']); if (!$rc) { $this->dieUsageMsg(['nosuchrcid', $params['rcid']]); } } else { $rev = Revision::newFromId($params['revid']); if (!$rev) { $this->dieUsageMsg(['nosuchrevid', $params['revid']]); } $rc = $rev->getRecentChange(); if (!$rc) { $this->dieUsage('The revision ' . $params['revid'] . " can't be patrolled as it's too old", 'notpatrollable'); } } $user = $this->getUser(); $tags = $params['tags']; // Check if user can add tags if (!is_null($tags)) { $ableToTag = ChangeTags::canAddTagsAccompanyingChange($tags, $user); if (!$ableToTag->isOK()) { $this->dieStatus($ableToTag); } } $retval = $rc->doMarkPatrolled($user, false, $tags); if ($retval) { $this->dieUsageMsg(reset($retval)); } $result = ['rcid' => intval($rc->getAttribute('rc_id'))]; ApiQueryBase::addTitleInfo($result, $rc->getTitle()); $this->getResult()->addValue(null, $this->getModuleName(), $result); }
/** * Get a link to mark the change as patrolled, or '' if there's either no * revision to patrol or the user is not allowed to to it. * Side effect: this method will call OutputPage::preventClickjacking() * when a link is builded. * * @return String */ protected function markPatrolledLink() { global $wgUseRCPatrol; if ($this->mMarkPatrolledLink === null) { // Prepare a change patrol link, if applicable if ($wgUseRCPatrol && $this->mNewPage->quickUserCan('patrol', $this->getUser())) { // If we've been given an explicit change identifier, use it; saves time if ($this->mRcidMarkPatrolled) { $rcid = $this->mRcidMarkPatrolled; $rc = RecentChange::newFromId($rcid); // Already patrolled? $rcid = is_object($rc) && !$rc->getAttribute('rc_patrolled') ? $rcid : 0; } else { // Look for an unpatrolled change corresponding to this diff $db = wfGetDB(DB_SLAVE); $change = RecentChange::newFromConds(array('rc_user_text' => $this->mNewRev->getRawUserText(), 'rc_timestamp' => $db->timestamp($this->mNewRev->getTimestamp()), 'rc_this_oldid' => $this->mNewid, 'rc_last_oldid' => $this->mOldid, 'rc_patrolled' => 0), __METHOD__); if ($change instanceof RecentChange) { $rcid = $change->mAttribs['rc_id']; $this->mRcidMarkPatrolled = $rcid; } else { // None found $rcid = 0; } } // Build the link if ($rcid) { $this->getOutput()->preventClickjacking(); $token = $this->getUser()->getEditToken($rcid); $this->mMarkPatrolledLink = ' <span class="patrollink">[' . Linker::linkKnown($this->mNewPage, $this->msg('markaspatrolleddiff')->escaped(), array(), array('action' => 'markpatrolled', 'rcid' => $rcid, 'token' => $token)) . ']</span>'; } else { $this->mMarkPatrolledLink = ''; } } else { $this->mMarkPatrolledLink = ''; } } return $this->mMarkPatrolledLink; }
/** * Mark this particular edit/page as patrolled */ public function markpatrolled() { global $wgOut, $wgUser, $wgRequest; $wgOut->setRobotPolicy('noindex,nofollow'); # If we haven't been given an rc_id value, we can't do anything $rcid = (int) $wgRequest->getVal('rcid'); if (!$wgUser->matchEditToken($wgRequest->getVal('token'), $rcid)) { $wgOut->showErrorPage('sessionfailure-title', 'sessionfailure'); return; } $rc = RecentChange::newFromId($rcid); if (is_null($rc)) { $wgOut->showErrorPage('markedaspatrollederror', 'markedaspatrollederrortext'); return; } # It would be nice to see where the user had actually come from, but for now just guess $returnto = $rc->getAttribute('rc_type') == RC_NEW ? 'Newpages' : 'Recentchanges'; $return = SpecialPage::getTitleFor($returnto); $errors = $rc->doMarkPatrolled(); if (in_array(array('rcpatroldisabled'), $errors)) { $wgOut->showErrorPage('rcpatroldisabled', 'rcpatroldisabledtext'); return; } if (in_array(array('hookaborted'), $errors)) { // The hook itself has handled any output return; } if (in_array(array('markedaspatrollederror-noautopatrol'), $errors)) { $wgOut->setPageTitle(wfMsg('markedaspatrollederror')); $wgOut->addWikiMsg('markedaspatrollederror-noautopatrol'); $wgOut->returnToMain(false, $return); return; } if (!empty($errors)) { $wgOut->showPermissionsErrorPage($errors); return; } # Inform the user $wgOut->setPageTitle(wfMsg('markedaspatrolled')); $wgOut->addWikiMsg('markedaspatrolledtext', $rc->getTitle()->getPrefixedText()); $wgOut->returnToMain(false, $return); }
function showDiffPage($diffOnly = false) { global $wgUser, $wgOut, $wgUseExternalEditor, $wgUseRCPatrol, $wgEnableHtmlDiff; wfProfileIn(__METHOD__); # If external diffs are enabled both globally and for the user, # we'll use the application/x-external-editor interface to call # an external diff tool like kompare, kdiff3, etc. if ($wgUseExternalEditor && $wgUser->getOption('externaldiff')) { global $wgInputEncoding, $wgServer, $wgScript, $wgLang; $wgOut->disable(); header("Content-type: application/x-external-editor; charset=" . $wgInputEncoding); $url1 = $this->mTitle->getFullURL("action=raw&oldid=" . $this->mOldid); $url2 = $this->mTitle->getFullURL("action=raw&oldid=" . $this->mNewid); $special = $wgLang->getNsText(NS_SPECIAL); $control = <<<CONTROL \t\t\t[Process] \t\t\tType=Diff text \t\t\tEngine=MediaWiki \t\t\tScript={$wgServer}{$wgScript} \t\t\tSpecial namespace={$special} \t\t\t[File] \t\t\tExtension=wiki \t\t\tURL={$url1} \t\t\t[File 2] \t\t\tExtension=wiki \t\t\tURL={$url2} CONTROL; echo $control; return; } $wgOut->setArticleFlag(false); if (!$this->loadRevisionData()) { $t = $this->mTitle->getPrefixedText(); $d = wfMsgExt('missingarticle-diff', array('escape'), $this->mOldid, $this->mNewid); $wgOut->setPagetitle(wfMsg('errorpagetitle')); $wgOut->addWikiMsg('missing-article', "<nowiki>{$t}</nowiki>", $d); wfProfileOut(__METHOD__); return; } wfRunHooks('DiffViewHeader', array($this, $this->mOldRev, $this->mNewRev)); if ($this->mNewRev->isCurrent()) { $wgOut->setArticleFlag(true); } # mOldid is false if the difference engine is called with a "vague" query for # a diff between a version V and its previous version V' AND the version V # is the first version of that article. In that case, V' does not exist. if ($this->mOldid === false) { $this->showFirstRevision(); $this->renderNewRevision(); // should we respect $diffOnly here or not? wfProfileOut(__METHOD__); return; } $wgOut->suppressQuickbar(); $oldTitle = $this->mOldPage->getPrefixedText(); $newTitle = $this->mNewPage->getPrefixedText(); if ($oldTitle == $newTitle) { $wgOut->setPageTitle($newTitle); } else { $wgOut->setPageTitle($oldTitle . ', ' . $newTitle); } $wgOut->setSubtitle(wfMsgExt('difference', array('parseinline'))); $wgOut->setRobotPolicy('noindex,nofollow'); if (!$this->mOldPage->userCanRead() || !$this->mNewPage->userCanRead()) { $wgOut->loginToUse(); $wgOut->output(); $wgOut->disable(); wfProfileOut(__METHOD__); return; } $sk = $wgUser->getSkin(); // Check if page is editable $editable = $this->mNewRev->getTitle()->userCan('edit'); if ($editable && $this->mNewRev->isCurrent() && $wgUser->isAllowed('rollback')) { $rollback = ' ' . $sk->generateRollback($this->mNewRev); } else { $rollback = ''; } // Prepare a change patrol link, if applicable if ($wgUseRCPatrol && $this->mTitle->userCan('patrol')) { // If we've been given an explicit change identifier, use it; saves time if ($this->mRcidMarkPatrolled) { $rcid = $this->mRcidMarkPatrolled; $rc = RecentChange::newFromId($rcid); // Already patrolled? $rcid = is_object($rc) && !$rc->getAttribute('rc_patrolled') ? $rcid : 0; } else { // Look for an unpatrolled change corresponding to this diff $db = wfGetDB(DB_SLAVE); $change = RecentChange::newFromConds(array('rc_user_text' => $this->mNewRev->getRawUserText(), 'rc_timestamp' => $db->timestamp($this->mNewRev->getTimestamp()), 'rc_this_oldid' => $this->mNewid, 'rc_last_oldid' => $this->mOldid, 'rc_patrolled' => 0), __METHOD__); if ($change instanceof RecentChange) { $rcid = $change->mAttribs['rc_id']; $this->mRcidMarkPatrolled = $rcid; } else { // None found $rcid = 0; } } // Build the link if ($rcid) { $patrol = ' <span class="patrollink">[' . $sk->makeKnownLinkObj($this->mTitle, wfMsgHtml('markaspatrolleddiff'), "action=markpatrolled&rcid={$rcid}") . ']</span>'; } else { $patrol = ''; } } else { $patrol = ''; } $diffOnlyArg = ''; # Carry over 'diffonly' param via navigation links if ($diffOnly != $wgUser->getBoolOption('diffonly')) { $diffOnlyArg = '&diffonly=' . $diffOnly; } $htmldiffarg = $this->htmlDiffArgument(); # Make "previous revision link" $prevlink = $sk->makeKnownLinkObj($this->mTitle, wfMsgHtml('previousdiff'), "diff=prev&oldid={$this->mOldid}{$htmldiffarg}{$diffOnlyArg}", '', '', 'id="differences-prevlink"'); # Make "next revision link" if ($this->mNewRev->isCurrent()) { $nextlink = ' '; } else { $nextlink = $sk->makeKnownLinkObj($this->mTitle, wfMsgHtml('nextdiff'), "diff=next&oldid={$this->mNewid}{$htmldiffarg}{$diffOnlyArg}", '', '', 'id="differences-nextlink"'); } $oldminor = ''; $newminor = ''; if ($this->mOldRev->isMinor()) { $oldminor = Xml::span(wfMsg('minoreditletter'), 'minor') . ' '; } if ($this->mNewRev->isMinor()) { $newminor = Xml::span(wfMsg('minoreditletter'), 'minor') . ' '; } $rdel = ''; $ldel = ''; if ($wgUser->isAllowed('deleterevision')) { if (!$this->mOldRev->userCan(Revision::DELETED_RESTRICTED)) { // If revision was hidden from sysops $ldel = Xml::tags('span', array('class' => 'mw-revdelundel-link'), '(' . wfMsgHtml('rev-delundel') . ')'); } else { $query = array('target' => $this->mOldRev->mTitle->getPrefixedDbkey(), 'oldid' => $this->mOldRev->getId()); $ldel = $sk->revDeleteLink($query, $this->mOldRev->isDeleted(Revision::DELETED_RESTRICTED)); } $ldel = " {$ldel} "; // We don't currently handle well changing the top revision's settings if ($this->mNewRev->isCurrent()) { $rdel = Xml::tags('span', array('class' => 'mw-revdelundel-link'), '(' . wfMsgHtml('rev-delundel') . ')'); } else { if (!$this->mNewRev->userCan(Revision::DELETED_RESTRICTED)) { // If revision was hidden from sysops $rdel = Xml::tags('span', array('class' => 'mw-revdelundel-link'), '(' . wfMsgHtml('rev-delundel') . ')'); } else { $query = array('target' => $this->mNewRev->mTitle->getPrefixedDbkey(), 'oldid' => $this->mNewRev->getId()); $rdel = $sk->revDeleteLink($query, $this->mNewRev->isDeleted(Revision::DELETED_RESTRICTED)); } } $rdel = " {$rdel} "; } $oldHeader = '<div id="mw-diff-otitle1"><strong>' . $this->mOldtitle . '</strong></div>' . '<div id="mw-diff-otitle2">' . $sk->revUserTools($this->mOldRev, !$this->unhide) . "</div>" . '<div id="mw-diff-otitle3">' . $oldminor . $sk->revComment($this->mOldRev, !$diffOnly, !$this->unhide) . $ldel . "</div>" . '<div id="mw-diff-otitle4">' . $prevlink . '</div>'; $newHeader = '<div id="mw-diff-ntitle1"><strong>' . $this->mNewtitle . '</strong></div>' . '<div id="mw-diff-ntitle2">' . $sk->revUserTools($this->mNewRev, !$this->unhide) . " {$rollback}</div>" . '<div id="mw-diff-ntitle3">' . $newminor . $sk->revComment($this->mNewRev, !$diffOnly, !$this->unhide) . $rdel . "</div>" . '<div id="mw-diff-ntitle4">' . $nextlink . $patrol . '</div>'; # Check if this user can see the revisions $allowed = $this->mOldRev->userCan(Revision::DELETED_TEXT) && $this->mNewRev->userCan(Revision::DELETED_TEXT); $deleted = $this->mOldRev->isDeleted(Revision::DELETED_TEXT) || $this->mNewRev->isDeleted(Revision::DELETED_TEXT); # Output the diff if allowed... if ($deleted && (!$this->unhide || !$allowed)) { $this->showDiffStyle(); $multi = $this->getMultiNotice(); $wgOut->addHTML($this->addHeader('', $oldHeader, $newHeader, $multi)); if (!$allowed) { # Give explanation for why revision is not visible $wgOut->wrapWikiMsg("<div class='mw-warning plainlinks'>\n\$1</div>\n", array('rev-deleted-no-diff')); } else { # Give explanation and add a link to view the diff... $link = $this->mTitle->getFullUrl("diff={$this->mNewid}&oldid={$this->mOldid}" . '&unhide=1&token=' . urlencode($wgUser->editToken($this->mNewid))); $wgOut->wrapWikiMsg("<div class='mw-warning plainlinks'>\n\$1</div>\n", array('rev-deleted-unhide-diff', $link)); } } else { if ($wgEnableHtmlDiff && $this->htmldiff) { $multi = $this->getMultiNotice(); $wgOut->addHTML('<div class="diff-switchtype">' . $sk->makeKnownLinkObj($this->mTitle, wfMsgHtml('wikicodecomparison'), 'diff=' . $this->mNewid . '&oldid=' . $this->mOldid . '&htmldiff=0', '', '', 'id="differences-switchtype"') . '</div>'); $wgOut->addHTML($this->addHeader('', $oldHeader, $newHeader, $multi)); $this->renderHtmlDiff(); } else { if ($wgEnableHtmlDiff) { $wgOut->addHTML('<div class="diff-switchtype">' . $sk->makeKnownLinkObj($this->mTitle, wfMsgHtml('visualcomparison'), 'diff=' . $this->mNewid . '&oldid=' . $this->mOldid . '&htmldiff=1', '', '', 'id="differences-switchtype"') . '</div>'); } $this->showDiff($oldHeader, $newHeader); if (!$diffOnly) { $this->renderNewRevision(); } } } wfProfileOut(__METHOD__); }
/** * Turn a RecentChange id into a revision ID. * Note: if the requested revision is a rolled back revision, don't return it. */ public static function getRevFromRC($pageid, $rcid) { $rc = RecentChange::newFromId($rcid, true); if ($rc) { // Check if there was a rollback on any of the more // recent changes to the article. If there was a // rollback, just return 0 so that it looks to any // calling function like there is no associated // revision ID to assign. $rollbackCommentPrefix = wfMsgForContent('rollback_comment_prefix'); $dbr = self::getDB('read'); $res = $dbr->select('recentchanges', array('rc_comment'), array('rc_cur_id' => $pageid, 'rc_id > ' . $rcid), __METHOD__); foreach ($res as $row) { $isRollback = strpos($row->rc_comment, $rollbackCommentPrefix) === 0; if ($isRollback) { return 0; } } return $rc->getAttribute('rc_this_oldid'); } else { return 0; } }
/** * Mark this particular edit as patrolled */ function markpatrolled() { global $wgOut, $wgRequest, $wgUseRCPatrol, $wgUser; $wgOut->setRobotPolicy('noindex,nofollow'); # Check RC patrol config. option if (!$wgUseRCPatrol) { $wgOut->errorPage('rcpatroldisabled', 'rcpatroldisabledtext'); return; } # Check permissions if (!$wgUser->isAllowed('patrol')) { $wgOut->permissionRequired('patrol'); return; } # If we haven't been given an rc_id value, we can't do anything $rcid = $wgRequest->getVal('rcid'); if (!$rcid) { $wgOut->errorPage('markedaspatrollederror', 'markedaspatrollederrortext'); return; } # Handle the 'MarkPatrolled' hook if (!wfRunHooks('MarkPatrolled', array($rcid, &$wgUser, false))) { return; } $return = SpecialPage::getTitleFor('Recentchanges'); # If it's left up to us, check that the user is allowed to patrol this edit # If the user has the "autopatrol" right, then we'll assume there are no # other conditions stopping them doing so if (!$wgUser->isAllowed('autopatrol')) { $rc = RecentChange::newFromId($rcid); # Graceful error handling, as we've done before here... # (If the recent change doesn't exist, then it doesn't matter whether # the user is allowed to patrol it or not; nothing is going to happen if (is_object($rc) && $wgUser->getName() == $rc->getAttribute('rc_user_text')) { # The user made this edit, and can't patrol it # Tell them so, and then back off $wgOut->setPageTitle(wfMsg('markedaspatrollederror')); $wgOut->addWikiText(wfMsgNoTrans('markedaspatrollederror-noautopatrol')); $wgOut->returnToMain(false, $return); return; } } # Mark the edit as patrolled RecentChange::markPatrolled($rcid); wfRunHooks('MarkPatrolledComplete', array(&$rcid, &$wgUser, false)); # Inform the user $wgOut->setPageTitle(wfMsg('markedaspatrolled')); $wgOut->addWikiText(wfMsgNoTrans('markedaspatrolledtext')); $wgOut->returnToMain(false, $return); }
static function getMarkPatrolledLink() { global $wgRequest, $wgUser; // Append a [Mark as Patrolled] link in certain cases $markPatrolledLink = ''; $rcid = $wgRequest->getInt('rcid'); $fromRC = $wgRequest->getInt('fromrc'); if ($wgUser && $rcid > 0 && $fromRC && $wgUser->isAllowed('patrol')) { $rc = RecentChange::newFromId($rcid); if ($rc) { $oldRevId = $rc->getAttribute('rc_last_oldid'); $newRevId = $rc->getAttribute('rc_this_oldid'); $diff = new DifferenceEngine(null, $oldRevId, $newRevId); if ($diff->loadRevisionData()) { $markPatrolledLink = $diff->markPatrolledLink(); } else { throw new MWException("wikiHow internal error: we know there is an rcid ({$rcid}) and newrevid ({$newRevId}), but couldn't find the revision"); } } } return $markPatrolledLink; }
function showDiffPage($diffOnly = false) { global $wgUser, $wgOut, $wgUseExternalEditor, $wgUseRCPatrol; wfProfileIn(__METHOD__); # Allow frames except in certain special cases $wgOut->allowClickjacking(); # If external diffs are enabled both globally and for the user, # we'll use the application/x-external-editor interface to call # an external diff tool like kompare, kdiff3, etc. if ($wgUseExternalEditor && $wgUser->getOption('externaldiff')) { global $wgCanonicalServer, $wgScript, $wgLang; $wgOut->disable(); header("Content-type: application/x-external-editor; charset=UTF-8"); $url1 = $this->mTitle->getCanonical(array('action' => 'raw', 'oldid' => $this->mOldid)); $url2 = $this->mTitle->getCanonical(array('action' => 'raw', 'oldid' => $this->mNewid)); $special = $wgLang->getNsText(NS_SPECIAL); $control = <<<CONTROL \t\t\t[Process] \t\t\tType=Diff text \t\t\tEngine=MediaWiki \t\t\tScript={$wgCanonicalServer}{$wgScript} \t\t\tSpecial namespace={$special} \t\t\t[File] \t\t\tExtension=wiki \t\t\tURL={$url1} \t\t\t[File 2] \t\t\tExtension=wiki \t\t\tURL={$url2} CONTROL; echo $control; wfProfileOut(__METHOD__); return; } $wgOut->setArticleFlag(false); if (!$this->loadRevisionData()) { // Sounds like a deleted revision... Let's see what we can do. $t = $this->mTitle->getPrefixedText(); $d = wfMsgExt('missingarticle-diff', array('escape'), $this->deletedIdMarker($this->mOldid), $this->deletedIdMarker($this->mNewid)); $wgOut->setPagetitle(wfMsg('errorpagetitle')); $wgOut->addWikiMsg('missing-article', "<nowiki>{$t}</nowiki>", "<span class='plainlinks'>{$d}</span>"); wfProfileOut(__METHOD__); return; } wfRunHooks('DiffViewHeader', array($this, $this->mOldRev, $this->mNewRev)); if ($this->mNewRev->isCurrent()) { $wgOut->setArticleFlag(true); } # mOldid is false if the difference engine is called with a "vague" query for # a diff between a version V and its previous version V' AND the version V # is the first version of that article. In that case, V' does not exist. if ($this->mOldid === false) { $this->showFirstRevision(); $this->renderNewRevision(); // should we respect $diffOnly here or not? wfProfileOut(__METHOD__); return; } $oldTitle = $this->mOldPage->getPrefixedText(); $newTitle = $this->mNewPage->getPrefixedText(); if ($oldTitle == $newTitle) { $wgOut->setPageTitle($newTitle); } else { $wgOut->setPageTitle($oldTitle . ', ' . $newTitle); } if ($this->mNewPage->equals($this->mOldPage)) { $wgOut->setSubtitle(wfMsgExt('difference', array('parseinline'))); } else { $wgOut->setSubtitle(wfMsgExt('difference-multipage', array('parseinline'))); } $wgOut->setRobotPolicy('noindex,nofollow'); if (!$this->mOldPage->userCanRead() || !$this->mNewPage->userCanRead()) { $wgOut->loginToUse(); $wgOut->output(); $wgOut->disable(); wfProfileOut(__METHOD__); return; } $sk = $wgUser->getSkin(); if (method_exists($sk, 'suppressQuickbar')) { $sk->suppressQuickbar(); } // Check if page is editable $editable = $this->mNewRev->getTitle()->userCan('edit'); if ($editable && $this->mNewRev->isCurrent() && $wgUser->isAllowed('rollback')) { $wgOut->preventClickjacking(); $rollback = '   ' . $sk->generateRollback($this->mNewRev); } else { $rollback = ''; } // Prepare a change patrol link, if applicable if ($wgUseRCPatrol && $this->mTitle->userCan('patrol')) { // If we've been given an explicit change identifier, use it; saves time if ($this->mRcidMarkPatrolled) { $rcid = $this->mRcidMarkPatrolled; $rc = RecentChange::newFromId($rcid); // Already patrolled? $rcid = is_object($rc) && !$rc->getAttribute('rc_patrolled') ? $rcid : 0; } else { // Look for an unpatrolled change corresponding to this diff $db = wfGetDB(DB_SLAVE); $change = RecentChange::newFromConds(array('rc_user_text' => $this->mNewRev->getRawUserText(), 'rc_timestamp' => $db->timestamp($this->mNewRev->getTimestamp()), 'rc_this_oldid' => $this->mNewid, 'rc_last_oldid' => $this->mOldid, 'rc_patrolled' => 0), __METHOD__); if ($change instanceof RecentChange) { $rcid = $change->mAttribs['rc_id']; $this->mRcidMarkPatrolled = $rcid; } else { // None found $rcid = 0; } } // Build the link if ($rcid) { $wgOut->preventClickjacking(); $token = $wgUser->editToken($rcid); $patrol = ' <span class="patrollink">[' . $sk->link($this->mTitle, wfMsgHtml('markaspatrolleddiff'), array(), array('action' => 'markpatrolled', 'rcid' => $rcid, 'token' => $token), array('known', 'noclasses')) . ']</span>'; } else { $patrol = ''; } } else { $patrol = ''; } # Carry over 'diffonly' param via navigation links if ($diffOnly != $wgUser->getBoolOption('diffonly')) { $query['diffonly'] = $diffOnly; } # Make "previous revision link" $query['diff'] = 'prev'; $query['oldid'] = $this->mOldid; # Cascade unhide param in links for easy deletion browsing if ($this->unhide) { $query['unhide'] = 1; } if (!$this->mOldRev->getPrevious()) { $prevlink = ' '; } else { $prevlink = $sk->link($this->mTitle, wfMsgHtml('previousdiff'), array('id' => 'differences-prevlink'), $query, array('known', 'noclasses')); } # Make "next revision link" $query['diff'] = 'next'; $query['oldid'] = $this->mNewid; # Skip next link on the top revision if ($this->mNewRev->isCurrent()) { $nextlink = ' '; } else { $nextlink = $sk->link($this->mTitle, wfMsgHtml('nextdiff'), array('id' => 'differences-nextlink'), $query, array('known', 'noclasses')); } $oldminor = ''; $newminor = ''; if ($this->mOldRev->isMinor()) { $oldminor = ChangesList::flag('minor'); } if ($this->mNewRev->isMinor()) { $newminor = ChangesList::flag('minor'); } # Handle RevisionDelete links... $ldel = $this->revisionDeleteLink($this->mOldRev); $rdel = $this->revisionDeleteLink($this->mNewRev); $oldHeader = '<div id="mw-diff-otitle1"><strong>' . $this->mOldtitle . '</strong></div>' . '<div id="mw-diff-otitle2">' . $sk->revUserTools($this->mOldRev, !$this->unhide) . '</div>' . '<div id="mw-diff-otitle3">' . $oldminor . $sk->revComment($this->mOldRev, !$diffOnly, !$this->unhide) . $ldel . '</div>' . '<div id="mw-diff-otitle4">' . $prevlink . '</div>'; $newHeader = '<div id="mw-diff-ntitle1"><strong>' . $this->mNewtitle . '</strong></div>' . '<div id="mw-diff-ntitle2">' . $sk->revUserTools($this->mNewRev, !$this->unhide) . " {$rollback}</div>" . '<div id="mw-diff-ntitle3">' . $newminor . $sk->revComment($this->mNewRev, !$diffOnly, !$this->unhide) . $rdel . '</div>' . '<div id="mw-diff-ntitle4">' . $nextlink . $patrol . '</div>'; # Check if this user can see the revisions $allowed = $this->mOldRev->userCan(Revision::DELETED_TEXT) && $this->mNewRev->userCan(Revision::DELETED_TEXT); # Check if one of the revisions is deleted/suppressed $deleted = $suppressed = false; if ($this->mOldRev->isDeleted(Revision::DELETED_TEXT)) { $deleted = true; // old revisions text is hidden if ($this->mOldRev->isDeleted(Revision::DELETED_RESTRICTED)) { $suppressed = true; } // also suppressed } if ($this->mNewRev->isDeleted(Revision::DELETED_TEXT)) { $deleted = true; // new revisions text is hidden if ($this->mNewRev->isDeleted(Revision::DELETED_RESTRICTED)) { $suppressed = true; } // also suppressed } # If the diff cannot be shown due to a deleted revision, then output # the diff header and links to unhide (if available)... if ($deleted && (!$this->unhide || !$allowed)) { $this->showDiffStyle(); $multi = $this->getMultiNotice(); $wgOut->addHTML($this->addHeader('', $oldHeader, $newHeader, $multi)); if (!$allowed) { $msg = $suppressed ? 'rev-suppressed-no-diff' : 'rev-deleted-no-diff'; # Give explanation for why revision is not visible $wgOut->wrapWikiMsg("<div id='mw-{$msg}' class='mw-warning plainlinks'>\n\$1\n</div>\n", array($msg)); } else { # Give explanation and add a link to view the diff... $link = $this->mTitle->getFullUrl(array('diff' => $this->mNewid, 'oldid' => $this->mOldid, 'unhide' => 1)); $msg = $suppressed ? 'rev-suppressed-unhide-diff' : 'rev-deleted-unhide-diff'; $wgOut->wrapWikiMsg("<div id='mw-{$msg}' class='mw-warning plainlinks'>\n\$1\n</div>\n", array($msg, $link)); } # Otherwise, output a regular diff... } else { # Add deletion notice if the user is viewing deleted content $notice = ''; if ($deleted) { $msg = $suppressed ? 'rev-suppressed-diff-view' : 'rev-deleted-diff-view'; $notice = "<div id='mw-{$msg}' class='mw-warning plainlinks'>\n" . wfMsgExt($msg, 'parseinline') . "</div>\n"; } $this->showDiff($oldHeader, $newHeader, $notice); if (!$diffOnly) { $this->renderNewRevision(); } } wfProfileOut(__METHOD__); }
function markRevisionsPatrolled($article) { global $wgOut; $request = $this->getRequest(); // some sanity checks $rcid = $request->getInt('rcid'); $rc = RecentChange::newFromId($rcid); if (is_null($rc)) { throw new ErrorPageError('markedaspatrollederror', 'markedaspatrollederrortext'); } $user = $this->getUser(); if (!$user->matchEditToken($request->getVal('token'), $rcid)) { throw new ErrorPageError('sessionfailure-title', 'sessionfailure'); } // check if skip has been passed to us if ($request->getInt('skip') != 1) { // find his and lows $rcids = array(); $rcids[] = $rcid; if ($request->getVal('rchi', null) && $request->getVal('rclow', null)) { $hilos = wfGetRCPatrols($rcid, $request->getVal('rchi'), $request->getVal('rclow'), $article->mTitle->getArticleID()); $rcids = array_merge($rcids, $hilos); } $rcids = array_unique($rcids); foreach ($rcids as $id) { RecentChange::markPatrolled($id, false); } wfRunHooks('MarkPatrolledBatchComplete', array(&$article, &$rcids, &$user)); } else { RCPatrol::skipPatrolled($article); } }
/** * Mark a given change as patrolled * * @param $change Mixed: RecentChange or corresponding rc_id * @param $auto Boolean: for automatic patrol * @return Array See doMarkPatrolled(), or null if $change is not an existing rc_id */ public static function markPatrolled($change, $auto = false, $force = false) { global $wgUser; $change = $change instanceof RecentChange ? $change : RecentChange::newFromId($change); if (!$change instanceof RecentChange) { return null; } return $change->doMarkPatrolled($wgUser, $auto, $force); }
/** * Mark this particular edit/page as patrolled */ public function markpatrolled() { global $wgOut, $wgRequest, $wgUseRCPatrol, $wgUseNPPatrol, $wgUser; $wgOut->setRobotPolicy('noindex,nofollow'); # If we haven't been given an rc_id value, we can't do anything $rcid = (int) $wgRequest->getVal('rcid'); $rc = RecentChange::newFromId($rcid); if (is_null($rc)) { $wgOut->showErrorPage('markedaspatrollederror', 'markedaspatrollederrortext'); return; } #It would be nice to see where the user had actually come from, but for now just guess $returnto = $rc->getAttribute('rc_type') == RC_NEW ? 'Newpages' : 'Recentchanges'; $return = Title::makeTitle(NS_SPECIAL, $returnto); $dbw = wfGetDB(DB_MASTER); $errors = $rc->doMarkPatrolled(); if (in_array(array('rcpatroldisabled'), $errors)) { $wgOut->showErrorPage('rcpatroldisabled', 'rcpatroldisabledtext'); return; } if (in_array(array('hookaborted'), $errors)) { // The hook itself has handled any output return; } if (in_array(array('markedaspatrollederror-noautopatrol'), $errors)) { $wgOut->setPageTitle(wfMsg('markedaspatrollederror')); $wgOut->addWikiMsg('markedaspatrollederror-noautopatrol'); $wgOut->returnToMain(false, $return); return; } if (!empty($errors)) { $wgOut->showPermissionsErrorPage($errors); return; } # Inform the user $wgOut->setPageTitle(wfMsg('markedaspatrolled')); $wgOut->addWikiMsg('markedaspatrolledtext'); $wgOut->returnToMain(false, $return); }
/** * Mark a given change as patrolled * * @param $change Mixed: RecentChange or corresponding rc_id * @param $auto Boolean: for automatic patrol * @return Array See doMarkPatrolled(), or null if $change is not an existing rc_id */ public static function markPatrolled($change, $auto = false) { $change = $change instanceof RecentChange ? $change : RecentChange::newFromId($change); if (!$change instanceof RecentChange) { return null; } return $change->doMarkPatrolled($auto); }
/** * Mark this particular edit/page as patrolled */ function markpatrolled() { global $wgOut, $wgRequest, $wgUseRCPatrol, $wgUseNPPatrol, $wgUser; $wgOut->setRobotPolicy('noindex,nofollow'); # Check patrol config options if (!($wgUseNPPatrol || $wgUseRCPatrol)) { $wgOut->errorPage('rcpatroldisabled', 'rcpatroldisabledtext'); return; } if ($wgUser->isBlocked()) { $wgOut->blockedPage(); return; } # If we haven't been given an rc_id value, we can't do anything $rcid = (int) $wgRequest->getVal('rcid'); $rc = $rcid ? RecentChange::newFromId($rcid) : null; if (is_null($rc)) { $wgOut->errorPage('markedaspatrollederror', 'markedaspatrollederrortext'); return; } if (!$wgUseRCPatrol && $rc->mAttribs['rc_type'] != RC_NEW) { // Only new pages can be patrolled if the general patrolling is off....??? // @fixme -- is this necessary? Shouldn't we only bother controlling the // front end here? $wgOut->errorPage('rcpatroldisabled', 'rcpatroldisabledtext'); return; } # Check permissions $permission_errors = $this->mTitle->getUserPermissionsErrors('patrol', $wgUser); if (count($permission_errors) > 0) { $wgOut->showPermissionsErrorPage($permission_errors); return; } # Handle the 'MarkPatrolled' hook if (!wfRunHooks('MarkPatrolled', array($rcid, &$wgUser, false))) { return; } #It would be nice to see where the user had actually come from, but for now just guess $returnto = $rc->mAttribs['rc_type'] == RC_NEW ? 'Newpages' : 'Recentchanges'; $return = Title::makeTitle(NS_SPECIAL, $returnto); # If it's left up to us, check that the user is allowed to patrol this edit # If the user has the "autopatrol" right, then we'll assume there are no # other conditions stopping them doing so if (!$wgUser->isAllowed('autopatrol') && $wgRequest->getVal('skip') != 1) { $rc = RecentChange::newFromId($rcid); # Graceful error handling, as we've done before here... # (If the recent change doesn't exist, then it doesn't matter whether # the user is allowed to patrol it or not; nothing is going to happen if (is_object($rc) && $wgUser->getName() == $rc->getAttribute('rc_user_text')) { # The user made this edit, and can't patrol it # Tell them so, and then back off $wgOut->setPageTitle(wfMsg('markedaspatrollederror')); $wgOut->addWikiMsg('markedaspatrollederror-noautopatrol'); $wgOut->returnToMain(false, $return); return; } } # Mark the edit as patrolled if (!wfRunHooks('ArticleMarkPatrolled', array(&$this, $rcid))) { return; } wfRunHooks('MarkPatrolledComplete', array(&$rcid, &$wgUser, false)); # Inform the user $wgOut->setPageTitle(wfMsg('markedaspatrolled')); $wgOut->addWikiMsg('markedaspatrolledtext'); $wgOut->returnToMain(false, $return); }