From f9a36ee7bfd0834b2cd02779410c1abd24a3f556 Mon Sep 17 00:00:00 2001 From: Bryan Tong Minh Date: Sat, 5 Mar 2011 17:23:35 +0000 Subject: [PATCH] (bug 27018) Added action=filerevert to revert files to an old version. Copied procedure from FileRevertForm, as most of the verification procedure is simple enough to not warrant the effort of writing a dedicated backend. Further changes: * Added Status::getErrorsByType() which returns the internal error array untouched * Added ApiResult::convertStatusToArray() which converts a Status object to something useful for the Api --- RELEASE-NOTES | 1 + includes/AutoLoader.php | 1 + includes/Status.php | 18 ++++ includes/api/ApiFileRevert.php | 192 +++++++++++++++++++++++++++++++++ includes/api/ApiMain.php | 1 + includes/api/ApiResult.php | 21 ++++ 6 files changed, 234 insertions(+) create mode 100644 includes/api/ApiFileRevert.php diff --git a/RELEASE-NOTES b/RELEASE-NOTES index d1ba8b5478..c1abcde979 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -208,6 +208,7 @@ PHP if you have not done so prior to upgrading MediaWiki. * (bug 27862) Useremail module didn't properly return success on success. * (bug 27590) prop=imageinfo now allows querying the media type * (bug 27587) list=filearchive now outputs full title info +(bug 27018) Added action=filerevert to revert files to an old version === Languages updated in 1.18 === diff --git a/includes/AutoLoader.php b/includes/AutoLoader.php index e1820b175a..e813f2032b 100644 --- a/includes/AutoLoader.php +++ b/includes/AutoLoader.php @@ -275,6 +275,7 @@ $wgAutoloadLocalClasses = array( 'ApiEmailUser' => 'includes/api/ApiEmailUser.php', 'ApiExpandTemplates' => 'includes/api/ApiExpandTemplates.php', 'ApiFeedWatchlist' => 'includes/api/ApiFeedWatchlist.php', + 'ApiFileRevert' => 'includes/api/ApiFileRevert.php', 'ApiFormatBase' => 'includes/api/ApiFormatBase.php', 'ApiFormatDbg' => 'includes/api/ApiFormatDbg.php', 'ApiFormatDump' => 'includes/api/ApiFormatDump.php', diff --git a/includes/Status.php b/includes/Status.php index 30cbb85179..6e44d0ba47 100644 --- a/includes/Status.php +++ b/includes/Status.php @@ -287,6 +287,24 @@ class Status { } return $result; } + + /** + * Returns a list of status messages of the given type, with message and + * params left untouched, like a sane version of getStatusArray + * + * @param $type String + * + * @return Array + */ + public function getErrorsByType( $type ) { + $result = array(); + foreach ( $this->errors as $error ) { + if ( $error['type'] === $type ) { + $result[] = $error; + } + } + return $result; + } /** * Returns true if the specified message is present as a warning or error * diff --git a/includes/api/ApiFileRevert.php b/includes/api/ApiFileRevert.php new file mode 100644 index 0000000000..9ae309a59b --- /dev/null +++ b/includes/api/ApiFileRevert.php @@ -0,0 +1,192 @@ + + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * http://www.gnu.org/copyleft/gpl.html + * + * @file + */ + +if ( !defined( 'MEDIAWIKI' ) ) { + // Eclipse helper - will be ignored in production + require_once( "ApiBase.php" ); +} + +/** + * @ingroup API + */ +class ApiFileRevert extends ApiBase { + + /** + * @var File + */ + protected $file; + protected $archiveName; + + protected $params; + + public function __construct( $main, $action ) { + parent::__construct( $main, $action ); + } + + public function execute() { + global $wgUser; + + // First check permission to upload/revert + $this->checkPermissions( $wgUser ); + + $this->params = $this->extractRequestParams(); + $this->validateParameters(); + + + $sourceUrl = $this->file->getArchiveVirtualUrl( $this->archiveName ); + $status = $this->file->upload( $sourceUrl, $this->params['comment'], $this->params['comment'] ); + + if ( $status->isGood() ) { + $result = array( 'result' => 'Success' ); + } else { + $result = array( + 'result' => 'Failure', + 'errors' => $this->getResult()->convertStatusToArray( $status ), + ); + } + + $this->getResult()->addValue( null, $this->getModuleName(), $result ); + + } + + /** + * Checks that the user has permissions to perform this revert. + * Dies with usage message on inadequate permissions. + * @param $user User The user to check. + */ + protected function checkPermissions( $user ) { + $permission = $user->isAllowed( 'edit' ) && $user->isAllowed( 'upload' ); + + if ( $permission !== true ) { + if ( !$user->isLoggedIn() ) { + $this->dieUsageMsg( array( 'mustbeloggedin', 'upload' ) ); + } else { + $this->dieUsageMsg( array( 'badaccess-groups' ) ); + } + } + } + + /** + * Validate the user parameters and set $this->archiveName and $this->file. + * Throws an error if validation fails + */ + protected function validateParameters() { + // Validate the input title + $title = Title::makeTitleSafe( NS_FILE, $this->params['filename'] ); + if ( is_null( $title ) ) { + $this->dieUsageMsg( array( 'invalidtitle', $this->params['filename'] ) ); + } + // Check if the file really exists + $this->file = wfLocalFile( $title ); + if ( !$this->file->exists() ) { + $this->dieUsageMsg( array( 'notanarticle' ) ); + } + + // Check if the archivename is valid for this file + $this->archiveName = $this->params['archivename']; + $oldFile = RepoGroup::singleton()->getLocalRepo()->newFromArchiveName( $title, $this->archiveName ); + if ( !$oldFile->exists() ) { + $this->dieUsageMsg( array( 'filerevert-badversion' ) ); + } + } + + + + public function mustBePosted() { + return true; + } + + public function isWriteMode() { + return true; + } + + public function getAllowedParams() { + return array( + 'filename' => array( + ApiBase::PARAM_TYPE => 'string', + ApiBase::PARAM_REQUIRED => true, + ), + 'comment' => array( + ApiBase::PARAM_DFLT => '', + ), + 'archivename' => array( + ApiBase::PARAM_TYPE => 'string', + ApiBase::PARAM_REQUIRED => true, + ), + 'token' => null, + ); + + } + + public function getParamDescription() { + $params = array( + 'filename' => 'Target filename', + 'token' => 'Edit token. You can get one of these through prop=info', + 'comment' => 'Upload comment', + 'archivename' => 'Archive name of the revision to revert to', + ); + + return $params; + + } + + public function getDescription() { + return array( + 'Revert a file to an old version' + ); + } + + public function getPossibleErrors() { + return array_merge( parent::getPossibleErrors(), + array( + array( 'mustbeloggedin', 'upload' ), + array( 'badaccess-groups' ), + array( 'invalidtitle', 'title' ), + array( 'notanarticle' ), + array( 'filerevert-badversion' ), + ) + ); + } + + public function needsToken() { + return true; + } + + public function getTokenSalt() { + return ''; + } + + protected function getExamples() { + return array( + 'Revert Wiki.png to the version of 20110305152740:', + ' api.php?action=filerevert&filename=Wiki.png&comment=Revert&archivename=20110305152740!Wiki.png&token=+\\', + ); + } + + public function getVersion() { + return __CLASS__ . ': $Id$'; + } +} diff --git a/includes/api/ApiMain.php b/includes/api/ApiMain.php index 7cf5386329..60820a7829 100644 --- a/includes/api/ApiMain.php +++ b/includes/api/ApiMain.php @@ -76,6 +76,7 @@ class ApiMain extends ApiBase { 'move' => 'ApiMove', 'edit' => 'ApiEditPage', 'upload' => 'ApiUpload', + 'filerevert' => 'ApiFileRevert', 'emailuser' => 'ApiEmailUser', 'watch' => 'ApiWatch', 'patrol' => 'ApiPatrol', diff --git a/includes/api/ApiResult.php b/includes/api/ApiResult.php index 90c29af679..48cd5b1218 100644 --- a/includes/api/ApiResult.php +++ b/includes/api/ApiResult.php @@ -338,6 +338,27 @@ class ApiResult extends ApiBase { global $wgContLang; $s = $wgContLang->normalize( $s ); } + + + /** + * Converts a Status object to an array suitable for addValue + * @param Status $status + * @param string $errorType + * @return array + */ + public function convertStatusToArray( $status, $errorType = 'error' ) { + if ( $status->isGood() ) { + return array(); + } + + $result = array(); + foreach ( $status->getErrorsByType( $errorType ) as $error ) { + $this->setIndexedTagName( $error['params'], 'param' ); + $result[] = $error; + } + $this->setIndexedTagName( $result, $errorType ); + return $result; + } public function execute() { ApiBase::dieDebug( __METHOD__, 'execute() is not supported on Result object' ); -- 2.20.1