MediaWiki  master
ApiRollback.php
Go to the documentation of this file.
1 <?php
26 class ApiRollback extends ApiBase {
27 
31  private $mTitleObj = null;
32 
36  private $mUser = null;
37 
38  public function execute() {
40 
41  $user = $this->getUser();
42  $params = $this->extractRequestParams();
43 
44  $titleObj = $this->getRbTitle( $params );
45  $pageObj = WikiPage::factory( $titleObj );
46  $summary = $params['summary'];
47  $details = [];
48 
49  // If change tagging was requested, check that the user is allowed to tag,
50  // and the tags are valid
51  if ( $params['tags'] ) {
52  $tagStatus = ChangeTags::canAddTagsAccompanyingChange( $params['tags'], $user );
53  if ( !$tagStatus->isOK() ) {
54  $this->dieStatus( $tagStatus );
55  }
56  }
57 
58  // @TODO: remove this hack once rollback uses POST (T88044)
59  $fname = __METHOD__;
60  $trxLimits = $this->getConfig()->get( 'TrxProfilerLimits' );
61  $trxProfiler = Profiler::instance()->getTransactionProfiler();
62  $trxProfiler->redefineExpectations( $trxLimits['POST'], $fname );
63  DeferredUpdates::addCallableUpdate( function () use ( $trxProfiler, $trxLimits, $fname ) {
64  $trxProfiler->redefineExpectations( $trxLimits['PostSend-POST'], $fname );
65  } );
66 
67  $retval = $pageObj->doRollback(
68  $this->getRbUser( $params ),
69  $summary,
70  $params['token'],
71  $params['markbot'],
72  $details,
73  $user,
74  $params['tags']
75  );
76 
77  if ( $retval ) {
78  $this->dieStatus( $this->errorArrayToStatus( $retval, $user ) );
79  }
80 
81  $watch = $params['watchlist'] ?? 'preferences';
82 
83  // Watch pages
84  $this->setWatch( $watch, $titleObj, 'watchrollback' );
85 
86  $info = [
87  'title' => $titleObj->getPrefixedText(),
88  'pageid' => (int)$details['current']->getPage(),
89  'summary' => $details['summary'],
90  'revid' => (int)$details['newid'],
91  // The revision being reverted (previously the current revision of the page)
92  'old_revid' => (int)$details['current']->getID(),
93  // The revision being restored (the last revision before revision(s) by the reverted user)
94  'last_revid' => (int)$details['target']->getID()
95  ];
96 
97  $this->getResult()->addValue( null, $this->getModuleName(), $info );
98  }
99 
100  public function mustBePosted() {
101  return true;
102  }
103 
104  public function isWriteMode() {
105  return true;
106  }
107 
108  public function getAllowedParams() {
109  return [
110  'title' => null,
111  'pageid' => [
112  ApiBase::PARAM_TYPE => 'integer'
113  ],
114  'tags' => [
115  ApiBase::PARAM_TYPE => 'tags',
116  ApiBase::PARAM_ISMULTI => true,
117  ],
118  'user' => [
119  ApiBase::PARAM_TYPE => 'user',
121  ],
122  'summary' => '',
123  'markbot' => false,
124  'watchlist' => [
125  ApiBase::PARAM_DFLT => 'preferences',
127  'watch',
128  'unwatch',
129  'preferences',
130  'nochange'
131  ],
132  ],
133  'token' => [
134  // Standard definition automatically inserted
135  ApiBase::PARAM_HELP_MSG_APPEND => [ 'api-help-param-token-webui' ],
136  ],
137  ];
138  }
139 
140  public function needsToken() {
141  return 'rollback';
142  }
143 
149  private function getRbUser( array $params ) {
150  if ( $this->mUser !== null ) {
151  return $this->mUser;
152  }
153 
154  // We need to be able to revert IPs, but getCanonicalName rejects them
155  $this->mUser = User::isIP( $params['user'] )
156  ? $params['user']
157  : User::getCanonicalName( $params['user'] );
158  if ( !$this->mUser ) {
159  $this->dieWithError( [ 'apierror-invaliduser', wfEscapeWikiText( $params['user'] ) ] );
160  }
161 
162  return $this->mUser;
163  }
164 
170  private function getRbTitle( array $params ) {
171  if ( $this->mTitleObj !== null ) {
172  return $this->mTitleObj;
173  }
174 
175  $this->requireOnlyOneParameter( $params, 'title', 'pageid' );
176 
177  if ( isset( $params['title'] ) ) {
178  $this->mTitleObj = Title::newFromText( $params['title'] );
179  if ( !$this->mTitleObj || $this->mTitleObj->isExternal() ) {
180  $this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $params['title'] ) ] );
181  }
182  } elseif ( isset( $params['pageid'] ) ) {
183  $this->mTitleObj = Title::newFromID( $params['pageid'] );
184  if ( !$this->mTitleObj ) {
185  $this->dieWithError( [ 'apierror-nosuchpageid', $params['pageid'] ] );
186  }
187  }
188 
189  if ( !$this->mTitleObj->exists() ) {
190  $this->dieWithError( 'apierror-missingtitle' );
191  }
192 
193  return $this->mTitleObj;
194  }
195 
196  protected function getExamplesMessages() {
197  return [
198  'action=rollback&title=Main%20Page&user=Example&token=123ABC' =>
199  'apihelp-rollback-example-simple',
200  'action=rollback&title=Main%20Page&user=192.0.2.5&' .
201  'token=123ABC&summary=Reverting%20vandalism&markbot=1' =>
202  'apihelp-rollback-example-summary',
203  ];
204  }
205 
206  public function getHelpUrls() {
207  return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Rollback';
208  }
209 }
static factory(Title $title)
Create a WikiPage object of the appropriate class for the given title.
Definition: WikiPage.php:142
const PARAM_TYPE
(string|string[]) Either an array of allowed value strings, or a string type as described below...
Definition: ApiBase.php:94
wfEscapeWikiText( $text)
Escapes the given text so that it may be output using addWikiText() without any linking, formatting, etc.
getResult()
Get the result object.
Definition: ApiBase.php:640
static newFromID( $id, $flags=0)
Create a new Title from an article ID.
Definition: Title.php:467
static isIP( $name)
Does the string match an anonymous IP address?
Definition: User.php:909
dieStatus(StatusValue $status)
Throw an ApiUsageException based on the Status object.
Definition: ApiBase.php:2078
useTransactionalTimeLimit()
Call wfTransactionalTimeLimit() if this request was POSTed.
Definition: ApiBase.php:1863
const PARAM_DFLT
(null|boolean|integer|string) Default value of the parameter.
Definition: ApiBase.php:55
static instance()
Singleton.
Definition: Profiler.php:63
const PARAM_REQUIRED
(boolean) Is the parameter required?
Definition: ApiBase.php:118
dieWithError( $msg, $code=null, $data=null, $httpCode=null)
Abort execution with an error.
Definition: ApiBase.php:2006
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user...
Definition: ApiBase.php:761
Title $mTitleObj
Definition: ApiRollback.php:31
requireOnlyOneParameter( $params,... $required)
Die if none or more than one of a certain set of parameters is set and not false. ...
Definition: ApiBase.php:893
static getCanonicalName( $name, $validate='valid')
Given unvalidated user input, return a canonical username, or false if the username is invalid...
Definition: User.php:1157
const PARAM_HELP_MSG_APPEND
((string|array|Message)[]) Specify additional i18n messages to append to the normal message for this ...
Definition: ApiBase.php:138
static addCallableUpdate( $callable, $stage=self::POSTSEND, $dbw=null)
Add a callable update.
getRbTitle(array $params)
getRbUser(array $params)
getModuleName()
Get the name of the module being executed by this instance.
Definition: ApiBase.php:520
errorArrayToStatus(array $errors, User $user=null)
Turn an array of message keys or key+param arrays into a Status.
Definition: ApiBase.php:1817
const PARAM_ISMULTI
(boolean) Accept multiple pipe-separated values for this parameter (e.g.
Definition: ApiBase.php:58
This abstract class implements many basic API functions, and is the base of all API classes...
Definition: ApiBase.php:42
setWatch( $watch, $titleObj, $userOption=null)
Set a watch (or unwatch) based the based on a watchlist parameter.
Definition: ApiBase.php:1742
static canAddTagsAccompanyingChange(array $tags, User $user=null)
Is it OK to allow the user to apply all the specified tags at the same time as they edit/make the cha...
Definition: ChangeTags.php:521
return true
Definition: router.php:92
static newFromText( $text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
Definition: Title.php:319