MediaWiki  master
McrUndoAction.php
Go to the documentation of this file.
1 <?php
13 
30 class McrUndoAction extends FormAction {
31 
32  protected $undo = 0, $undoafter = 0, $cur = 0;
33 
35  protected $curRev = null;
36 
37  public function getName() {
38  return 'mcrundo';
39  }
40 
41  public function getDescription() {
42  return '';
43  }
44 
45  public function show() {
46  // Send a cookie so anons get talk message notifications
47  // (copied from SubmitAction)
49 
50  // Some stuff copied from EditAction
52 
53  $out = $this->getOutput();
54  $out->setRobotPolicy( 'noindex,nofollow' );
55  if ( $this->getContext()->getConfig()->get( 'UseMediaWikiUIEverywhere' ) ) {
56  $out->addModuleStyles( [
57  'mediawiki.ui.input',
58  'mediawiki.ui.checkbox',
59  ] );
60  }
61 
62  // IP warning headers copied from EditPage
63  // (should more be copied?)
64  if ( wfReadOnly() ) {
65  $out->wrapWikiMsg(
66  "<div id=\"mw-read-only-warning\">\n$1\n</div>",
67  [ 'readonlywarning', wfReadOnlyReason() ]
68  );
69  } elseif ( $this->context->getUser()->isAnon() ) {
70  if ( !$this->getRequest()->getCheck( 'wpPreview' ) ) {
71  $out->wrapWikiMsg(
72  "<div id='mw-anon-edit-warning' class='warningbox'>\n$1\n</div>",
73  [ 'anoneditwarning',
74  // Log-in link
75  SpecialPage::getTitleFor( 'Userlogin' )->getFullURL( [
76  'returnto' => $this->getTitle()->getPrefixedDBkey()
77  ] ),
78  // Sign-up link
79  SpecialPage::getTitleFor( 'CreateAccount' )->getFullURL( [
80  'returnto' => $this->getTitle()->getPrefixedDBkey()
81  ] )
82  ]
83  );
84  } else {
85  $out->wrapWikiMsg( "<div id=\"mw-anon-preview-warning\" class=\"warningbox\">\n$1</div>",
86  'anonpreviewwarning'
87  );
88  }
89  }
90 
91  parent::show();
92  }
93 
94  protected function initFromParameters() {
95  $this->undoafter = $this->getRequest()->getInt( 'undoafter' );
96  $this->undo = $this->getRequest()->getInt( 'undo' );
97 
98  if ( $this->undo == 0 || $this->undoafter == 0 ) {
99  throw new ErrorPageError( 'mcrundofailed', 'mcrundo-missingparam' );
100  }
101 
102  $curRev = $this->getWikiPage()->getRevisionRecord();
103  if ( !$curRev ) {
104  throw new ErrorPageError( 'mcrundofailed', 'nopagetext' );
105  }
106  $this->curRev = $curRev;
107  $this->cur = $this->getRequest()->getInt( 'cur', $this->curRev->getId() );
108  }
109 
110  protected function checkCanExecute( User $user ) {
111  parent::checkCanExecute( $user );
112 
113  $this->initFromParameters();
114 
115  $revisionLookup = MediaWikiServices::getInstance()->getRevisionLookup();
116 
117  $undoRev = $revisionLookup->getRevisionById( $this->undo );
118  $oldRev = $revisionLookup->getRevisionById( $this->undoafter );
119 
120  if ( $undoRev === null || $oldRev === null ||
121  $undoRev->isDeleted( RevisionRecord::DELETED_TEXT ) ||
122  $oldRev->isDeleted( RevisionRecord::DELETED_TEXT )
123  ) {
124  throw new ErrorPageError( 'mcrundofailed', 'undo-norev' );
125  }
126 
127  return true;
128  }
129 
133  private function getNewRevision() {
134  $revisionLookup = MediaWikiServices::getInstance()->getRevisionLookup();
135 
136  $undoRev = $revisionLookup->getRevisionById( $this->undo );
137  $oldRev = $revisionLookup->getRevisionById( $this->undoafter );
139 
140  $isLatest = $curRev->getId() === $undoRev->getId();
141 
142  if ( $undoRev === null || $oldRev === null ||
143  $undoRev->isDeleted( RevisionRecord::DELETED_TEXT ) ||
144  $oldRev->isDeleted( RevisionRecord::DELETED_TEXT )
145  ) {
146  throw new ErrorPageError( 'mcrundofailed', 'undo-norev' );
147  }
148 
149  if ( $isLatest ) {
150  // Short cut! Undoing the current revision means we just restore the old.
151  return MutableRevisionRecord::newFromParentRevision( $oldRev );
152  }
153 
154  $newRev = MutableRevisionRecord::newFromParentRevision( $curRev );
155 
156  // Figure out the roles that need merging by first collecting all roles
157  // and then removing the ones that don't.
158  $rolesToMerge = array_unique( array_merge(
159  $oldRev->getSlotRoles(),
160  $undoRev->getSlotRoles(),
162  ) );
163 
164  // Any roles with the same content in $oldRev and $undoRev can be
165  // inherited because undo won't change them.
166  $rolesToMerge = array_intersect(
167  $rolesToMerge, $oldRev->getSlots()->getRolesWithDifferentContent( $undoRev->getSlots() )
168  );
169  if ( !$rolesToMerge ) {
170  throw new ErrorPageError( 'mcrundofailed', 'undo-nochange' );
171  }
172 
173  // Any roles with the same content in $oldRev and $curRev were already reverted
174  // and so can be inherited.
175  $rolesToMerge = array_intersect(
176  $rolesToMerge, $oldRev->getSlots()->getRolesWithDifferentContent( $curRev->getSlots() )
177  );
178  if ( !$rolesToMerge ) {
179  throw new ErrorPageError( 'mcrundofailed', 'undo-nochange' );
180  }
181 
182  // Any roles with the same content in $undoRev and $curRev weren't
183  // changed since and so can be reverted to $oldRev.
184  $diffRoles = array_intersect(
185  $rolesToMerge, $undoRev->getSlots()->getRolesWithDifferentContent( $curRev->getSlots() )
186  );
187  foreach ( array_diff( $rolesToMerge, $diffRoles ) as $role ) {
188  if ( $oldRev->hasSlot( $role ) ) {
189  $newRev->inheritSlot( $oldRev->getSlot( $role, RevisionRecord::RAW ) );
190  } else {
191  $newRev->removeSlot( $role );
192  }
193  }
194  $rolesToMerge = $diffRoles;
195 
196  // Any slot additions or removals not handled by the above checks can't be undone.
197  // There will be only one of the three revisions missing the slot:
198  // - !old means it was added in the undone revisions and modified after.
199  // Should it be removed entirely for the undo, or should the modified version be kept?
200  // - !undo means it was removed in the undone revisions and then readded with different content.
201  // Which content is should be kept, the old or the new?
202  // - !cur means it was changed in the undone revisions and then deleted after.
203  // Did someone delete vandalized content instead of undoing (meaning we should ideally restore
204  // it), or should it stay gone?
205  foreach ( $rolesToMerge as $role ) {
206  if ( !$oldRev->hasSlot( $role ) || !$undoRev->hasSlot( $role ) || !$curRev->hasSlot( $role ) ) {
207  throw new ErrorPageError( 'mcrundofailed', 'undo-failure' );
208  }
209  }
210 
211  // Try to merge anything that's left.
212  foreach ( $rolesToMerge as $role ) {
213  $oldContent = $oldRev->getSlot( $role, RevisionRecord::RAW )->getContent();
214  $undoContent = $undoRev->getSlot( $role, RevisionRecord::RAW )->getContent();
215  $curContent = $curRev->getSlot( $role, RevisionRecord::RAW )->getContent();
216  $newContent = $undoContent->getContentHandler()
217  ->getUndoContent( $curContent, $undoContent, $oldContent, $isLatest );
218  if ( !$newContent ) {
219  throw new ErrorPageError( 'mcrundofailed', 'undo-failure' );
220  }
221  $newRev->setSlot( SlotRecord::newUnsaved( $role, $newContent ) );
222  }
223 
224  return $newRev;
225  }
226 
227  private function generateDiffOrPreview() {
228  $newRev = $this->getNewRevision();
229  if ( $newRev->hasSameContent( $this->curRev ) ) {
230  throw new ErrorPageError( 'mcrundofailed', 'undo-nochange' );
231  }
232 
233  $diffEngine = new DifferenceEngine( $this->context );
234  $diffEngine->setRevisions( $this->curRev, $newRev );
235 
236  $oldtitle = $this->context->msg( 'currentrev' )->parse();
237  $newtitle = $this->context->msg( 'yourtext' )->parse();
238 
239  if ( $this->getRequest()->getCheck( 'wpPreview' ) ) {
240  $this->showPreview( $newRev );
241  return '';
242  } else {
243  $diffText = $diffEngine->getDiff( $oldtitle, $newtitle );
244  $diffEngine->showDiffStyle();
245  return '<div id="wikiDiff">' . $diffText . '</div>';
246  }
247  }
248 
249  private function showPreview( RevisionRecord $rev ) {
250  // Mostly copied from EditPage::getPreviewText()
251  $out = $this->getOutput();
252 
253  try {
254  $previewHTML = '';
255 
256  # provide a anchor link to the form
257  $continueEditing = '<span class="mw-continue-editing">' .
258  '[[#mw-mcrundo-form|' .
259  $this->context->getLanguage()->getArrow() . ' ' .
260  $this->context->msg( 'continue-editing' )->text() . ']]</span>';
261 
262  $note = $this->context->msg( 'previewnote' )->plain() . ' ' . $continueEditing;
263 
264  $parserOptions = $this->getWikiPage()->makeParserOptions( $this->context );
265  $parserOptions->setIsPreview( true );
266  $parserOptions->setIsSectionPreview( false );
267  $parserOptions->enableLimitReport();
268 
269  $parserOutput = MediaWikiServices::getInstance()->getRevisionRenderer()
270  ->getRenderedRevision( $rev, $parserOptions, $this->context->getUser() )
271  ->getRevisionParserOutput();
272  $previewHTML = $parserOutput->getText( [ 'enableSectionEditLinks' => false ] );
273 
274  $out->addParserOutputMetadata( $parserOutput );
275  if ( count( $parserOutput->getWarnings() ) ) {
276  $note .= "\n\n" . implode( "\n\n", $parserOutput->getWarnings() );
277  }
278  } catch ( MWContentSerializationException $ex ) {
279  $m = $this->context->msg(
280  'content-failed-to-parse',
281  $ex->getMessage()
282  );
283  $note .= "\n\n" . $m->parse();
284  $previewHTML = '';
285  }
286 
287  $previewhead = Html::rawElement(
288  'div', [ 'class' => 'previewnote' ],
290  'h2', [ 'id' => 'mw-previewheader' ],
291  $this->context->msg( 'preview' )->text()
292  ) .
293  Html::rawElement( 'div', [ 'class' => 'warningbox' ],
294  $out->parseAsInterface( $note )
295  )
296  );
297 
298  $pageViewLang = $this->getTitle()->getPageViewLanguage();
299  $attribs = [ 'lang' => $pageViewLang->getHtmlCode(), 'dir' => $pageViewLang->getDir(),
300  'class' => 'mw-content-' . $pageViewLang->getDir() ];
301  $previewHTML = Html::rawElement( 'div', $attribs, $previewHTML );
302 
303  $out->addHTML( $previewhead . $previewHTML );
304  }
305 
306  public function onSubmit( $data ) {
307  global $wgUseRCPatrol;
308 
309  if ( !$this->getRequest()->getCheck( 'wpSave' ) ) {
310  // Diff or preview
311  return false;
312  }
313 
314  $updater = $this->getWikiPage()->newPageUpdater( $this->context->getUser() );
315  $curRev = $updater->grabParentRevision();
316  if ( !$curRev ) {
317  throw new ErrorPageError( 'mcrundofailed', 'nopagetext' );
318  }
319 
320  if ( $this->cur !== $curRev->getId() ) {
321  return Status::newFatal( 'mcrundo-changed' );
322  }
323 
324  $newRev = $this->getNewRevision();
325  if ( !$newRev->hasSameContent( $curRev ) ) {
326  $revisionStore = MediaWikiServices::getInstance()->getRevisionStore();
327 
328  // Copy new slots into the PageUpdater, and remove any removed slots.
329  // TODO: This interface is awful, there should be a way to just pass $newRev.
330  // TODO: MCR: test this once we can store multiple slots
331  foreach ( $newRev->getSlots()->getSlots() as $slot ) {
332  $updater->setSlot( $slot );
333  }
334  foreach ( $curRev->getSlotRoles() as $role ) {
335  if ( !$newRev->hasSlot( $role ) ) {
336  $updater->removeSlot( $role );
337  }
338  }
339 
340  // The revision we revert to is specified by the undoafter param.
341  // $oldRev is not null, we check this and more in getNewRevision()
342  $oldRev = $revisionStore->getRevisionById( $this->undoafter );
343  $oldestRevertedRev = $revisionStore->getNextRevision( $oldRev );
344  if ( $oldestRevertedRev ) {
345  $updater->markAsRevert(
346  EditResult::REVERT_UNDO,
347  $oldestRevertedRev->getId(),
348  $this->undo
349  );
350  } else {
351  // fallback in case something goes wrong
352  $updater->markAsRevert( EditResult::REVERT_UNDO, $this->undo );
353  }
354  // Set the original revision ID if this is an exact revert.
355  if ( $oldRev->hasSameContent( $newRev ) ) {
356  $updater->setOriginalRevisionId( $oldRev->getId() );
357  }
358 
359  $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
360 
361  // TODO: Ugh.
362  if ( $wgUseRCPatrol && $permissionManager->userCan(
363  'autopatrol',
364  $this->getUser(),
365  $this->getTitle() )
366  ) {
367  $updater->setRcPatrolStatus( RecentChange::PRC_AUTOPATROLLED );
368  }
369 
370  $updater->saveRevision(
371  CommentStoreComment::newUnsavedComment( trim( $this->getRequest()->getVal( 'wpSummary' ) ) ),
373  );
374 
375  return $updater->getStatus();
376  }
377 
378  return Status::newGood();
379  }
380 
381  protected function usesOOUI() {
382  return true;
383  }
384 
385  protected function getFormFields() {
386  $request = $this->getRequest();
387  $ret = [
388  'diff' => [
389  'type' => 'info',
390  'vertical-label' => true,
391  'raw' => true,
392  'default' => function () {
393  return $this->generateDiffOrPreview();
394  }
395  ],
396  'summary' => [
397  'type' => 'text',
398  'id' => 'wpSummary',
399  'name' => 'wpSummary',
400  'cssclass' => 'mw-summary',
401  'label-message' => 'summary',
403  'value' => $request->getVal( 'wpSummary', '' ),
404  'size' => 60,
405  'spellcheck' => 'true',
406  ],
407  'summarypreview' => [
408  'type' => 'info',
409  'label-message' => 'summary-preview',
410  'raw' => true,
411  ],
412  ];
413 
414  if ( $request->getCheck( 'wpSummary' ) ) {
415  $ret['summarypreview']['default'] = Xml::tags( 'div', [ 'class' => 'mw-summary-preview' ],
416  Linker::commentBlock( trim( $request->getVal( 'wpSummary' ) ), $this->getTitle(), false )
417  );
418  } else {
419  unset( $ret['summarypreview'] );
420  }
421 
422  return $ret;
423  }
424 
425  protected function alterForm( HTMLForm $form ) {
426  $form->setWrapperLegendMsg( 'confirm-mcrundo-title' );
427 
428  $labelAsPublish = $this->context->getConfig()->get( 'EditSubmitButtonLabelPublish' );
429 
430  $form->setId( 'mw-mcrundo-form' );
431  $form->setSubmitName( 'wpSave' );
432  $form->setSubmitTooltip( $labelAsPublish ? 'publish' : 'save' );
433  $form->setSubmitTextMsg( $labelAsPublish ? 'publishchanges' : 'savechanges' );
434  $form->showCancel( true );
435  $form->setCancelTarget( $this->getTitle() );
436  $form->addButton( [
437  'name' => 'wpPreview',
438  'value' => '1',
439  'label-message' => 'showpreview',
440  'attribs' => Linker::tooltipAndAccesskeyAttribs( 'preview' ),
441  ] );
442  $form->addButton( [
443  'name' => 'wpDiff',
444  'value' => '1',
445  'label-message' => 'showdiff',
446  'attribs' => Linker::tooltipAndAccesskeyAttribs( 'diff' ),
447  ] );
448 
449  $this->addStatePropagationFields( $form );
450  }
451 
452  protected function addStatePropagationFields( HTMLForm $form ) {
453  $form->addHiddenField( 'undo', $this->undo );
454  $form->addHiddenField( 'undoafter', $this->undoafter );
455  $form->addHiddenField( 'cur', $this->curRev->getId() );
456  }
457 
458  public function onSuccess() {
459  $this->getOutput()->redirect( $this->getTitle()->getFullURL() );
460  }
461 
462  protected function preText() {
463  return '<div style="clear:both"></div>';
464  }
465 }
McrUndoAction\$undoafter
$undoafter
Definition: McrUndoAction.php:32
CommentStoreComment\newUnsavedComment
static newUnsavedComment( $comment, array $data=null)
Create a new, unsaved CommentStoreComment.
Definition: CommentStoreComment.php:67
McrUndoAction\generateDiffOrPreview
generateDiffOrPreview()
Definition: McrUndoAction.php:227
Revision\RevisionRecord
Page revision base class.
Definition: RevisionRecord.php:46
StatusValue\newFatal
static newFatal( $message,... $parameters)
Factory function for fatal errors.
Definition: StatusValue.php:70
HTMLForm\setSubmitName
setSubmitName( $name)
Definition: HTMLForm.php:1436
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:165
Action\getRequest
getRequest()
Get the WebRequest being used for this instance.
Definition: Action.php:229
HTMLForm\setSubmitTooltip
setSubmitTooltip( $name)
Definition: HTMLForm.php:1447
McrUndoAction\preText
preText()
Add pre- or post-text to the form Stable to override.
Definition: McrUndoAction.php:462
McrUndoAction\show
show()
The basic pattern for actions is to display some sort of HTMLForm UI, maybe with some stuff underneat...
Definition: McrUndoAction.php:45
HTMLForm\showCancel
showCancel( $show=true)
Show a cancel button (or prevent it).
Definition: HTMLForm.php:1510
HTMLForm\setCancelTarget
setCancelTarget( $target)
Sets the target where the user is redirected to after clicking cancel.
Definition: HTMLForm.php:1521
FormAction
An action which shows a form and does something based on the input from the form.
Definition: FormAction.php:30
wfReadOnly
wfReadOnly()
Check whether the wiki is in read-only mode.
Definition: GlobalFunctions.php:1126
Revision\RevisionRecord\getSlot
getSlot( $role, $audience=self::FOR_PUBLIC, User $user=null)
Returns meta-data for the given slot.
Definition: RevisionRecord.php:183
McrUndoAction\alterForm
alterForm(HTMLForm $form)
Play with the HTMLForm if you need to more substantially Stable to override.
Definition: McrUndoAction.php:425
SpecialPage\getTitleFor
static getTitleFor( $name, $subpage=false, $fragment='')
Get a localised Title object for a specified special page name If you don't need a full Title object,...
Definition: SpecialPage.php:106
McrUndoAction\getFormFields
getFormFields()
Get an HTMLForm descriptor array Stable to override.
Definition: McrUndoAction.php:385
Revision\RevisionRecord\hasSlot
hasSlot( $role)
Returns whether the given slot is defined in this revision.
Definition: RevisionRecord.php:200
McrUndoAction
Temporary action for MCR undos.
Definition: McrUndoAction.php:30
$wgUseRCPatrol
$wgUseRCPatrol
Use RC Patrolling to check for vandalism (from recent changes and watchlists) New pages and new files...
Definition: DefaultSettings.php:7355
Linker\tooltipAndAccesskeyAttribs
static tooltipAndAccesskeyAttribs( $name, array $msgParams=[], $options=null)
Returns the attributes for the tooltip and access key.
Definition: Linker.php:2294
Action\getContext
getContext()
Get the IContextSource in use here.
Definition: Action.php:215
McrUndoAction\getDescription
getDescription()
Returns the description that goes below the <h1> tag.
Definition: McrUndoAction.php:41
HTMLForm\addButton
addButton( $data)
Add a button to the form.
Definition: HTMLForm.php:1007
McrUndoAction\addStatePropagationFields
addStatePropagationFields(HTMLForm $form)
Definition: McrUndoAction.php:452
Revision\RevisionRecord\getUser
getUser( $audience=self::FOR_PUBLIC, User $user=null)
Fetch revision's author's user identity, if it's available to the specified audience.
Definition: RevisionRecord.php:363
HTMLForm\addHiddenField
addHiddenField( $name, $value, array $attribs=[])
Add a hidden field to the output.
Definition: HTMLForm.php:958
McrUndoAction\$cur
$cur
Definition: McrUndoAction.php:32
MWContentSerializationException
Exception representing a failure to serialize or unserialize a content object.
Definition: MWContentSerializationException.php:8
McrUndoAction\usesOOUI
usesOOUI()
Whether the form should use OOUI Stable to override.
Definition: McrUndoAction.php:381
McrUndoAction\getNewRevision
getNewRevision()
Definition: McrUndoAction.php:133
McrUndoAction\$curRev
RevisionRecord null $curRev
Definition: McrUndoAction.php:35
McrUndoAction\getName
getName()
Return the name of the action this object responds to.
Definition: McrUndoAction.php:37
Revision\RevisionRecord\getSlotRoles
getSlotRoles()
Returns the slot names (roles) of all slots present in this revision.
Definition: RevisionRecord.php:210
Action\getWikiPage
getWikiPage()
Get a WikiPage object.
Definition: Action.php:278
MediaWiki\Storage\EditResult
Object for storing information about the effects of an edit.
Definition: EditResult.php:38
Revision\RevisionRecord\getId
getId()
Get revision ID.
Definition: RevisionRecord.php:271
MediaWiki\Session\SessionManager\getGlobalSession
static getGlobalSession()
If PHP's session_id() has been set, returns that session.
Definition: SessionManager.php:113
EDIT_UPDATE
const EDIT_UPDATE
Definition: Defines.php:142
Linker\commentBlock
static commentBlock( $comment, $title=null, $local=false, $wikiId=null, $useParentheses=true)
Wrap a comment in standard punctuation and formatting if it's non-empty, otherwise return empty strin...
Definition: Linker.php:1574
StatusValue\newGood
static newGood( $value=null)
Factory function for good results.
Definition: StatusValue.php:82
HTMLForm\setId
setId( $id)
Definition: HTMLForm.php:1546
Revision\MutableRevisionRecord
Definition: MutableRevisionRecord.php:45
Xml\tags
static tags( $element, $attribs, $contents)
Same as Xml::element(), but does not escape contents.
Definition: Xml.php:130
Action\getTitle
getTitle()
Shortcut to get the Title object from the page.
Definition: Action.php:299
RecentChange\PRC_AUTOPATROLLED
const PRC_AUTOPATROLLED
Definition: RecentChange.php:84
Revision\RevisionRecord\getSlots
getSlots()
Returns the slots defined for this revision.
Definition: RevisionRecord.php:225
CommentStore\COMMENT_CHARACTER_LIMIT
const COMMENT_CHARACTER_LIMIT
Maximum length of a comment in UTF-8 characters.
Definition: CommentStore.php:48
HTMLForm\setSubmitTextMsg
setSubmitTextMsg( $msg)
Set the text for the submit button to a message.
Definition: HTMLForm.php:1414
EDIT_AUTOSUMMARY
const EDIT_AUTOSUMMARY
Definition: Defines.php:147
wfReadOnlyReason
wfReadOnlyReason()
Check if the site is in read-only mode and return the message if so.
Definition: GlobalFunctions.php:1139
McrUndoAction\onSubmit
onSubmit( $data)
Process the form on POST submission.
Definition: McrUndoAction.php:306
HTMLForm\setWrapperLegendMsg
setWrapperLegendMsg( $msg)
Prompt the whole form to be wrapped in a "<fieldset>", with this message as its "<legend>" element.
Definition: HTMLForm.php:1601
McrUndoAction\checkCanExecute
checkCanExecute(User $user)
Checks if the given user (identified by an object) can perform this action.
Definition: McrUndoAction.php:110
McrUndoAction\initFromParameters
initFromParameters()
Definition: McrUndoAction.php:94
Html\rawElement
static rawElement( $element, $attribs=[], $contents='')
Returns an HTML element in a string.
Definition: Html.php:212
DifferenceEngine
DifferenceEngine is responsible for rendering the difference between two revisions as HTML.
Definition: DifferenceEngine.php:57
McrUndoAction\showPreview
showPreview(RevisionRecord $rev)
Definition: McrUndoAction.php:249
Action\getOutput
getOutput()
Get the OutputPage being used for this instance.
Definition: Action.php:239
Action\useTransactionalTimeLimit
useTransactionalTimeLimit()
Call wfTransactionalTimeLimit() if this request was POSTed.
Definition: Action.php:538
McrUndoAction\$undo
$undo
Definition: McrUndoAction.php:32
McrUndoAction\onSuccess
onSuccess()
Do something exciting on successful processing of the form.
Definition: McrUndoAction.php:458
Html\element
static element( $element, $attribs=[], $contents='')
Identical to rawElement(), but HTML-escapes $contents (like Xml::element()).
Definition: Html.php:234
ErrorPageError
An error page which can definitely be safely rendered using the OutputPage.
Definition: ErrorPageError.php:30
User
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition: User.php:56
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