Beware that getContent() may return null
[lhc/web/wiklou.git] / includes / Revision.php
index c39183b..df02b16 100644 (file)
  */
 class Revision implements IDBAccessObject {
        protected $mId;
+
+       /**
+        * @var int|null
+        */
        protected $mPage;
        protected $mUserText;
        protected $mOrigUserText;
@@ -38,11 +42,23 @@ class Revision implements IDBAccessObject {
        protected $mComment;
        protected $mText;
        protected $mTextRow;
+
+       /**
+        * @var null|Title
+        */
        protected $mTitle;
        protected $mCurrent;
        protected $mContentModel;
        protected $mContentFormat;
+
+       /**
+        * @var Content
+        */
        protected $mContent;
+
+       /**
+        * @var null|ContentHandler
+        */
        protected $mContentHandler;
 
        // Revision deletion constants
@@ -108,7 +124,7 @@ class Revision implements IDBAccessObject {
         * Returns null if no such revision can be found.
         *
         * $flags include:
-        *      Revision::READ_LATEST  : Select the data from the master
+        *      Revision::READ_LATEST  : Select the data from the master (since 1.20)
         *      Revision::READ_LOCKING : Select & lock the data from the master
         *
         * @param $revId Integer
@@ -162,6 +178,13 @@ class Revision implements IDBAccessObject {
                        unset( $attribs['content_format'] );
                }
 
+               if ( !isset( $attribs['title'] )
+                       && isset( $row->ar_namespace )
+                       && isset( $row->ar_title ) ) {
+
+                       $attribs['title'] = Title::makeTitle( $row->ar_namespace, $row->ar_title );
+               }
+
                if ( isset( $row->ar_text ) && !$row->ar_text_id ) {
                        // Pre-1.5 ar_text row
                        $attribs['text'] = self::getRevisionText( $row, 'ar_' );
@@ -584,15 +607,19 @@ class Revision implements IDBAccessObject {
                                $this->mContent = $handler->unserializeContent( $this->mText );
                        }
 
-                       // if we have a Title object, override mPage. Useful for testing and convenience.
-                       if ( isset( $row['title'] ) ) {
-                               $this->mTitle     = $row['title'];
-                               $this->mPage      = $this->mTitle->getArticleID();
-                       } else {
-                               $this->mTitle     = null; // Load on demand if needed
+                       // If we have a Title object, make sure it is consistent with mPage.
+                       if ( $this->mTitle && $this->mTitle->exists() ) {
+                               if ( $this->mPage === null ) {
+                                       // if the page ID wasn't known, set it now
+                                       $this->mPage = $this->mTitle->getArticleID();
+                               } elseif ( $this->mTitle->getArticleID() !== $this->mPage ) {
+                                       // Got different page IDs. This may be legit (e.g. during undeletion),
+                                       // but it seems worth mentioning it in the log.
+                                       wfDebug( "Page ID " . $this->mPage . " mismatches the ID "
+                                                       . $this->mTitle->getArticleID() . " provided by the Title object." );
+                               }
                        }
 
-                       // @todo: XXX: really? we are about to create a revision. it will usually then be the current one.
                        $this->mCurrent   = false;
 
                        // If we still have no length, see it we have the text to figure it out
@@ -908,7 +935,7 @@ class Revision implements IDBAccessObject {
         * @param $user User object to check for, only if FOR_THIS_USER is passed
         *              to the $audience parameter
         * @since 1.21
-        * @return Content
+        * @return Content|null
         */
        public function getContent( $audience = self::FOR_PUBLIC, User $user = null ) {
                if( $audience == self::FOR_PUBLIC && $this->isDeleted( self::DELETED_TEXT ) ) {
@@ -941,7 +968,6 @@ class Revision implements IDBAccessObject {
         */
        public function getRawText() {
                ContentHandler::deprecated( __METHOD__, "1.21" );
-
                return $this->getText( self::RAW );
        }
 
@@ -967,14 +993,14 @@ class Revision implements IDBAccessObject {
 
                        $handler = $this->getContentHandler();
                        $format = $this->getContentFormat();
-                       $title = $this->getTitle();
 
                        if( is_null( $this->mText ) ) {
                                // Load text on demand:
                                $this->mText = $this->loadText();
                        }
 
-                       $this->mContent = is_null( $this->mText ) ? null : $handler->unserializeContent( $this->mText, $format );
+                       $this->mContent = ( $this->mText === null || $this->mText === false ) ? null
+                               : $handler->unserializeContent( $this->mText, $format );
                }
 
                return $this->mContent->copy(); // NOTE: copy() will return $this for immutable content objects
@@ -1022,6 +1048,7 @@ class Revision implements IDBAccessObject {
        /**
         * Returns the content handler appropriate for this revision's content model.
         *
+        * @throws MWException
         * @return ContentHandler
         */
        public function getContentHandler() {
@@ -1351,7 +1378,7 @@ class Revision implements IDBAccessObject {
 
                $content = $this->getContent( Revision::RAW );
 
-               if ( !$content->isValid() ) {
+               if ( !$content || !$content->isValid() ) {
                        $t = $title->getPrefixedDBkey();
 
                        throw new MWException( "Content of $t is not valid! Content model is $model" );
@@ -1371,7 +1398,7 @@ class Revision implements IDBAccessObject {
         * Lazy-load the revision's text.
         * Currently hardcoded to the 'text' table storage engine.
         *
-        * @return String
+        * @return String|boolean the revision text, or false on failure
         */
        protected function loadText() {
                wfProfileIn( __METHOD__ );