return true;
}
- /** Backend rollback implementation. UI logic is in rollback()
- * @param string $user - Name of the user whose edits to rollback.
- * @param string $token - Rollback token.
- * @param bool $bot - If true, mark all reverted edits as bot.
- * @param string $summary - Custom summary. Set to default summary if empty.
- * @param array $info - Reference to associative array that will be set to contain the revision ID, edit summary, etc.
- * @return ROLLBACK_SUCCES on succes, ROLLBACK_* on failure
- */
- public function doRollback($user, $token, $bot = false, $summary = "", &$info = NULL)
- {
- global $wgUser, $wgUseRCPatrol;
- if(!$wgUser->isAllowed('rollback'))
- return ROLLBACK_PERM;
- if($wgUser->isBlocked())
- return ROLLBACK_BLOCKED;
- if(wfReadOnly())
- return ROLLBACK_READONLY;
-
- // Check token first
- if(!$wgUser->matchEditToken($token, array($this->mTitle->getPrefixedText(), $user)))
- return ROLLBACK_BADTOKEN;
-
- $dbw = wfGetDB(DB_MASTER);
- $current = Revision::newFromTitle($this->mTitle);
- if(is_null($current))
- return ROLLBACK_BADARTICLE;
-
- // Check if someone else was there first
- if($user != $current->getUserText())
- {
- $info['usertext'] = $current->getUserText();
- $info['comment'] = $current->getComment();
- return ROLLBACK_ALREADYROLLED;
- }
- // Get the last edit not by $user
- $userid = intval($current->getUser());
- $s = $dbw->selectRow('revision',
- array('rev_id', 'rev_timestamp'),
+ /**
+ * Revert a modification
+ */
+ function rollback() {
+ global $wgUser, $wgOut, $wgRequest, $wgUseRCPatrol;
+
+ if( $wgUser->isAllowed( 'rollback' ) ) {
+ if( $wgUser->isBlocked() ) {
+ $wgOut->blockedPage();
+ return;
+ }
+ } else {
+ $wgOut->permissionRequired( 'rollback' );
+ return;
+ }
+
+ if ( wfReadOnly() ) {
+ $wgOut->readOnlyPage( $this->getContent() );
+ return;
+ }
+ if( !$wgUser->matchEditToken( $wgRequest->getVal( 'token' ),
+ array( $this->mTitle->getPrefixedText(),
+ $wgRequest->getVal( 'from' ) ) ) ) {
+ $wgOut->setPageTitle( wfMsg( 'rollbackfailed' ) );
+ $wgOut->addWikiText( wfMsg( 'sessionfailure' ) );
+ return;
+ }
+ $dbw = wfGetDB( DB_MASTER );
+
+ # Enhanced rollback, marks edits rc_bot=1
+ $bot = $wgRequest->getBool( 'bot' );
+
+ # Replace all this user's current edits with the next one down
+
+ # Get the last editor
+ $current = Revision::newFromTitle( $this->mTitle );
+ if( is_null( $current ) ) {
+ # Something wrong... no page?
+ $wgOut->addHTML( wfMsg( 'notanarticle' ) );
+ return;
+ }
+
+ $from = str_replace( '_', ' ', $wgRequest->getVal( 'from' ) );
+ if( $from != $current->getUserText() ) {
+ $wgOut->setPageTitle( wfMsg('rollbackfailed') );
+ $wgOut->addWikiText( wfMsg( 'alreadyrolled',
+ htmlspecialchars( $this->mTitle->getPrefixedText()),
+ htmlspecialchars( $from ),
+ htmlspecialchars( $current->getUserText() ) ) );
+ if( $current->getComment() != '') {
+ $wgOut->addHTML(
+ wfMsg( 'editcomment',
+ $wgUser->getSkin()->formatComment( $current->getComment() ) ) );
+ }
+ return;
+ }
+
+ # Get the last edit not by this guy
+ $user = intval( $current->getUser() );
+ $user_text = $dbw->addQuotes( $current->getUserText() );
+ $s = $dbw->selectRow( 'revision',
+ array( 'rev_id', 'rev_timestamp' ),
array(
'rev_page' => $current->getPage(),
- "rev_user <> $userid OR rev_user_text <> {$dbw->addQuotes($user)}"
+ "rev_user <> {$user} OR rev_user_text <> {$user_text}"
), __METHOD__,
array(
'USE INDEX' => 'page_timestamp',
- 'ORDER BY' => 'rev_timestamp DESC'
- ));
- if($s === false)
- return ROLLBACK_ONLYAUTHOR;
- $target = Revision::newFromID($s->rev_id);
+ 'ORDER BY' => 'rev_timestamp DESC' )
+ );
+ if( $s === false ) {
+ # Something wrong
+ $wgOut->setPageTitle(wfMsg('rollbackfailed'));
+ $wgOut->addHTML( wfMsg( 'cantrollback' ) );
+ return;
+ }
- // If the reverted edits should be marked bot or patrolled, do so
$set = array();
- if($bot)
+ if ( $bot ) {
+ # Mark all reverted edits as bot
$set['rc_bot'] = 1;
- if($wgUseRCPatrol)
+ }
+ if ( $wgUseRCPatrol ) {
+ # Mark all reverted edits as patrolled
$set['rc_patrolled'] = 1;
- if($set)
- $dbw->update('recentchanges', $set,
- array(
- 'rc_cur_id' => $current->getPage(),
- 'rc_user_text' => $user,
- "rc_timestamp > '{$s->rev_timestamp}'"
- ), __METHOD__
- );
-
- // Generate an edit summary
- if(empty($summary))
- $summary = wfMsgForContent('revertpage', $target->getUserText(), $user);
-
- // Now we *finally* get to commit the edit
- $flags = EDIT_UPDATE | EDIT_MINOR;
- if($bot)
- $flags |= EDIT_FORCE_BOT;
- if(!$this->doEdit($target->getText(), $summary, $flags))
- return ROLLBACK_EDITFAILED;
-
- if(is_null($info))
- // Save time
- return ROLLBACK_SUCCESS;
-
- $info['title'] = $this->mTitle->getPrefixedText();
- $info['pageid'] = $current->getPage();
- $info['summary'] = $summary;
- // NOTE: If the rollback turned out to be a null edit, revid and old_revid will be equal
- $info['revid'] = $this->mTitle->getLatestRevID(); // The revid of your rollback
- $info['old_revid'] = $current->getId(); // The revid of the last edit before your rollback
- $info['last_revid'] = $s->rev_id; // The revid of the last edit that was not rolled back
- $info['user'] = $user; // The name of the victim
- $info['userid'] = $userid; // And their userid
- $info['to'] = $target->getUserText(); // The user whose last version was reverted to
- if($bot)
- $info['bot'] = "";
- return ROLLBACK_SUCCESS;
- }
-
- /** UI entry point for rollbacks. Relies on doRollback() to do the hard work */
- function rollback() {
- global $wgUser, $wgOut, $wgRequest, $wgUseRCPatrol;
+ }
- // Basically, we just call doRollback() and interpret its return value
- $info = array();
- $retval = $this->doRollback($wgRequest->getVal('from'), $wgRequest->getVal('token'), $wgRequest->getBool('bot'),
- $wgRequest->getText('summary'), &$info);
- switch($retval)
- {
- case ROLLBACK_SUCCESS:
- case ROLLBACK_EDITFAILED: // Is ignored
- $wgOut->setPagetitle( wfMsg( 'actioncomplete' ) );
- $wgOut->setRobotpolicy( 'noindex,nofollow' );
- $wgOut->addHTML( '<h2>' . htmlspecialchars( $info['summary'] ) . "</h2>\n<hr />\n" );
- $this->doRedirect(true);
- $wgOut->returnToMain(false);
- return;
- case ROLLBACK_PERM:
- $wgOut->permissionRequired('rollback');
- return;
- case ROLLBACK_BLOCKED:
- $wgOut->blockedPage();
- return;
- case ROLLBACK_READONLY:
- $wgOut->readOnlyPage($this->getContent());
- return;
- case ROLLBACK_BADTOKEN:
- $wgOut->setPageTitle(wfMsg('rollbackfailed'));
- $wgOut->addWikiText(wfMsg('sessionfailure'));
- return;
- case ROLLBACK_BADARTICLE:
- $wgOut->addHTML(wfMsg('notanarticle'));
- return;
- case ROLLBACK_ALREADYROLLED:
- $wgOut->setPageTitle(wfMsg('rollbackfailed'));
- $wgOut->addWikiText(wfMsg('alreadyrolled',
- htmlspecialchars($this->mTitle->getPrefixedText()),
- htmlspecialchars($wgRequest->getVal('from')),
- htmlspecialchars($info['usertext'])));
- if($info['comment'] != '')
- $wgOut->addHTML(wfMsg('editcomment',
- $wgUser->getSkin()->formatComment($info['comment'])));
- return;
- case ROLLBACK_ONLYAUTHOR:
- $wgOut->setPageTitle(wfMsg('rollbackfailed'));
- $wgOut->addHTML(wfMsg('cantrollback'));
- return;
+ if ( $set ) {
+ $dbw->update( 'recentchanges', $set,
+ array( /* WHERE */
+ 'rc_cur_id' => $current->getPage(),
+ 'rc_user_text' => $current->getUserText(),
+ "rc_timestamp > '{$s->rev_timestamp}'",
+ ), __METHOD__
+ );
}
+
+ # Get the edit summary
+ $target = Revision::newFromId( $s->rev_id );
+ $newComment = wfMsgForContent( 'revertpage', $target->getUserText(), $from );
+ $newComment = $wgRequest->getText( 'summary', $newComment );
+
+ # Save it!
+ $wgOut->setPagetitle( wfMsg( 'actioncomplete' ) );
+ $wgOut->setRobotpolicy( 'noindex,nofollow' );
+ $wgOut->addHTML( '<h2>' . htmlspecialchars( $newComment ) . "</h2>\n<hr />\n" );
+
+ $this->updateArticle( $target->getText(), $newComment, 1, $this->mTitle->userIsWatching(), $bot );
+
+ $wgOut->returnToMain( false );
}
+
/**
* Do standard deferred updates after page view
* @private
'ApiQuerySiteinfo' => 'includes/api/ApiQuerySiteinfo.php',
'ApiQueryWatchlist' => 'includes/api/ApiQueryWatchlist.php',
'ApiResult' => 'includes/api/ApiResult.php',
- 'ApiRollback' => 'includes/api/ApiRollback.php'
);
wfProfileIn( __METHOD__ );
define( 'EDIT_AUTOSUMMARY', 64 );
/**#@-*/
-/**#@+
- * Article::doRollback() return values
- */
-define('ROLLBACK_SUCCES', 0);
-define('ROLLBACK_PERM', 1); // Permission denied
-define('ROLLBACK_BLOCKED', 2); // User has been blocked
-define('ROLLBACK_READONLY', 3); // Wiki is in read-only mode
-define('ROLLBACK_BADTOKEN', 4); // Invalid token specified
-define('ROLLBACK_BADARTICLE', 5); // $article is not a valid Article
-define('ROLLBACK_ALREADYROLLED', 6); // Someone else already rolled this back. $info['usertext'] and $info['comment'] will be set
-define('ROLLBACK_ONLYAUTHOR', 7); // User is the only author of the page
-define('ROLLBACK_EDITFAILED', 8); // Article::doEdit() failed. This is a very weird error
-
/**
* Flags for Database::makeList()
* These are also available as Database class constants
private static $Modules = array (
'login' => 'ApiLogin',
'query' => 'ApiQuery',
- 'rollback' => 'ApiRollback',
'opensearch' => 'ApiOpenSearch',
'feedwatchlist' => 'ApiFeedWatchlist',
'help' => 'ApiHelp',
$this->mRequest = & $request;
$this->mSquidMaxage = 0;
-
- global $wgUser, $wgCookiePrefix;
- if(session_id() == '')
- wfSetupSession();
- // Reinit $wgUser with info from lg* or the session data. The former overrides the latter
- if(isset($_REQUEST['lguserid']) && isset($_REQUEST['lgusername']) && isset($_REQUEST['lgtoken']))
- {
- $_SESSION['wsUserID'] = $_REQUEST['lguserid'];
- $_SESSION['wsUserName'] = $_REQUEST['lgusername'];
- $_SESSION['wsToken'] = $_REQUEST['lgtoken'];
- }
- $wgUser = User::newFromSession();
}
/**
}
public function execute() {
- global $wgUser;
$params = $this->extractRequestParams();
$fld_protection = false;
if(!is_null($params['prop'])) {
$prop = array_flip($params['prop']);
$fld_protection = isset($prop['protection']);
- $fld_lastrevby = isset($prop['lastrevby']);
}
- if(!is_null($params['tokens']))
- $params['tokens'] = array_flip($params['tokens']);
$pageSet = $this->getPageSet();
$titles = $pageSet->getGoodTitles();
$db->freeResult($res);
}
- foreach ( $titles as $pageid => $title ) {
+ foreach ( $titles as $pageid => $unused ) {
$pageInfo = array (
'touched' => wfTimestamp(TS_ISO_8601, $pageTouched[$pageid]),
'lastrevid' => intval($pageLatest[$pageid]),
'counter' => intval($pageCounter[$pageid]),
- 'length' => intval($pageLength[$pageid])
+ 'length' => intval($pageLength[$pageid]),
);
- if(isset($params['tokens']) || $fld_lastrevby)
- {
- $lastrev = Revision::newFromId($pageInfo['lastrevid']);
- $pageInfo['lastrevby'] = $lastrev->getUserText();
- }
if ($pageIsRedir[$pageid])
$pageInfo['redirect'] = '';
}
}
- $tokenArr = array();
- foreach($params['tokens'] as $token => $unused)
- switch($token)
- {
- case 'rollback':
- $tokenArr[$token] = $wgUser->editToken(array($title->getPrefixedText(), $pageInfo['lastrevby']));
- break;
- case 'edit':
- case 'move':
- case 'delete':
- case 'undelete':
- case 'protect':
- case 'unprotect':
- if($wgUser->isAnon())
- $tokenArr[$token] = EDIT_TOKEN_SUFFIX;
- else
- $tokenArr[$token] = $wgUser->editToken();
- // default: can't happen, ignore it if it does happen in some weird way
- }
- if(count($tokenArr) > 0)
- {
- $pageInfo['tokens'] = $tokenArr;
- $result->setIndexedTagName($pageInfo['tokens'], 't');
- }
-
$result->addValue(array (
'query',
'pages'
ApiBase :: PARAM_DFLT => NULL,
ApiBase :: PARAM_ISMULTI => true,
ApiBase :: PARAM_TYPE => array (
- 'protection',
- 'lastrevby'
- )),
- 'tokens' => array(
- ApiBase :: PARAM_DFLT => NULL,
- ApiBase :: PARAM_ISMULTI => true,
- ApiBase :: PARAM_TYPE => array(
- 'edit',
- 'move',
- 'delete',
- 'undelete',
- 'rollback',
- 'protect',
- 'unprotect'
+ 'protection'
))
);
}
return array (
'prop' => array (
'Which additional properties to get:',
- ' "protection" - List the protection level of each page',
- ' "lastrevby" - The name of the user who made the last edit. You may need this for action=rollback.'
- ),
- 'tokens' => 'Which tokens to get.'
+ ' "protection" - List the protection level of each page'
+ )
);
}
protected function getExamples() {
return array (
'api.php?action=query&prop=info&titles=Main%20Page',
- 'api.php?action=query&prop=info&inprop=protection&titles=Main%20Page',
- 'api.php?action=query&prop=info&intokens=edit|rollback&titles=Main%20Page'
+ 'api.php?action=query&prop=info&inprop=protection&titles=Main%20Page'
);
}
-<?php
-
-/*
- * Created on Jun 20, 2007
- * API for MediaWiki 1.8+
- *
- * Copyright (C) 2007 Roan Kattouw <Firstname>.<Lastname>@home.nl
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-if (!defined('MEDIAWIKI')) {
- // Eclipse helper - will be ignored in production
- require_once ("ApiBase.php");
-}
-
-/**
- * @addtogroup API
- */
-class ApiRollback extends ApiBase {
-
- public function __construct($main, $action) {
- parent :: __construct($main, $action);
- }
-
- public function execute() {
- global $wgUser;
- $params = $this->extractRequestParams();
-
- $titleObj = NULL;
- if(!isset($params['title']))
- $this->dieUsage('The title parameter must be set', 'notarget');
- if(!isset($params['user']))
- $this->dieUsage('The user parameter must be set', 'nouser');
- if(!isset($params['token']))
- $this->dieUsage('The token parameter must be set', 'notoken');
-
- // doRollback() also checks for these, but we wanna save some work
- if(!$wgUser->isAllowed('rollback'))
- $this->dieUsage('You don\'t have permission to rollback', 'permissiondenied');
- if($wgUser->isBlocked())
- $this->dieUsage('You have been blocked from editing', 'blocked');
- if(wfReadOnly())
- $this->dieUsage('The wiki is in read-only mode', 'readonly');
-
- $titleObj = Title::newFromText($params['title']);
- if(!$titleObj)
- $this->dieUsage("bad title {$params['title']}", 'invalidtitle');
-
- $articleObj = new Article($titleObj);
- $summary = (isset($params['summary']) ? $params['summary'] : "");
- $info = array();
- $retval = $articleObj->doRollback($params['user'], $params['token'], isset($params['markbot']), $summary, &$info);
-
- switch($retval)
- {
- case ROLLBACK_SUCCESS:
- break; // We'll deal with that later
- case ROLLBACK_PERM:
- $this->dieUsage('You don\'t have permission to rollback', 'permissiondenied');
- case ROLLBACK_BLOCKED: // If we get BLOCKED or PERM that's very weird, but it's possible
- $this->dieUsage('You have been blocked from editing', 'blocked');
- case ROLLBACK_READONLY:
- $this->dieUsage('The wiki is in read-only mode', 'readonly');
- case ROLLBACK_BADTOKEN:
- $this->dieUsage('Invalid token', 'badtoken');
- case ROLLBACK_BADARTICLE:
- $this->dieUsage("The article ``{$params['title']}'' doesn't exist", 'missingtitle');
- case ROLLBACK_ALREADYROLLED:
- $this->dieUsage('The edit(s) you tried to rollback is/are already rolled back', 'alreadyrolled');
- case ROLLBACK_ONLYAUTHOR:
- $this->dieUsage("{$params['user']} is the only author of the page", 'onlyauthor');
- case ROLLBACK_EDITFAILED:
- $this->dieDebug(__METHOD__, 'Article::doEdit() failed');
- default:
- // rollback() has apparently invented a new error, which is extremely weird
- $this->dieDebug(__METHOD__, "rollback() returned an unknown error ($retval)");
- }
- // $retval has to be ROLLBACK_SUCCESS if we get here
- $this->getResult()->addValue(null, 'rollback', $info);
- }
-
- protected function getAllowedParams() {
- return array (
- 'title' => null,
- 'user' => null,
- 'token' => null,
- 'summary' => null,
- 'markbot' => null
- );
- }
-
- protected function getParamDescription() {
- return array (
- 'title' => 'Title of the page you want to rollback.',
- 'user' => 'Name of the user whose edits are to be rolled back. If set incorrectly, you\'ll get a badtoken error.',
- 'token' => 'A rollback token previously retrieved through prop=info',
- 'summary' => 'Custom edit summary. If not set, default summary will be used.',
- 'markbot' => 'Mark the reverted edits and the revert as bot edits'
- );
- }
-
- protected function getDescription() {
- return array(
- 'Undoes the last edit to the page. If the last user who edited the page made multiple edits in a row,',
- 'they will all be rolled back. You need to be logged in as a sysop to use this function, see also action=login.'
- );
- }
-
- protected function getExamples() {
- return array (
- 'api.php?action=rollback&title=Main%20Page&user=Catrope&token=123ABC',
- 'api.php?action=rollback&title=Main%20Page&user=217.121.114.116&token=123ABC&summary=Reverting%20vandalism&markbot=1'
- );
- }
-
- public function getVersion() {
- return __CLASS__ . ': $Id: ApiRollback.php 22289 2007-05-20 23:31:44Z yurik $';
- }
-}
-?>