(Bug 41244) Gracefully handle failure to load text blob.
authordaniel <daniel.kinzler@wikimedia.de>
Mon, 29 Oct 2012 17:38:11 +0000 (18:38 +0100)
committerdaniel <daniel.kinzler@wikimedia.de>
Sat, 10 Nov 2012 14:58:17 +0000 (15:58 +0100)
This change fixes fatal errors ocurring when Revision::loadText
returns false because of a failure to load the text blob.
Revision::getContent() should simply return null in such a case.

Change-Id: I1e13de14ff15b124b5a2e07155d368595a16fda7

includes/Revision.php
tests/phpunit/includes/RevisionStorageTest.php

index 02eec31..fd356e1 100644 (file)
@@ -52,7 +52,7 @@ class Revision implements IDBAccessObject {
        protected $mContentFormat;
 
        /**
-        * @var Content
+        * @var Content|null|bool
         */
        protected $mContent;
 
@@ -982,25 +982,30 @@ class Revision implements IDBAccessObject {
        }
 
        /**
-        * Gets the content object for the revision
+        * Gets the content object for the revision (or null on failure).
+        *
+        * Note that for mutable Content objects, each call to this method will return a
+        * fresh clone.
         *
         * @since 1.21
-        * @return Content|null
+        * @return Content|null the Revision's content, or null on failure.
         */
        protected function getContentInternal() {
                if( is_null( $this->mContent ) ) {
                        // Revision is immutable. Load on demand:
-
-                       $handler = $this->getContentHandler();
-                       $format = $this->getContentFormat();
-
                        if( is_null( $this->mText ) ) {
-                               // Load text on demand:
                                $this->mText = $this->loadText();
                        }
 
-                       $this->mContent = ( $this->mText === null || $this->mText === false ) ? null
-                               : $handler->unserializeContent( $this->mText, $format );
+                       if ( $this->mText !== null && $this->mText !== false ) {
+                               // Unserialize content
+                               $handler = $this->getContentHandler();
+                               $format = $this->getContentFormat();
+
+                               $this->mContent = $handler->unserializeContent( $this->mText, $format );
+                       } else {
+                               $this->mContent = false; // negative caching!
+                       }
                }
 
                // NOTE: copy() will return $this for immutable content objects
@@ -1399,7 +1404,11 @@ class Revision implements IDBAccessObject {
         * Lazy-load the revision's text.
         * Currently hardcoded to the 'text' table storage engine.
         *
+<<<<<<< HEAD
         * @return String|boolean the revision text, or false on failure
+=======
+        * @return String|bool the revision's text, or false on failure
+>>>>>>> (Bug 41244) Gracefully handle failure to load text blob.
         */
        protected function loadText() {
                wfProfileIn( __METHOD__ );
index fbaa34c..4fa42f3 100644 (file)
@@ -268,6 +268,25 @@ class RevisionStorageTest extends MediaWikiTestCase {
                $this->assertEquals( 'hello hello.', $rev->getText() );
        }
 
+       /**
+        * @covers Revision::getContent
+        */
+       public function testGetContent_failure()
+       {
+               $rev = new Revision( array(
+                       'page'       =>  $this->the_page->getId(),
+                       'content_model' => $this->the_page->getContentModel(),
+                       'text_id' => 123456789, // not in the test DB
+               ) );
+
+               $this->assertNull( $rev->getContent(),
+                       "getContent() should return null if the revision's text blob could not be loaded." );
+
+               //NOTE: check this twice, once for lazy initialization, and once with the cached value.
+               $this->assertNull( $rev->getContent(),
+                       "getContent() should return null if the revision's text blob could not be loaded." );
+       }
+
        /**
         * @covers Revision::getContent
         */