MediaWiki  master
RollbackAction.php
Go to the documentation of this file.
1 <?php
26 
32 class RollbackAction extends FormAction {
33 
34  public function getName() {
35  return 'rollback';
36  }
37 
38  public function getRestriction() {
39  return 'rollback';
40  }
41 
42  protected function usesOOUI() {
43  return true;
44  }
45 
46  protected function getDescription() {
47  return '';
48  }
49 
50  public function doesWrites() {
51  return true;
52  }
53 
54  public function onSuccess() {
55  return false;
56  }
57 
58  public function onSubmit( $data ) {
59  return false;
60  }
61 
62  protected function alterForm( HTMLForm $form ) {
63  $form->setWrapperLegendMsg( 'confirm-rollback-top' );
64  $form->setSubmitTextMsg( 'confirm-rollback-button' );
65  $form->setTokenSalt( 'rollback' );
66 
67  $from = $this->getRequest()->getVal( 'from' );
68  if ( $from === null ) {
69  throw new BadRequestError( 'rollbackfailed', 'rollback-missingparam' );
70  }
71  foreach ( [ 'from', 'bot', 'hidediff', 'summary', 'token' ] as $param ) {
72  $val = $this->getRequest()->getVal( $param );
73  if ( $val !== null ) {
74  $form->addHiddenField( $param, $val );
75  }
76  }
77  }
78 
84  public function show() {
85  if ( $this->getUser()->getOption( 'showrollbackconfirmation' ) == false ||
86  $this->getRequest()->wasPosted() ) {
87  $this->handleRollbackRequest();
88  } else {
90  }
91  }
92 
93  public function handleRollbackRequest() {
95 
96  $request = $this->getRequest();
97  $user = $this->getUser();
98  $from = $request->getVal( 'from' );
99  $rev = $this->getWikiPage()->getRevisionRecord();
100  if ( $from === null ) {
101  throw new ErrorPageError( 'rollbackfailed', 'rollback-missingparam' );
102  }
103  if ( !$rev ) {
104  throw new ErrorPageError( 'rollbackfailed', 'rollback-missingrevision' );
105  }
106 
107  $revUser = $rev->getUser();
108  $userText = $revUser ? $revUser->getName() : '';
109  if ( $from !== $userText ) {
110  throw new ErrorPageError( 'rollbackfailed', 'alreadyrolled', [
111  $this->getTitle()->getPrefixedText(),
112  $from,
113  $userText
114  ] );
115  }
116 
117  $data = null;
118  $errors = $this->getWikiPage()->doRollback(
119  $from,
120  $request->getText( 'summary' ),
121  $request->getVal( 'token' ),
122  $request->getBool( 'bot' ),
123  $data,
124  $this->getUser()
125  );
126 
127  if ( in_array( [ 'actionthrottledtext' ], $errors ) ) {
128  throw new ThrottledError;
129  }
130 
131  if ( $this->hasRollbackRelatedErrors( $errors ) ) {
132  $this->getOutput()->setPageTitle( $this->msg( 'rollbackfailed' ) );
133  $errArray = $errors[0];
134  $errMsg = array_shift( $errArray );
135  $this->getOutput()->addWikiMsgArray( $errMsg, $errArray );
136 
137  if ( isset( $data['current-revision-record'] ) ) {
139  $current = $data['current-revision-record'];
140 
141  if ( $current->getComment() != null ) {
142  $this->getOutput()->addWikiMsg(
143  'editcomment',
146  $current->getComment()->text
147  )
148  )
149  );
150  }
151  }
152 
153  return;
154  }
155 
156  # NOTE: Permission errors already handled by Action::checkExecute.
157  if ( $errors == [ [ 'readonlytext' ] ] ) {
158  throw new ReadOnlyError;
159  }
160 
161  # XXX: Would be nice if ErrorPageError could take multiple errors, and/or a status object.
162  # Right now, we only show the first error
163  foreach ( $errors as $error ) {
164  throw new ErrorPageError( 'rollbackfailed', $error[0], array_slice( $error, 1 ) );
165  }
166 
168  $current = $data['current-revision-record'];
169  $target = $data['target-revision-record'];
170  $newId = $data['newid'];
171  $this->getOutput()->setPageTitle( $this->msg( 'actioncomplete' ) );
172  $this->getOutput()->setRobotPolicy( 'noindex,nofollow' );
173 
174  $old = Linker::revUserTools( $current );
175  $new = Linker::revUserTools( $target );
176 
177  $currentUser = $current->getUser( RevisionRecord::FOR_THIS_USER, $user );
178  $targetUser = $target->getUser( RevisionRecord::FOR_THIS_USER, $user );
179  $this->getOutput()->addHTML(
180  $this->msg( 'rollback-success' )
181  ->rawParams( $old, $new )
182  ->params( $currentUser ? $currentUser->getName() : '' )
183  ->params( $targetUser ? $targetUser->getName() : '' )
184  ->parseAsBlock()
185  );
186 
187  if ( $user->getBoolOption( 'watchrollback' ) ) {
188  $user->addWatch( $this->getTitle(), User::IGNORE_USER_RIGHTS );
189  }
190 
191  $this->getOutput()->returnToMain( false, $this->getTitle() );
192 
193  if ( !$request->getBool( 'hidediff', false ) &&
194  !$this->getUser()->getBoolOption( 'norollbackdiff' )
195  ) {
196  $contentModel = $current->getSlot( SlotRecord::MAIN, RevisionRecord::RAW )
197  ->getModel();
198  $contentHandler = MediaWikiServices::getInstance()
199  ->getContentHandlerFactory()
200  ->getContentHandler( $contentModel );
201  $de = $contentHandler->createDifferenceEngine(
202  $this->getContext(),
203  $current->getId(),
204  $newId,
205  false,
206  true
207  );
208  $de->showDiff( '', '' );
209  }
210  }
211 
216  private function enableTransactionalTimelimit() {
217  // If Rollbacks are made POST-only, use $this->useTransactionalTimeLimit()
219  if ( !$this->getRequest()->wasPosted() ) {
224  $fname = __METHOD__;
225  $trxLimits = $this->context->getConfig()->get( 'TrxProfilerLimits' );
226  $trxProfiler = Profiler::instance()->getTransactionProfiler();
227  $trxProfiler->redefineExpectations( $trxLimits['POST'], $fname );
228  DeferredUpdates::addCallableUpdate( function () use ( $trxProfiler, $trxLimits, $fname
229  ) {
230  $trxProfiler->redefineExpectations( $trxLimits['PostSend-POST'], $fname );
231  } );
232  }
233  }
234 
235  private function showRollbackConfirmationForm() {
236  $form = $this->getForm();
237  if ( $form->show() ) {
238  $this->onSuccess();
239  }
240  }
241 
242  protected function getFormFields() {
243  return [
244  'intro' => [
245  'type' => 'info',
246  'vertical-label' => true,
247  'raw' => true,
248  'default' => $this->msg( 'confirm-rollback-bottom' )->parse()
249  ]
250  ];
251  }
252 
253  private function hasRollbackRelatedErrors( array $errors ) {
254  return isset( $errors[0][0] ) &&
255  ( $errors[0][0] == 'alreadyrolled' ||
256  $errors[0][0] == 'cantrollback'
257  );
258  }
259 }
ReadOnlyError
Show an error when the wiki is locked/read-only and the user tries to do something that requires writ...
Definition: ReadOnlyError.php:29
RollbackAction\showRollbackConfirmationForm
showRollbackConfirmationForm()
Definition: RollbackAction.php:235
Revision\RevisionRecord
Page revision base class.
Definition: RevisionRecord.php:46
RollbackAction\alterForm
alterForm(HTMLForm $form)
Play with the HTMLForm if you need to more substantially Stable to override.
Definition: RollbackAction.php:62
Profiler\instance
static instance()
Singleton.
Definition: Profiler.php:69
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:160
Action\getRequest
getRequest()
Get the WebRequest being used for this instance.
Definition: Action.php:229
RollbackAction\show
show()
Definition: RollbackAction.php:84
RollbackAction\getDescription
getDescription()
Returns the description that goes below the <h1> tag.
Definition: RollbackAction.php:46
HTMLForm\setTokenSalt
setTokenSalt( $salt)
Set the salt for the edit token.
Definition: HTMLForm.php:1047
FormAction
An action which shows a form and does something based on the input from the form.
Definition: FormAction.php:30
RollbackAction\handleRollbackRequest
handleRollbackRequest()
Definition: RollbackAction.php:93
RollbackAction\getFormFields
getFormFields()
Get an HTMLForm descriptor array Stable to override.
Definition: RollbackAction.php:242
RollbackAction\usesOOUI
usesOOUI()
Whether the form should use OOUI Stable to override.
Definition: RollbackAction.php:42
Action\getContext
getContext()
Get the IContextSource in use here.
Definition: Action.php:215
wfTransactionalTimeLimit
wfTransactionalTimeLimit()
Set PHP's time limit to the larger of php.ini or $wgTransactionalTimeLimit.
Definition: GlobalFunctions.php:2650
HTMLForm\addHiddenField
addHiddenField( $name, $value, array $attribs=[])
Add a hidden field to the output.
Definition: HTMLForm.php:957
RollbackAction\onSubmit
onSubmit( $data)
Process the form on POST submission.
Definition: RollbackAction.php:58
ThrottledError
Show an error when the user hits a rate limit.
Definition: ThrottledError.php:28
RollbackAction\enableTransactionalTimelimit
enableTransactionalTimelimit()
Enables transactional time limit for POST and GET requests to RollbackAction.
Definition: RollbackAction.php:216
Linker\revUserTools
static revUserTools( $rev, $isPublic=false, $useParentheses=true)
Generate a user tool link cluster if the current user is allowed to view it.
Definition: Linker.php:1142
Action\getWikiPage
getWikiPage()
Get a WikiPage object.
Definition: Action.php:278
FormAction\getForm
getForm()
Get the HTMLForm to control behavior Stable to override.
Definition: FormAction.php:81
Action\getUser
getUser()
Shortcut to get the User being used for this instance.
Definition: Action.php:249
RollbackAction\hasRollbackRelatedErrors
hasRollbackRelatedErrors(array $errors)
Definition: RollbackAction.php:253
RollbackAction\getRestriction
getRestriction()
Get the permission required to perform this action.
Definition: RollbackAction.php:38
Message\rawParam
static rawParam( $raw)
Definition: Message.php:1024
Action\getTitle
getTitle()
Shortcut to get the Title object from the page.
Definition: Action.php:299
Linker\formatComment
static formatComment( $comment, $title=null, $local=false, $wikiId=null)
This function is called by all recent changes variants, by the page history, and by the user contribu...
Definition: Linker.php:1199
HTMLForm\setSubmitTextMsg
setSubmitTextMsg( $msg)
Set the text for the submit button to a message.
Definition: HTMLForm.php:1411
RollbackAction
User interface for the rollback action.
Definition: RollbackAction.php:32
Action\msg
msg( $key,... $params)
Get a Message object with context set Parameters are the same as wfMessage()
Definition: Action.php:311
HTMLForm\setWrapperLegendMsg
setWrapperLegendMsg( $msg)
Prompt the whole form to be wrapped in a "<fieldset>", with this message as its "<legend>" element.
Definition: HTMLForm.php:1598
BadRequestError
An error page that emits an HTTP 400 Bad Request status code.
Definition: BadRequestError.php:29
Action\getOutput
getOutput()
Get the OutputPage being used for this instance.
Definition: Action.php:239
RollbackAction\doesWrites
doesWrites()
Stable to override.
Definition: RollbackAction.php:50
User\IGNORE_USER_RIGHTS
const IGNORE_USER_RIGHTS
Definition: User.php:91
RollbackAction\onSuccess
onSuccess()
Do something exciting on successful processing of the form.
Definition: RollbackAction.php:54
ErrorPageError
An error page which can definitely be safely rendered using the OutputPage.
Definition: ErrorPageError.php:30
DeferredUpdates\addCallableUpdate
static addCallableUpdate( $callable, $stage=self::POSTSEND, $dbw=null)
Add a callable update.
Definition: DeferredUpdates.php:145
RollbackAction\getName
getName()
Return the name of the action this object responds to.
Definition: RollbackAction.php:34
Revision\SlotRecord
Value object representing a content slot associated with a page revision.
Definition: SlotRecord.php:40
HTMLForm
Object handling generic submission, CSRF protection, layout and other logic for UI forms in a reusabl...
Definition: HTMLForm.php:135