$revision = $this->mArticle->getRevisionFetched();
// Disallow editing revisions with content models different from the current one
- if ( $revision && $revision->getContentModel() !== $this->contentModel ) {
- $this->displayViewSourcePage(
- $this->getContentObject(),
- wfMessage(
- 'contentmodelediterror',
- $revision->getContentModel(),
- $this->contentModel
- )->plain()
- );
- return;
+ // Undo edits being an exception in order to allow reverting content model changes.
+ if ( $revision
+ && $revision->getContentModel() !== $this->contentModel
+ ) {
+ $prevRev = null;
+ if ( $this->undidRev ) {
+ $undidRevObj = Revision::newFromId( $this->undidRev );
+ $prevRev = $undidRevObj ? $undidRevObj->getPrevious() : null;
+ }
+ if ( !$this->undidRev
+ || !$prevRev
+ || $prevRev->getContentModel() !== $this->contentModel
+ ) {
+ $this->displayViewSourcePage(
+ $this->getContentObject(),
+ wfMessage(
+ 'contentmodelediterror',
+ $revision->getContentModel(),
+ $this->contentModel
+ )->plain()
+ );
+ return;
+ }
}
$this->isConflict = false;
$oldContent = $this->page->getContent( Revision::RAW );
$popts = ParserOptions::newFromUserAndLang( $wgUser, $wgContLang );
$newContent = $content->preSaveTransform( $this->mTitle, $wgUser, $popts );
+ if ( $newContent->getModel() !== $oldContent->getModel() ) {
+ // The undo may change content
+ // model if its reverting the top
+ // edit. This can result in
+ // mismatched content model/format.
+ $this->contentModel = $newContent->getModel();
+ $this->contentFormat = $oldrev->getContentFormat();
+ }
if ( $newContent->equals( $oldContent ) ) {
# Tell the user that the undo results in no change,
$handler = ContentHandler::getForModelID( $this->contentModel );
return $handler->makeEmptyContent();
- } else {
+ } elseif ( !$this->undidRev ) {
// Content models should always be the same since we error
- // out if they are different before this point.
+ // out if they are different before this point (in ->edit()).
+ // The exception being, during an undo, the current revision might
+ // differ from the prior revision.
$logger = LoggerFactory::getInstance( 'editpage' );
if ( $this->contentModel !== $rev->getContentModel() ) {
$logger->warning( "Overriding content model from current edit {prev} to {new}", [
] );
$this->contentFormat = $rev->getContentFormat();
}
-
- return $content;
}
+ return $content;
}
/**
try {
$this->checkModelID( $cur_content->getModel() );
$this->checkModelID( $undo_content->getModel() );
- $this->checkModelID( $undoafter_content->getModel() );
+ if ( $current->getId() !== $undo->getId() ) {
+ // If we are undoing the most recent revision,
+ // its ok to revert content model changes. However
+ // if we are undoing a revision in the middle, then
+ // doing that will be confusing.
+ $this->checkModelID( $undoafter_content->getModel() );
+ }
} catch ( MWException $e ) {
// If the revisions have different content models
// just return false