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