MediaWiki master
ApiRollback.php
Go to the documentation of this file.
1<?php
9namespace MediaWiki\Api;
10
23
27class ApiRollback extends ApiBase {
28
30
31 private RollbackPageFactory $rollbackPageFactory;
32
33 public function __construct(
34 ApiMain $mainModule,
35 string $moduleName,
36 RollbackPageFactory $rollbackPageFactory,
37 WatchlistManager $watchlistManager,
38 WatchedItemStoreInterface $watchedItemStore,
39 UserOptionsLookup $userOptionsLookup
40 ) {
41 parent::__construct( $mainModule, $moduleName );
42 $this->rollbackPageFactory = $rollbackPageFactory;
43
44 // Variables needed in ApiWatchlistTrait trait
45 $this->watchlistExpiryEnabled = $this->getConfig()->get( MainConfigNames::WatchlistExpiry );
46 $this->watchlistMaxDuration =
48 $this->watchlistManager = $watchlistManager;
49 $this->watchedItemStore = $watchedItemStore;
50 $this->userOptionsLookup = $userOptionsLookup;
51 }
52
56 private $mTitleObj = null;
57
61 private $mUser = null;
62
63 public function execute() {
65
66 $user = $this->getUser();
67 $params = $this->extractRequestParams();
68
69 $titleObj = $this->getRbTitle( $params );
70
71 // If change tagging was requested, check that the user is allowed to tag,
72 // and the tags are valid. TODO: move inside rollback command?
73 if ( $params['tags'] ) {
74 $tagStatus = ChangeTags::canAddTagsAccompanyingChange( $params['tags'], $this->getAuthority() );
75 if ( !$tagStatus->isOK() ) {
76 $this->dieStatus( $tagStatus );
77 }
78 }
79
80 // @TODO: remove this hack once rollback uses POST (T88044)
81 $fname = __METHOD__;
82 $trxLimits = $this->getConfig()->get( MainConfigNames::TrxProfilerLimits );
83 $trxProfiler = Profiler::instance()->getTransactionProfiler();
84 $trxProfiler->redefineExpectations( $trxLimits['POST'], $fname );
85 DeferredUpdates::addCallableUpdate( static function () use ( $trxProfiler, $trxLimits, $fname ) {
86 $trxProfiler->redefineExpectations( $trxLimits['PostSend-POST'], $fname );
87 } );
88
89 $rollbackResult = $this->rollbackPageFactory
90 ->newRollbackPage( $titleObj, $this->getAuthority(), $this->getRbUser( $params ) )
91 ->setSummary( $params['summary'] )
92 ->markAsBot( $params['markbot'] )
93 ->setChangeTags( $params['tags'] )
94 ->rollbackIfAllowed();
95
96 if ( !$rollbackResult->isGood() ) {
97 $this->dieStatus( $rollbackResult );
98 }
99
100 $watch = $params['watchlist'] ?? 'preferences';
101 $watchlistExpiry = $this->getExpiryFromParams( $params, $titleObj, $user, 'watchrollback-expiry' );
102
103 // Watch pages
104 $this->setWatch( $watch, $titleObj, $user, 'watchrollback', $watchlistExpiry );
105
106 $details = $rollbackResult->getValue();
107 $currentRevisionRecord = $details['current-revision-record'];
108 $targetRevisionRecord = $details['target-revision-record'];
109
110 $info = [
111 'title' => $titleObj->getPrefixedText(),
112 'pageid' => $currentRevisionRecord->getPageId(),
113 'summary' => $details['summary'],
114 'revid' => (int)$details['newid'],
115 // The revision being reverted (previously the current revision of the page)
116 'old_revid' => $currentRevisionRecord->getID(),
117 // The revision being restored (the last revision before revision(s) by the reverted user)
118 'last_revid' => $targetRevisionRecord->getID()
119 ];
120
121 $this->getResult()->addValue( null, $this->getModuleName(), $info );
122 }
123
125 public function mustBePosted() {
126 return true;
127 }
128
130 public function isWriteMode() {
131 return true;
132 }
133
135 public function getAllowedParams() {
136 $params = [
137 'title' => null,
138 'pageid' => [
139 ParamValidator::PARAM_TYPE => 'integer'
140 ],
141 'tags' => [
142 ParamValidator::PARAM_TYPE => 'tags',
143 ParamValidator::PARAM_ISMULTI => true,
144 ],
145 'user' => [
146 ParamValidator::PARAM_TYPE => 'user',
147 UserDef::PARAM_ALLOWED_USER_TYPES => [ 'name', 'ip', 'temp', 'id', 'interwiki' ],
148 UserDef::PARAM_RETURN_OBJECT => true,
149 ParamValidator::PARAM_REQUIRED => true
150 ],
151 'summary' => '',
152 'markbot' => false,
153 ];
154
155 // Params appear in the docs in the order they are defined,
156 // which is why this is here (we want it above the token param).
157 $params += $this->getWatchlistParams();
158
159 return $params + [
160 'token' => [
161 // Standard definition automatically inserted
162 ApiBase::PARAM_HELP_MSG_APPEND => [ 'api-help-param-token-webui' ],
163 ],
164 ];
165 }
166
168 public function needsToken() {
169 return 'rollback';
170 }
171
172 private function getRbUser( array $params ): UserIdentity {
173 if ( $this->mUser !== null ) {
174 return $this->mUser;
175 }
176
177 $this->mUser = $params['user'];
178
179 return $this->mUser;
180 }
181
187 private function getRbTitle( array $params ) {
188 if ( $this->mTitleObj !== null ) {
189 return $this->mTitleObj;
190 }
191
192 $this->requireOnlyOneParameter( $params, 'title', 'pageid' );
193
194 if ( isset( $params['title'] ) ) {
195 $this->mTitleObj = Title::newFromText( $params['title'] );
196 if ( !$this->mTitleObj || $this->mTitleObj->isExternal() ) {
197 $this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $params['title'] ) ] );
198 }
199 } elseif ( isset( $params['pageid'] ) ) {
200 $this->mTitleObj = Title::newFromID( $params['pageid'] );
201 if ( !$this->mTitleObj ) {
202 $this->dieWithError( [ 'apierror-nosuchpageid', $params['pageid'] ] );
203 }
204 }
205
206 if ( !$this->mTitleObj->exists() ) {
207 $this->dieWithError( 'apierror-missingtitle' );
208 }
209
210 return $this->mTitleObj;
211 }
212
214 protected function getExamplesMessages() {
215 $title = Title::newMainPage()->getPrefixedText();
216 $mp = rawurlencode( $title );
217
218 return [
219 "action=rollback&title={$mp}&user=Example&token=123ABC" =>
220 'apihelp-rollback-example-simple',
221 "action=rollback&title={$mp}&user=192.0.2.5&" .
222 'token=123ABC&summary=Reverting%20vandalism&markbot=1' =>
223 'apihelp-rollback-example-summary',
224 ];
225 }
226
228 public function getHelpUrls() {
229 return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Rollback';
230 }
231}
232
234class_alias( ApiRollback::class, 'ApiRollback' );
wfEscapeWikiText( $input)
Escapes the given text so that it may be output using addWikiText() without any linking,...
if(!defined('MW_SETUP_CALLBACK'))
Definition WebStart.php:69
This abstract class implements many basic API functions, and is the base of all API classes.
Definition ApiBase.php:61
getModuleName()
Get the name of the module being executed by this instance.
Definition ApiBase.php:543
useTransactionalTimeLimit()
Call wfTransactionalTimeLimit() if this request was POSTed.
Definition ApiBase.php:1355
getResult()
Get the result object.
Definition ApiBase.php:682
const PARAM_HELP_MSG_APPEND
((string|array|Message)[]) Specify additional i18n messages to append to the normal message for this ...
Definition ApiBase.php:175
dieStatus(StatusValue $status)
Throw an ApiUsageException based on the Status object.
Definition ApiBase.php:1558
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition ApiBase.php:823
This is the main API class, used for both external and internal processing.
Definition ApiMain.php:67
execute()
Evaluates the parameters, performs the requested query, and sets up the result.
__construct(ApiMain $mainModule, string $moduleName, RollbackPageFactory $rollbackPageFactory, WatchlistManager $watchlistManager, WatchedItemStoreInterface $watchedItemStore, UserOptionsLookup $userOptionsLookup)
getHelpUrls()
Return links to more detailed help pages about the module.1.25, returning boolean false is deprecated...
isWriteMode()
Indicates whether this module requires write access to the wiki.API modules must override this method...
mustBePosted()
Indicates whether this module must be called with a POST request.Implementations of this method must ...
getExamplesMessages()
Returns usage examples for this module.Return value has query strings as keys, with values being eith...
getAllowedParams()
Returns an array of allowed parameters (parameter name) => (default value) or (parameter name) => (ar...
needsToken()
Returns the token type this module requires in order to execute.Modules are strongly encouraged to us...
Recent changes tagging.
Defer callable updates to run later in the PHP process.
A class containing constants representing the names of configuration variables.
const TrxProfilerLimits
Name constant for the TrxProfilerLimits setting, for use with Config::get()
const WatchlistExpiry
Name constant for the WatchlistExpiry setting, for use with Config::get()
const WatchlistExpiryMaxDuration
Name constant for the WatchlistExpiryMaxDuration setting, for use with Config::get()
Type definition for user types.
Definition UserDef.php:27
Profiler base class that defines the interface and some shared functionality.
Definition Profiler.php:25
Represents a title within MediaWiki.
Definition Title.php:69
Provides access to user options.
Service for formatting and validating API parameters.
trait ApiWatchlistTrait
An ApiWatchlistTrait adds class properties and convenience methods for APIs that allow you to watch a...
Service for page rollback actions.
Interface for objects representing user identity.
setWatch(string $watch, PageIdentity $page, User $user, ?string $userOption=null, ?string $expiry=null)
Set a watch (or unwatch) based the based on a watchlist parameter.
getWatchlistParams(array $watchOptions=[])
Get additional allow params specific to watchlisting.
getExpiryFromParams(array $params, ?PageIdentity $page=null, ?UserIdentity $user=null, string $userOption='watchdefault-expiry')
Get formatted expiry from the given parameters.