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