Merge "[MCR] Don't require $title to be passed to Revision::newFromId"
[lhc/web/wiklou.git] / includes / Revision.php
index c7c708e..8f36e88 100644 (file)
@@ -65,10 +65,14 @@ class Revision implements IDBAccessObject {
        }
 
        /**
+        * @param bool|string $wikiId The ID of the target wiki database. Use false for the local wiki.
+        *
         * @return SqlBlobStore
         */
-       protected static function getBlobStore() {
-               $store = MediaWikiServices::getInstance()->getBlobStore();
+       protected static function getBlobStore( $wiki = false ) {
+               $store = MediaWikiServices::getInstance()
+                       ->getBlobStoreFactory()
+                       ->newSqlBlobStore( $wiki );
 
                if ( !$store instanceof SqlBlobStore ) {
                        throw new RuntimeException(
@@ -90,11 +94,54 @@ class Revision implements IDBAccessObject {
         *
         * @param int $id
         * @param int $flags (optional)
+        * @param Title $title (optional) If known you can pass the Title in here.
+        *  Passing no Title may result in another DB query if there are recent writes.
         * @return Revision|null
         */
-       public static function newFromId( $id, $flags = 0 ) {
-               $rec = self::getRevisionStore()->getRevisionById( $id, $flags );
-               return $rec === null ? null : new Revision( $rec, $flags );
+       public static function newFromId( $id, $flags = 0, Title $title = null ) {
+               /**
+                * MCR RevisionStore Compat
+                *
+                * If the title is not passed in as a param (already known) then select it here.
+                *
+                * Do the selection with MASTER if $flags includes READ_LATEST or recent changes
+                * have happened on our load balancer.
+                *
+                * If we select the title here and pass it down it will results in fewer queries
+                * further down the stack.
+                */
+               if ( !$title ) {
+                       if (
+                               $flags & self::READ_LATEST ||
+                               wfGetLB()->hasOrMadeRecentMasterChanges()
+                       ) {
+                               $dbr = wfGetDB( DB_MASTER );
+                       } else {
+                               $dbr = wfGetDB( DB_REPLICA );
+                       }
+                       $row = $dbr->selectRow(
+                               [ 'revision', 'page' ],
+                               [
+                                       'page_namespace',
+                                       'page_title',
+                                       'page_id',
+                                       'page_latest',
+                                       'page_is_redirect',
+                                       'page_len',
+                               ],
+                               [ 'rev_id' => $id ],
+                               __METHOD__,
+                               [],
+                               [ 'page' => [ 'JOIN', 'page_id=rev_page' ] ]
+                       );
+                       if ( $row ) {
+                               $title = Title::newFromRow( $row );
+                       }
+                       wfGetLB()->reuseConnection( $dbr );
+               }
+
+               $rec = self::getRevisionStore()->getRevisionById( $id, $flags, $title );
+               return $rec === null ? null : new Revision( $rec, $flags, $title );
        }
 
        /**
@@ -141,13 +188,25 @@ class Revision implements IDBAccessObject {
         *
         * @param object $row
         * @param array $overrides
+        * @param Title $title (optional)
         *
         * @throws MWException
         * @return Revision
         */
-       public static function newFromArchiveRow( $row, $overrides = [] ) {
-               $rec = self::getRevisionStore()->newRevisionFromArchiveRow( $row, 0, null, $overrides );
-               return new Revision( $rec );
+       public static function newFromArchiveRow( $row, $overrides = [], Title $title = null ) {
+               /**
+                * MCR Migration: https://phabricator.wikimedia.org/T183564
+                * This method used to overwrite attributes, then passed to Revision::__construct
+                * RevisionStore::newRevisionFromArchiveRow instead overrides row field names
+                * So do a conversion here.
+                */
+               if ( array_key_exists( 'page', $overrides ) ) {
+                       $overrides['page_id'] = $overrides['page'];
+                       unset( $overrides['page'] );
+               }
+
+               $rec = self::getRevisionStore()->newRevisionFromArchiveRow( $row, 0, $title, $overrides );
+               return new Revision( $rec, self::READ_NORMAL, $title );
        }
 
        /**
@@ -879,8 +938,10 @@ class Revision implements IDBAccessObject {
         * @return Revision|null
         */
        public function getPrevious() {
-               $rec = self::getRevisionStore()->getPreviousRevision( $this->mRecord );
-               return $rec === null ? null : new Revision( $rec );
+               $rec = self::getRevisionStore()->getPreviousRevision( $this->mRecord, $this->getTitle() );
+               return $rec === null
+                       ? null
+                       : new Revision( $rec, self::READ_NORMAL, $this->getTitle() );
        }
 
        /**
@@ -889,8 +950,10 @@ class Revision implements IDBAccessObject {
         * @return Revision|null
         */
        public function getNext() {
-               $rec = self::getRevisionStore()->getNextRevision( $this->mRecord );
-               return $rec === null ? null : new Revision( $rec );
+               $rec = self::getRevisionStore()->getNextRevision( $this->mRecord, $this->getTitle() );
+               return $rec === null
+                       ? null
+                       : new Revision( $rec, self::READ_NORMAL, $this->getTitle() );
        }
 
        /**
@@ -925,7 +988,7 @@ class Revision implements IDBAccessObject {
 
                $cacheKey = isset( $row->old_id ) ? ( 'tt:' . $row->old_id ) : null;
 
-               return self::getBlobStore()->expandBlob( $text, $flags, $cacheKey );
+               return self::getBlobStore( $wiki )->expandBlob( $text, $flags, $cacheKey );
        }
 
        /**