53 $out->setRobotPolicy(
'noindex,nofollow' );
54 if ( $this->
getContext()->getConfig()->
get(
'UseMediaWikiUIEverywhere' ) ) {
55 $out->addModuleStyles( [
57 'mediawiki.ui.checkbox',
65 "<div id=\"mw-read-only-warning\">\n$1\n</div>",
68 } elseif ( $this->context->getUser()->isAnon() ) {
69 if ( !$this->
getRequest()->getCheck(
'wpPreview' ) ) {
71 "<div id='mw-anon-edit-warning' class='warningbox'>\n$1\n</div>",
75 'returnto' => $this->
getTitle()->getPrefixedDBkey()
79 'returnto' => $this->
getTitle()->getPrefixedDBkey()
84 $out->wrapWikiMsg(
"<div id=\"mw-anon-preview-warning\" class=\"warningbox\">\n$1</div>",
94 $this->undoafter = $this->
getRequest()->getInt(
'undoafter' );
95 $this->undo = $this->
getRequest()->getInt(
'undo' );
97 if ( $this->undo == 0 || $this->undoafter == 0 ) {
98 throw new ErrorPageError(
'mcrundofailed',
'mcrundo-missingparam' );
101 $curRev = $this->page->getRevision();
105 $this->curRev =
$curRev->getRevisionRecord();
106 $this->cur = $this->
getRequest()->getInt(
'cur', $this->curRev->getId() );
110 parent::checkCanExecute( $user );
114 $revisionLookup = MediaWikiServices::getInstance()->getRevisionLookup();
116 $undoRev = $revisionLookup->getRevisionById( $this->undo );
117 $oldRev = $revisionLookup->getRevisionById( $this->undoafter );
119 if ( $undoRev ===
null || $oldRev ===
null ||
120 $undoRev->isDeleted( RevisionRecord::DELETED_TEXT ) ||
121 $oldRev->isDeleted( RevisionRecord::DELETED_TEXT )
133 $revisionLookup = MediaWikiServices::getInstance()->getRevisionLookup();
135 $undoRev = $revisionLookup->getRevisionById( $this->undo );
136 $oldRev = $revisionLookup->getRevisionById( $this->undoafter );
141 if ( $undoRev ===
null || $oldRev ===
null ||
142 $undoRev->isDeleted( RevisionRecord::DELETED_TEXT ) ||
143 $oldRev->isDeleted( RevisionRecord::DELETED_TEXT )
150 return MutableRevisionRecord::newFromParentRevision( $oldRev );
153 $newRev = MutableRevisionRecord::newFromParentRevision(
$curRev );
157 $rolesToMerge = array_unique( array_merge(
158 $oldRev->getSlotRoles(),
159 $undoRev->getSlotRoles(),
165 $rolesToMerge = array_intersect(
166 $rolesToMerge, $oldRev->getSlots()->getRolesWithDifferentContent( $undoRev->getSlots() )
168 if ( !$rolesToMerge ) {
174 $rolesToMerge = array_intersect(
175 $rolesToMerge, $oldRev->getSlots()->getRolesWithDifferentContent(
$curRev->
getSlots() )
177 if ( !$rolesToMerge ) {
183 $diffRoles = array_intersect(
184 $rolesToMerge, $undoRev->getSlots()->getRolesWithDifferentContent(
$curRev->
getSlots() )
186 foreach ( array_diff( $rolesToMerge, $diffRoles ) as $role ) {
187 if ( $oldRev->hasSlot( $role ) ) {
188 $newRev->inheritSlot( $oldRev->getSlot( $role, RevisionRecord::RAW ) );
190 $newRev->removeSlot( $role );
193 $rolesToMerge = $diffRoles;
204 foreach ( $rolesToMerge as $role ) {
205 if ( !$oldRev->hasSlot( $role ) || !$undoRev->hasSlot( $role ) || !
$curRev->
hasSlot( $role ) ) {
211 foreach ( $rolesToMerge as $role ) {
212 $oldContent = $oldRev->getSlot( $role, RevisionRecord::RAW )->getContent();
213 $undoContent = $undoRev->getSlot( $role, RevisionRecord::RAW )->getContent();
214 $curContent =
$curRev->
getSlot( $role, RevisionRecord::RAW )->getContent();
215 $newContent = $undoContent->getContentHandler()
216 ->getUndoContent( $curContent, $undoContent, $oldContent, $isLatest );
217 if ( !$newContent ) {
220 $newRev->setSlot( SlotRecord::newUnsaved( $role, $newContent ) );
228 if ( $newRev->hasSameContent( $this->curRev ) ) {
233 $diffEngine->setRevisions( $this->curRev, $newRev );
235 $oldtitle = $this->context->msg(
'currentrev' )->parse();
236 $newtitle = $this->context->msg(
'yourtext' )->parse();
238 if ( $this->
getRequest()->getCheck(
'wpPreview' ) ) {
242 $diffText = $diffEngine->getDiff( $oldtitle, $newtitle );
243 $diffEngine->showDiffStyle();
244 return '<div id="wikiDiff">' . $diffText .
'</div>';
255 # provide a anchor link to the form
256 $continueEditing =
'<span class="mw-continue-editing">' .
257 '[[#mw-mcrundo-form|' .
258 $this->context->getLanguage()->getArrow() .
' ' .
259 $this->context->msg(
'continue-editing' )->text() .
']]</span>';
261 $note = $this->context->msg(
'previewnote' )->plain() .
' ' . $continueEditing;
263 $parserOptions = $this->page->makeParserOptions( $this->context );
264 $parserOptions->setIsPreview(
true );
265 $parserOptions->setIsSectionPreview(
false );
266 $parserOptions->enableLimitReport();
268 $parserOutput = MediaWikiServices::getInstance()->getRevisionRenderer()
269 ->getRenderedRevision( $rev, $parserOptions, $this->context->
getUser() )
270 ->getRevisionParserOutput();
271 $previewHTML = $parserOutput->getText( [
'enableSectionEditLinks' =>
false ] );
273 $out->addParserOutputMetadata( $parserOutput );
274 if ( count( $parserOutput->getWarnings() ) ) {
275 $note .=
"\n\n" . implode(
"\n\n", $parserOutput->getWarnings() );
278 $m = $this->context->msg(
279 'content-failed-to-parse',
282 $note .=
"\n\n" . $m->parse();
286 $previewhead = Html::rawElement(
287 'div', [
'class' =>
'previewnote' ],
289 'h2', [
'id' =>
'mw-previewheader' ],
290 $this->context->msg(
'preview' )->text()
292 Html::rawElement(
'div', [
'class' =>
'warningbox' ],
293 $out->parseAsInterface( $note )
297 $pageViewLang = $this->
getTitle()->getPageViewLanguage();
298 $attribs = [
'lang' => $pageViewLang->getHtmlCode(),
'dir' => $pageViewLang->getDir(),
299 'class' =>
'mw-content-' . $pageViewLang->getDir() ];
300 $previewHTML = Html::rawElement(
'div', $attribs, $previewHTML );
302 $out->addHTML( $previewhead . $previewHTML );
308 if ( !$this->
getRequest()->getCheck(
'wpSave' ) ) {
313 $updater = $this->page->getPage()->newPageUpdater( $this->context->getUser() );
314 $curRev = $updater->grabParentRevision();
324 if ( !$newRev->hasSameContent(
$curRev ) ) {
328 foreach ( $newRev->getSlots()->getSlots() as $slot ) {
329 $updater->setSlot( $slot );
332 if ( !$newRev->hasSlot( $role ) ) {
333 $updater->removeSlot( $role );
337 $updater->setOriginalRevisionId(
false );
338 $updater->setUndidRevisionId( $this->undo );
340 $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
351 $updater->saveRevision(
356 return $updater->getStatus();
371 'vertical-label' =>
true,
373 'default' =>
function () {
380 'name' =>
'wpSummary',
381 'cssclass' =>
'mw-summary',
382 'label-message' =>
'summary',
384 'value' => $request->getVal(
'wpSummary',
'' ),
386 'spellcheck' =>
'true',
388 'summarypreview' => [
390 'label-message' =>
'summary-preview',
395 if ( $request->getCheck(
'wpSummary' ) ) {
396 $ret[
'summarypreview'][
'default'] =
Xml::tags(
'div', [
'class' =>
'mw-summary-preview' ],
400 unset( $ret[
'summarypreview'] );
409 $labelAsPublish = $this->context->getConfig()->get(
'EditSubmitButtonLabelPublish' );
411 $form->
setId(
'mw-mcrundo-form' );
414 $form->
setSubmitTextMsg( $labelAsPublish ?
'publishchanges' :
'savechanges' );
418 'name' =>
'wpPreview',
420 'label-message' =>
'showpreview',
426 'label-message' =>
'showdiff',
444 return '<div style="clear:both"></div>';