Remove workaround for comparing database domain IDs.
[lhc/web/wiklou.git] / includes / Storage / RevisionStore.php
index 3101aea..b6a751b 100644 (file)
@@ -164,6 +164,8 @@ class RevisionStore implements IDBAccessObject, RevisionFactory, RevisionLookup
         *
         * MCR migration note: this corresponds to Revision::getTitle
         *
+        * @note this method should be private, external use should be avoided!
+        *
         * @param int|null $pageId
         * @param int|null $revId
         * @param int $queryFlags
@@ -171,24 +173,24 @@ class RevisionStore implements IDBAccessObject, RevisionFactory, RevisionLookup
         * @return Title
         * @throws RevisionAccessException
         */
-       private function getTitle( $pageId, $revId, $queryFlags = 0 ) {
+       public function getTitle( $pageId, $revId, $queryFlags = 0 ) {
                if ( !$pageId && !$revId ) {
                        throw new InvalidArgumentException( '$pageId and $revId cannot both be 0 or null' );
                }
 
+               list( $dbMode, $dbOptions, , ) = DBAccessObjectUtils::getDBOptions( $queryFlags );
+               $titleFlags = $dbMode == DB_MASTER ? Title::GAID_FOR_UPDATE : 0;
                $title = null;
 
                // Loading by ID is best, but Title::newFromID does not support that for foreign IDs.
                if ( $pageId !== null && $pageId > 0 && $this->wikiId === false ) {
                        // TODO: better foreign title handling (introduce TitleFactory)
-                       $title = Title::newFromID( $pageId, $queryFlags );
+                       $title = Title::newFromID( $pageId, $titleFlags );
                }
 
                // rev_id is defined as NOT NULL, but this revision may not yet have been inserted.
                if ( !$title && $revId !== null && $revId > 0 ) {
-                       list( $dbMode, $dbOptions, , ) = DBAccessObjectUtils::getDBOptions( $queryFlags );
-
-                       $dbr = $this->getDbConnectionRef( $dbMode );
+                       $dbr = $this->getDBConnectionRef( $dbMode );
                        // @todo: Title::getSelectFields(), or Title::getQueryInfo(), or something like that
                        $row = $dbr->selectRow(
                                [ 'revision', 'page' ],
@@ -687,7 +689,7 @@ class RevisionStore implements IDBAccessObject, RevisionFactory, RevisionLookup
 
                $content = null;
                $blobData = null;
-               $blobFlags = '';
+               $blobFlags = null;
 
                if ( is_object( $row ) ) {
                        // archive row
@@ -704,7 +706,11 @@ class RevisionStore implements IDBAccessObject, RevisionFactory, RevisionLookup
                        if ( isset( $row->old_text ) ) {
                                // this happens when the text-table gets joined directly, in the pre-1.30 schema
                                $blobData = isset( $row->old_text ) ? strval( $row->old_text ) : null;
-                               $blobFlags = isset( $row->old_flags ) ? strval( $row->old_flags ) : '';
+                               // Check against selects that might have not included old_flags
+                               if ( !property_exists( $row, 'old_flags' ) ) {
+                                       throw new InvalidArgumentException( 'old_flags was not set in $row' );
+                               }
+                               $blobFlags = ( $row->old_flags === null ) ? '' : $row->old_flags;
                        }
 
                        $mainSlotRow->slot_revision = intval( $row->rev_id );
@@ -733,7 +739,9 @@ class RevisionStore implements IDBAccessObject, RevisionFactory, RevisionLookup
                        $mainSlotRow->format_name = isset( $row['content_format'] )
                                ? strval( $row['content_format'] ) : null;
                        $blobData = isset( $row['text'] ) ? rtrim( strval( $row['text'] ) ) : null;
-                       $blobFlags = isset( $row['flags'] ) ? trim( strval( $row['flags'] ) ) : '';
+                       // XXX: If the flags field is not set then $blobFlags should be null so that no
+                       // decoding will happen. An empty string will result in default decodings.
+                       $blobFlags = isset( $row['flags'] ) ? trim( strval( $row['flags'] ) ) : null;
 
                        // if we have a Content object, override mText and mContentModel
                        if ( !empty( $row['content'] ) ) {
@@ -795,7 +803,9 @@ class RevisionStore implements IDBAccessObject, RevisionFactory, RevisionLookup
         *
         * @param SlotRecord $slot The SlotRecord to load content for
         * @param string|null $blobData The content blob, in the form indicated by $blobFlags
-        * @param string $blobFlags Flags indicating how $blobData needs to be processed
+        * @param string|null $blobFlags Flags indicating how $blobData needs to be processed.
+        *        Use null if no processing should happen. That is in constrast to the empty string,
+        *        which causes the blob to be decoded according to the configured legacy encoding.
         * @param string|null $blobFormat MIME type indicating how $dataBlob is encoded
         * @param int $queryFlags
         *
@@ -805,23 +815,28 @@ class RevisionStore implements IDBAccessObject, RevisionFactory, RevisionLookup
        private function loadSlotContent(
                SlotRecord $slot,
                $blobData = null,
-               $blobFlags = '',
+               $blobFlags = null,
                $blobFormat = null,
                $queryFlags = 0
        ) {
                if ( $blobData !== null ) {
                        Assert::parameterType( 'string', $blobData, '$blobData' );
-                       Assert::parameterType( 'string', $blobFlags, '$blobFlags' );
+                       Assert::parameterType( 'string|null', $blobFlags, '$blobFlags' );
 
                        $cacheKey = $slot->hasAddress() ? $slot->getAddress() : null;
 
-                       $data = $this->blobStore->expandBlob( $blobData, $blobFlags, $cacheKey );
-
-                       if ( $data === false ) {
-                               throw new RevisionAccessException(
-                                       "Failed to expand blob data using flags $blobFlags (key: $cacheKey)"
-                               );
+                       if ( $blobFlags === null ) {
+                               // No blob flags, so use the blob verbatim.
+                               $data = $blobData;
+                       } else {
+                               $data = $this->blobStore->expandBlob( $blobData, $blobFlags, $cacheKey );
+                               if ( $data === false ) {
+                                       throw new RevisionAccessException(
+                                               "Failed to expand blob data using flags $blobFlags (key: $cacheKey)"
+                                       );
+                               }
                        }
+
                } else {
                        $address = $slot->getAddress();
                        try {
@@ -1469,29 +1484,13 @@ class RevisionStore implements IDBAccessObject, RevisionFactory, RevisionLookup
         * @throws MWException
         */
        private function checkDatabaseWikiId( IDatabase $db ) {
-               $storeWiki = $this->wikiId;
+               $storeWiki = $this->loadBalancer->getLocalDomainID();
                $dbWiki = $db->getDomainID();
 
                if ( $dbWiki === $storeWiki ) {
                        return;
                }
 
-               // XXX: we really want the default database ID...
-               $storeWiki = $storeWiki ?: wfWikiID();
-               $dbWiki = $dbWiki ?: wfWikiID();
-
-               if ( $dbWiki === $storeWiki ) {
-                       return;
-               }
-
-               // HACK: counteract encoding imposed by DatabaseDomain
-               $storeWiki = str_replace( '?h', '-', $storeWiki );
-               $dbWiki = str_replace( '?h', '-', $dbWiki );
-
-               if ( $dbWiki === $storeWiki ) {
-                       return;
-               }
-
                throw new MWException( "RevisionStore for $storeWiki "
                        . "cannot be used with a DB connection for $dbWiki" );
        }
@@ -1707,11 +1706,14 @@ class RevisionStore implements IDBAccessObject, RevisionFactory, RevisionLookup
         * MCR migration note: this replaces Revision::getPrevious
         *
         * @param RevisionRecord $rev
+        * @param Title $title if known (optional)
         *
         * @return RevisionRecord|null
         */
-       public function getPreviousRevision( RevisionRecord $rev ) {
-               $title = $this->getTitle( $rev->getPageId(), $rev->getId() );
+       public function getPreviousRevision( RevisionRecord $rev, Title $title = null ) {
+               if ( $title === null ) {
+                       $title = $this->getTitle( $rev->getPageId(), $rev->getId() );
+               }
                $prev = $title->getPreviousRevisionID( $rev->getId() );
                if ( $prev ) {
                        return $this->getRevisionByTitle( $title, $prev );
@@ -1725,11 +1727,14 @@ class RevisionStore implements IDBAccessObject, RevisionFactory, RevisionLookup
         * MCR migration note: this replaces Revision::getNext
         *
         * @param RevisionRecord $rev
+        * @param Title $title if known (optional)
         *
         * @return RevisionRecord|null
         */
-       public function getNextRevision( RevisionRecord $rev ) {
-               $title = $this->getTitle( $rev->getPageId(), $rev->getId() );
+       public function getNextRevision( RevisionRecord $rev, Title $title = null ) {
+               if ( $title === null ) {
+                       $title = $this->getTitle( $rev->getPageId(), $rev->getId() );
+               }
                $next = $title->getNextRevisionID( $rev->getId() );
                if ( $next ) {
                        return $this->getRevisionByTitle( $title, $next );