$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;
// May be overridden by revision.
$this->contentFormat = $request->getText( 'format', $this->contentFormat );
- if ( !ContentHandler::getForModelID( $this->contentModel )
- ->isSupportedFormat( $this->contentFormat )
- ) {
+ try {
+ $handler = ContentHandler::getForModelID( $this->contentModel );
+ } catch ( MWUnknownContentModelException $e ) {
+ throw new ErrorPageError(
+ 'editpage-invalidcontentmodel-title',
+ 'editpage-invalidcontentmodel-text',
+ [ $this->contentModel ]
+ );
+ }
+
+ if ( !$handler->isSupportedFormat( $this->contentFormat ) ) {
throw new ErrorPageError(
'editpage-notsupportedcontentformat-title',
'editpage-notsupportedcontentformat-text',
$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;
}
/**
$status->value = self::AS_READ_ONLY_PAGE;
return $status;
}
- if ( $wgUser->pingLimiter() || $wgUser->pingLimiter( 'linkpurge', 0 ) ) {
+ if ( $wgUser->pingLimiter() || $wgUser->pingLimiter( 'linkpurge', 0 )
+ || ( $changingContentModel && $wgUser->pingLimiter( 'editcontentmodel' ) )
+ ) {
$status->fatal( 'actionthrottledtext' );
$status->value = self::AS_RATE_LIMITED;
return $status;
* subclasses may reorganize the form.
* Note that you do not need to worry about the label's for=, it will be
* inferred by the id given to the input. You can remove them both by
- * passing array( 'id' => false ) to $userInputAttrs.
+ * passing [ 'id' => false ] to $userInputAttrs.
*
* @param string $summary The value of the summary input
* @param string $labelText The html to place inside the label
* @param array $inputAttrs Array of attrs to use on the input
* @param array $spanLabelAttrs Array of attrs to use on the span inside the label
*
- * @return array An array in the format array( $label, $input )
+ * @return array An array in the format [ $label, $input ]
*/
function getSummaryInput( $summary = "", $labelText = null,
$inputAttrs = null, $spanLabelAttrs = null
* @return bool|stdClass
*/
protected function getLastDelete() {
- $dbr = wfGetDB( DB_SLAVE );
+ $dbr = wfGetDB( DB_REPLICA );
$data = $dbr->selectRow(
[ 'logging', 'user' ],
[