Localisation updates from https://translatewiki.net.
[mediawiki.git] / includes / api / ApiRollback.php
blob1c5f3ca47f96daa2c912c5cb9b0777a33bde1003
1 <?php
2 /**
3 * Copyright © 2007 Roan Kattouw <roan.kattouw@gmail.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * http://www.gnu.org/copyleft/gpl.html
20 * @file
23 namespace MediaWiki\Api;
25 use ChangeTags;
26 use MediaWiki\Deferred\DeferredUpdates;
27 use MediaWiki\MainConfigNames;
28 use MediaWiki\Page\RollbackPageFactory;
29 use MediaWiki\ParamValidator\TypeDef\UserDef;
30 use MediaWiki\Title\Title;
31 use MediaWiki\User\Options\UserOptionsLookup;
32 use MediaWiki\User\UserIdentity;
33 use MediaWiki\Watchlist\WatchlistManager;
34 use Profiler;
35 use Wikimedia\ParamValidator\ParamValidator;
37 /**
38 * @ingroup API
40 class ApiRollback extends ApiBase {
42 use ApiWatchlistTrait;
44 private RollbackPageFactory $rollbackPageFactory;
46 public function __construct(
47 ApiMain $mainModule,
48 string $moduleName,
49 RollbackPageFactory $rollbackPageFactory,
50 WatchlistManager $watchlistManager,
51 UserOptionsLookup $userOptionsLookup
52 ) {
53 parent::__construct( $mainModule, $moduleName );
54 $this->rollbackPageFactory = $rollbackPageFactory;
56 // Variables needed in ApiWatchlistTrait trait
57 $this->watchlistExpiryEnabled = $this->getConfig()->get( MainConfigNames::WatchlistExpiry );
58 $this->watchlistMaxDuration =
59 $this->getConfig()->get( MainConfigNames::WatchlistExpiryMaxDuration );
60 $this->watchlistManager = $watchlistManager;
61 $this->userOptionsLookup = $userOptionsLookup;
64 /**
65 * @var Title
67 private $mTitleObj = null;
69 /**
70 * @var UserIdentity
72 private $mUser = null;
74 public function execute() {
75 $this->useTransactionalTimeLimit();
77 $user = $this->getUser();
78 $params = $this->extractRequestParams();
80 $titleObj = $this->getRbTitle( $params );
82 // If change tagging was requested, check that the user is allowed to tag,
83 // and the tags are valid. TODO: move inside rollback command?
84 if ( $params['tags'] ) {
85 $tagStatus = ChangeTags::canAddTagsAccompanyingChange( $params['tags'], $this->getAuthority() );
86 if ( !$tagStatus->isOK() ) {
87 $this->dieStatus( $tagStatus );
91 // @TODO: remove this hack once rollback uses POST (T88044)
92 $fname = __METHOD__;
93 $trxLimits = $this->getConfig()->get( MainConfigNames::TrxProfilerLimits );
94 $trxProfiler = Profiler::instance()->getTransactionProfiler();
95 $trxProfiler->redefineExpectations( $trxLimits['POST'], $fname );
96 DeferredUpdates::addCallableUpdate( static function () use ( $trxProfiler, $trxLimits, $fname ) {
97 $trxProfiler->redefineExpectations( $trxLimits['PostSend-POST'], $fname );
98 } );
100 $rollbackResult = $this->rollbackPageFactory
101 ->newRollbackPage( $titleObj, $this->getAuthority(), $this->getRbUser( $params ) )
102 ->setSummary( $params['summary'] )
103 ->markAsBot( $params['markbot'] )
104 ->setChangeTags( $params['tags'] )
105 ->rollbackIfAllowed();
107 if ( !$rollbackResult->isGood() ) {
108 $this->dieStatus( $rollbackResult );
111 $watch = $params['watchlist'] ?? 'preferences';
112 $watchlistExpiry = $this->getExpiryFromParams( $params );
114 // Watch pages
115 $this->setWatch( $watch, $titleObj, $user, 'watchrollback', $watchlistExpiry );
117 $details = $rollbackResult->getValue();
118 $currentRevisionRecord = $details['current-revision-record'];
119 $targetRevisionRecord = $details['target-revision-record'];
121 $info = [
122 'title' => $titleObj->getPrefixedText(),
123 'pageid' => $currentRevisionRecord->getPageId(),
124 'summary' => $details['summary'],
125 'revid' => (int)$details['newid'],
126 // The revision being reverted (previously the current revision of the page)
127 'old_revid' => $currentRevisionRecord->getID(),
128 // The revision being restored (the last revision before revision(s) by the reverted user)
129 'last_revid' => $targetRevisionRecord->getID()
132 $this->getResult()->addValue( null, $this->getModuleName(), $info );
135 public function mustBePosted() {
136 return true;
139 public function isWriteMode() {
140 return true;
143 public function getAllowedParams() {
144 $params = [
145 'title' => null,
146 'pageid' => [
147 ParamValidator::PARAM_TYPE => 'integer'
149 'tags' => [
150 ParamValidator::PARAM_TYPE => 'tags',
151 ParamValidator::PARAM_ISMULTI => true,
153 'user' => [
154 ParamValidator::PARAM_TYPE => 'user',
155 UserDef::PARAM_ALLOWED_USER_TYPES => [ 'name', 'ip', 'temp', 'id', 'interwiki' ],
156 UserDef::PARAM_RETURN_OBJECT => true,
157 ParamValidator::PARAM_REQUIRED => true
159 'summary' => '',
160 'markbot' => false,
163 // Params appear in the docs in the order they are defined,
164 // which is why this is here (we want it above the token param).
165 $params += $this->getWatchlistParams();
167 return $params + [
168 'token' => [
169 // Standard definition automatically inserted
170 ApiBase::PARAM_HELP_MSG_APPEND => [ 'api-help-param-token-webui' ],
175 public function needsToken() {
176 return 'rollback';
180 * @param array $params
182 * @return UserIdentity
184 private function getRbUser( array $params ): UserIdentity {
185 if ( $this->mUser !== null ) {
186 return $this->mUser;
189 $this->mUser = $params['user'];
191 return $this->mUser;
195 * @param array $params
197 * @return Title
199 private function getRbTitle( array $params ) {
200 if ( $this->mTitleObj !== null ) {
201 return $this->mTitleObj;
204 $this->requireOnlyOneParameter( $params, 'title', 'pageid' );
206 if ( isset( $params['title'] ) ) {
207 $this->mTitleObj = Title::newFromText( $params['title'] );
208 if ( !$this->mTitleObj || $this->mTitleObj->isExternal() ) {
209 $this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $params['title'] ) ] );
211 } elseif ( isset( $params['pageid'] ) ) {
212 $this->mTitleObj = Title::newFromID( $params['pageid'] );
213 if ( !$this->mTitleObj ) {
214 $this->dieWithError( [ 'apierror-nosuchpageid', $params['pageid'] ] );
218 if ( !$this->mTitleObj->exists() ) {
219 $this->dieWithError( 'apierror-missingtitle' );
222 return $this->mTitleObj;
225 protected function getExamplesMessages() {
226 $title = Title::newMainPage()->getPrefixedText();
227 $mp = rawurlencode( $title );
229 return [
230 "action=rollback&title={$mp}&user=Example&token=123ABC" =>
231 'apihelp-rollback-example-simple',
232 "action=rollback&title={$mp}&user=192.0.2.5&" .
233 'token=123ABC&summary=Reverting%20vandalism&markbot=1' =>
234 'apihelp-rollback-example-summary',
238 public function getHelpUrls() {
239 return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Rollback';
243 /** @deprecated class alias since 1.43 */
244 class_alias( ApiRollback::class, 'ApiRollback' );