Added consistency checks to Revision.
authordaniel <daniel.kinzler@wikimedia.de>
Thu, 7 Jun 2012 15:35:37 +0000 (17:35 +0200)
committerdaniel <daniel.kinzler@wikimedia.de>
Thu, 7 Jun 2012 15:35:37 +0000 (17:35 +0200)
This is to avoid corruption arising from confusion about which revision
uses which data model and format.

includes/Content.php
includes/Revision.php

index 490bb8c..75fe391 100644 (file)
@@ -443,6 +443,8 @@ abstract class Content {
        # FUTURE: MultipartMultipart < WikipageContent (Main + Links + X)
        # FUTURE: LinksContent < LanguageLinksContent, CategoriesContent
 
+// @TODO: add support for ar_content_format, ar_content_model, rev_content_format, rev_content_model to API
+
 /**
  * Content object implementation for representing flat text.
  *
index 1ffbc5c..84826c9 100644 (file)
@@ -634,7 +634,7 @@ class Revision {
                if( isset( $this->mTitle ) ) {
                        return $this->mTitle;
                }
-               if( !is_null( $this->mId ) ) { //rev_id is defined as NOT NULL
+               if( !is_null( $this->mId ) ) { //rev_id is defined as NOT NULL, but this revision may not yet have been inserted.
                        $dbr = wfGetDB( DB_SLAVE );
                        $row = $dbr->selectRow(
                                array( 'page', 'revision' ),
@@ -646,6 +646,8 @@ class Revision {
                                $this->mTitle = Title::newFromRow( $row );
                        }
                }
+
+               //@todo: as a last resort, perhaps load from page table, if $this->mPage is given?!
                return $this->mTitle;
        }
 
@@ -1225,6 +1227,8 @@ class Revision {
                        $row[ 'rev_content_format' ] = $this->getContentFormat();
                }
 
+               $this->checkContentModel();
+
                $dbw->insert( 'revision', $row, __METHOD__ );
 
                $this->mId = !is_null( $rev_id ) ? $rev_id : $dbw->insertId();
@@ -1235,6 +1239,57 @@ class Revision {
                return $this->mId;
        }
 
+       protected function checkContentModel() {
+               global $wgContentHandlerUseDB;
+
+               $title = $this->getTitle(); //note: returns null for revisions that have not yet been inserted.
+
+               $model = $this->getContentModel();
+               $format = $this->getContentFormat();
+               $handler = $this->getContentHandler();
+
+               if ( !$handler->isSupportedFormat( $format ) ) {
+                       $t = $title->getPrefixedDBkey();
+                       $modelName = ContentHandler::getContentModelName( $model );
+                       $formatName = ContentHandler::getContentFormatMimeType( $format );
+
+                       throw new MWException( "Can't use format #$format ($formatName) with content model #$model ($modelName) on $t" );
+               }
+
+               if ( !$wgContentHandlerUseDB && $title ) {
+                       // if $wgContentHandlerUseDB is not set, all revisions must use the default content model and format.
+
+                       $defaultModel = ContentHandler::getDefaultModelFor( $title );
+                       $defaultHandler = ContentHandler::getForModelID( $defaultModel );
+                       $defaultFormat = $defaultHandler->getDefaultFormat();
+
+                       if ( $this->getContentModel() != $defaultModel ) {
+                               $defaultModelName = ContentHandler::getContentModelName( $defaultModel );
+                               $modelName = ContentHandler::getContentModelName( $model );
+                               $t = $title->getPrefixedDBkey();
+
+                               throw new MWException( "Can't save non-default content model with \$wgContentHandlerUseDB disabled: model is #$model ($modelName), default for $t is #$defaultModel ($defaultModelName)" );
+                       }
+
+                       if ( $this->getContentFormat() != $defaultFormat ) {
+                               $defaultFormatName = ContentHandler::getContentFormatMimeType( $defaultFormat );
+                               $formatName = ContentHandler::getContentFormatMimeType( $format );
+                               $t = $title->getPrefixedDBkey();
+
+                               throw new MWException( "Can't use non-default content format with \$wgContentHandlerUseDB disabled: format is #$format ($formatName), default for $t is #$defaultFormat ($defaultFormatName)" );
+                       }
+               }
+
+               $content = $this->getContent( Revision::RAW );
+
+               if ( !$content->isValid() ) {
+                       $t = $title->getPrefixedDBkey();
+                       $modelName = ContentHandler::getContentModelName( $model );
+
+                       throw new MWException( "Content of $t is not valid! Content model is #$model ($modelName)" );
+               }
+       }
+
        /**
         * Get the base 36 SHA-1 value for a string of text
         * @param $text String