Daniel Kinzler has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/387640 )

Change subject: [MCR] Make WikiPage use Revisionrecord instead of Revision
......................................................................

[MCR] Make WikiPage use Revisionrecord instead of Revision

This is preparatory work for splittinng WikiPage into
PageRecord, PageStore, and PageUpdater.

Change-Id: I29d817b682ed556875e1f520d410f0623a4cc15b
---
M includes/Storage/RevisionStore.php
M includes/Title.php
M includes/page/WikiPage.php
M includes/resourceloader/ResourceLoaderWikiModule.php
4 files changed, 271 insertions(+), 108 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core 
refs/changes/40/387640/1

diff --git a/includes/Storage/RevisionStore.php 
b/includes/Storage/RevisionStore.php
index fa566d3..9b34d1e 100644
--- a/includes/Storage/RevisionStore.php
+++ b/includes/Storage/RevisionStore.php
@@ -1727,6 +1727,41 @@
                }
        }
 
+       /**
+        * Get the first revision of the page, or null if the page does not 
exist.
+        *
+        * @param Title $title
+        * @param int $flags See IDBAccessObject::READ_XXX, default is 0.
+        *
+        * @return RevisionRecord|null
+        */
+       public function getFirstRevision( Title $title, $flags = 0 ) {
+               if ( !$title->exists( $flags ) ) {
+                       return null;
+               }
+
+               $pageId = $title->getArticleID( $flags );
+
+               $db = ( $flags & self::READ_LATEST )
+                       ? $this->getDBConnection( DB_MASTER )
+                       : $this->getDBConnection( DB_REPLICA );
+
+               $row = $db->selectRow( 'revision', self::selectRevisionFields(),
+                       [ 'rev_page' => $pageId ],
+                       __METHOD__,
+                       [
+                               'ORDER BY' => 'rev_timestamp ASC, rev_id ASC',
+                               'IGNORE INDEX' => 'rev_timestamp', // See 
T159319
+                       ]
+               );
+
+               if ( $row ) {
+                       return $this->newRevisionFromRow( $row );
+               }
+
+               return null;
+       }
+
        // TODO: move relevant methods from Title here, e.g. getFirstRevision, 
isBigDeletion, etc.
 
 }
diff --git a/includes/Title.php b/includes/Title.php
index 718239d..492b747 100644
--- a/includes/Title.php
+++ b/includes/Title.php
@@ -22,6 +22,7 @@
  * @file
  */
 
+use MediaWiki\Storage\RevisionStore;
 use Wikimedia\Rdbms\Database;
 use Wikimedia\Rdbms\IDatabase;
 use MediaWiki\Linker\LinkTarget;
@@ -51,7 +52,7 @@
         * Used to be GAID_FOR_UPDATE define. Used with getArticleID() and 
friends
         * to use the master DB
         */
-       const GAID_FOR_UPDATE = 1;
+       const GAID_FOR_UPDATE = IDBAccessObject::READ_LATEST;
 
        /**
         * @name Private member variables
@@ -4184,28 +4185,19 @@
        }
 
        /**
-        * Get the first revision of the page
+        * Get the first revision of the page, or null if the page does not 
exist.
         *
         * @param int $flags Title::GAID_FOR_UPDATE
         * @return Revision|null If page doesn't exist
         */
        public function getFirstRevision( $flags = 0 ) {
-               $pageId = $this->getArticleID( $flags );
-               if ( $pageId ) {
-                       $db = ( $flags & self::GAID_FOR_UPDATE ) ? wfGetDB( 
DB_MASTER ) : wfGetDB( DB_REPLICA );
-                       $row = $db->selectRow( 'revision', 
Revision::selectFields(),
-                               [ 'rev_page' => $pageId ],
-                               __METHOD__,
-                               [
-                                       'ORDER BY' => 'rev_timestamp ASC, 
rev_id ASC',
-                                       'IGNORE INDEX' => 'rev_timestamp', // 
See T159319
-                               ]
-                       );
-                       if ( $row ) {
-                               return new Revision( $row );
-                       }
-               }
-               return null;
+               // not needed if we rely on self::GAID_FOR_UPDATE === 
RevisionStore::READ_LATEST.
+               $revStoreFlags = ( $flags & self::GAID_FOR_UPDATE ) ? 
RevisionStore::READ_LATEST : 0;
+
+               $revStore = 
MediaWikiServices::getInstance()->getRevisionStore(); // inject?
+               $revRec = $revStore->getFirstRevision( $this, $revStoreFlags );
+
+               return $revRec ? new Revision( $revRec, $revStoreFlags, $this ) 
: null;
        }
 
        /**
diff --git a/includes/page/WikiPage.php b/includes/page/WikiPage.php
index e015230..a9b9ba4 100644
--- a/includes/page/WikiPage.php
+++ b/includes/page/WikiPage.php
@@ -23,6 +23,8 @@
 use MediaWiki\Edit\PreparedEdit;
 use \MediaWiki\Logger\LoggerFactory;
 use \MediaWiki\MediaWikiServices;
+use MediaWiki\Storage\RevisionRecord;
+use MediaWiki\Storage\RevisionStore;
 use Wikimedia\Assert\Assert;
 use Wikimedia\Rdbms\FakeResultWrapper;
 use Wikimedia\Rdbms\IDatabase;
@@ -72,7 +74,12 @@
        /**
         * @var Revision
         */
-       protected $mLastRevision = null;
+       private $mLastRevision = null;
+
+       /**
+        * @var RevisionRecord
+        */
+       private $mLastRevisionRecord = null;
 
        /**
         * @var string Timestamp of the current revision or empty string if not 
loaded
@@ -211,6 +218,8 @@
         * @return array
         */
        public function getActionOverrides() {
+               // XXX: are action overrides always defined by the main slot?
+               // Perhaps they should be registered per namespace instead.
                return $this->getContentHandler()->getActionOverrides();
        }
 
@@ -218,6 +227,9 @@
         * Returns the ContentHandler instance to be used to deal with the 
content of this WikiPage.
         *
         * Shorthand for ContentHandler::getForModelID( 
$this->getContentModel() );
+        *
+        * @deprecated since 1.31, the content model is defined for each slot, 
not per page.
+        * For backwards compatibility, this method will use the main slot.
         *
         * @return ContentHandler
         *
@@ -254,6 +266,7 @@
                $this->mId = null;
                $this->mRedirectTarget = null; // Title object if set
                $this->mLastRevision = null; // Latest revision
+               $this->mLastRevisionRecord = null; // Latest revision
                $this->mTouched = '19700101000000';
                $this->mLinksUpdated = '19700101000000';
                $this->mTimestamp = '';
@@ -429,8 +442,9 @@
                        $this->mLatest = intval( $data->page_latest );
                        // T39225: $latest may no longer match the cached 
latest Revision object.
                        // Double-check the ID of any cached latest Revision 
object for consistency.
-                       if ( $this->mLastRevision && 
$this->mLastRevision->getId() != $this->mLatest ) {
+                       if ( $this->mLastRevisionRecord && 
$this->mLastRevisionRecord->getId() != $this->mLatest ) {
                                $this->mLastRevision = null;
+                               $this->mLastRevisionRecord = null;
                                $this->mTimestamp = '';
                        }
                } else {
@@ -497,6 +511,9 @@
         *
         * Will use the revisions actual content model if the page exists,
         * and the page's default if the page doesn't exist yet.
+        *
+        * @deprecated since 1.31, the content model is defined for each slot, 
not per page.
+        * For backwards compatibility, this method will use the main slot.
         *
         * @return string
         *
@@ -573,15 +590,35 @@
 
        /**
         * Get the Revision object of the oldest revision
+        *
+        * @deprecated since 1.31, use getOldestRevisionRecord() instead.
+        *
         * @return Revision|null
         */
        public function getOldestRevision() {
+               $revRec = $this->getOldestRevisionRecord();
+               return $revRec ? new Revision( $revRec ) : null;
+       }
+
+       /**
+        * Get the Revision object of the oldest revision, or null if the page 
does not exist.
+        * @return RevisionRecord|null
+        */
+       public function getOldestRevisionRecord() {
                // Try using the replica DB first, then try the master
-               $rev = $this->mTitle->getFirstRevision();
+               $revStore = self::getRevisionStore();
+               $rev = $revStore->getFirstRevision( $this->mTitle );
                if ( !$rev ) {
-                       $rev = $this->mTitle->getFirstRevision( 
Title::GAID_FOR_UPDATE );
+                       $rev = $revStore->getFirstRevision( $this->mTitle, 
RevisionStore::READ_LATEST );
                }
                return $rev;
+       }
+
+       /**
+        * @return RevisionStore
+        */
+       private static function getRevisionStore() {
+               return MediaWikiServices::getInstance()->getRevisionStore();
        }
 
        /**
@@ -589,7 +626,11 @@
         * This isn't necessary for all uses, so it's only done if needed.
         */
        protected function loadLastEdit() {
-               if ( $this->mLastRevision !== null ) {
+               if ( $this->mLastRevisionRecord !== null ) {
+                       if ( $this->mLastRevision === null ) {
+                               $this->mLastRevision = new Revision( 
$this->mLastRevisionRecord );
+                       }
+
                        return; // already loaded
                }
 
@@ -606,17 +647,17 @@
                        // may not find it since a page row UPDATE and revision 
row INSERT by S2 may have
                        // happened after the first S1 SELECT.
                        // 
https://dev.mysql.com/doc/refman/5.0/en/set-transaction.html#isolevel_repeatable-read
-                       $flags = Revision::READ_LOCKING;
-                       $revision = Revision::newFromPageId( $this->getId(), 
$latest, $flags );
+                       $flags = RevisionStore::READ_LOCKING;
+                       $revision = 
self::getRevisionStore()->getRevisionByPageId( $this->getId(), $latest, $flags 
);
                } elseif ( $this->mDataLoadedFrom == self::READ_LATEST ) {
                        // Bug T93976: if page_latest was loaded from the 
master, fetch the
                        // revision from there as well, as it may not exist yet 
on a replica DB.
                        // Also, this keeps the queries in the same 
REPEATABLE-READ snapshot.
-                       $flags = Revision::READ_LATEST;
-                       $revision = Revision::newFromPageId( $this->getId(), 
$latest, $flags );
+                       $flags = RevisionStore::READ_LATEST;
+                       $revision = 
self::getRevisionStore()->getRevisionByPageId( $this->getId(), $latest, $flags 
);
                } else {
                        $dbr = wfGetDB( DB_REPLICA );
-                       $revision = Revision::newKnownCurrent( $dbr, 
$this->getTitle(), $latest );
+                       $revision = 
self::getRevisionStore()->getKnownCurrentRevision( $dbr, $this->getTitle(), 
$latest );
                }
 
                if ( $revision ) { // sanity
@@ -626,42 +667,56 @@
 
        /**
         * Set the latest revision
-        * @param Revision $revision
+        * @param RevisionRecord $revRec
         */
-       protected function setLastEdit( Revision $revision ) {
-               $this->mLastRevision = $revision;
-               $this->mTimestamp = $revision->getTimestamp();
+       private function setLastEdit( RevisionRecord $revRec ) {
+               if ( $this->mLastRevisionRecord !== $revRec ) {
+                       $this->mLastRevisionRecord = $revRec;
+                       $this->mLastRevision = new Revision( $revRec );
+                       $this->mTimestamp = $revRec->getTimestamp();
+               }
        }
 
        /**
-        * Get the latest revision
+        * Get the latest revision, or null if the page does not exist.
+        *
+        * @deprecated since 1.31, use getRevisionRecord instead.
+        *
         * @return Revision|null
         */
        public function getRevision() {
                $this->loadLastEdit();
-               if ( $this->mLastRevision ) {
-                       return $this->mLastRevision;
-               }
-               return null;
+               return $this->mLastRevision;
+       }
+
+       /**
+        * Get the latest revision, or null if the page does not exist.
+        * @return RevisionRecord|null
+        */
+       public function getLatestRevisionRecord() {
+               $this->loadLastEdit();
+               return $this->mLastRevisionRecord;
        }
 
        /**
         * Get the content of the current revision. No side-effects...
         *
+        * @deprecated since 1.31, use getRevisionrecord()->getContent() 
instead.
+        *
         * @param int $audience One of:
-        *   Revision::FOR_PUBLIC       to be displayed to all users
-        *   Revision::FOR_THIS_USER    to be displayed to $wgUser
-        *   Revision::RAW              get the text regardless of permissions
+        *   RevisionRecord::FOR_PUBLIC       to be displayed to all users
+        *   RevisionRecord::FOR_THIS_USER    to be displayed to $wgUser
+        *   RevisionRecord::RAW              get the text regardless of 
permissions
         * @param User $user User object to check for, only if FOR_THIS_USER is 
passed
         *   to the $audience parameter
         * @return Content|null The content of the current revision
         *
         * @since 1.21
         */
-       public function getContent( $audience = Revision::FOR_PUBLIC, User 
$user = null ) {
+       public function getContent( $audience = RevisionRecord::FOR_PUBLIC, 
User $user = null ) {
                $this->loadLastEdit();
-               if ( $this->mLastRevision ) {
-                       return $this->mLastRevision->getContent( $audience, 
$user );
+               if ( $this->mLastRevisionRecord ) {
+                       return $this->mLastRevisionRecord->getContent( 'main', 
$audience, $user );
                }
                return null;
        }
@@ -689,17 +744,17 @@
 
        /**
         * @param int $audience One of:
-        *   Revision::FOR_PUBLIC       to be displayed to all users
-        *   Revision::FOR_THIS_USER    to be displayed to the given user
-        *   Revision::RAW              get the text regardless of permissions
+        *   RevisionRecord::FOR_PUBLIC       to be displayed to all users
+        *   RevisionRecord::FOR_THIS_USER    to be displayed to the given user
+        *   RevisionRecord::RAW              get the text regardless of 
permissions
         * @param User $user User object to check for, only if FOR_THIS_USER is 
passed
         *   to the $audience parameter
         * @return int User ID for the user that made the last article revision
         */
-       public function getUser( $audience = Revision::FOR_PUBLIC, User $user = 
null ) {
+       public function getUser( $audience = RevisionRecord::FOR_PUBLIC, User 
$user = null ) {
                $this->loadLastEdit();
-               if ( $this->mLastRevision ) {
-                       return $this->mLastRevision->getUser( $audience, $user 
);
+               if ( $this->mLastRevisionRecord ) {
+                       return $this->mLastRevisionRecord->getUserId( 
$audience, $user );
                } else {
                        return -1;
                }
@@ -708,15 +763,15 @@
        /**
         * Get the User object of the user who created the page
         * @param int $audience One of:
-        *   Revision::FOR_PUBLIC       to be displayed to all users
-        *   Revision::FOR_THIS_USER    to be displayed to the given user
-        *   Revision::RAW              get the text regardless of permissions
+        *   RevisionRecord::FOR_PUBLIC       to be displayed to all users
+        *   RevisionRecord::FOR_THIS_USER    to be displayed to the given user
+        *   RevisionRecord::RAW              get the text regardless of 
permissions
         * @param User $user User object to check for, only if FOR_THIS_USER is 
passed
         *   to the $audience parameter
         * @return User|null
         */
-       public function getCreator( $audience = Revision::FOR_PUBLIC, User 
$user = null ) {
-               $revision = $this->getOldestRevision();
+       public function getCreator( $audience = RevisionRecord::FOR_PUBLIC, 
User $user = null ) {
+               $revision = $this->getOldestRevisionRecord();
                if ( $revision ) {
                        $userName = $revision->getUserText( $audience, $user );
                        return User::newFromName( $userName, false );
@@ -727,17 +782,17 @@
 
        /**
         * @param int $audience One of:
-        *   Revision::FOR_PUBLIC       to be displayed to all users
-        *   Revision::FOR_THIS_USER    to be displayed to the given user
-        *   Revision::RAW              get the text regardless of permissions
+        *   RevisionRecord::FOR_PUBLIC       to be displayed to all users
+        *   RevisionRecord::FOR_THIS_USER    to be displayed to the given user
+        *   RevisionRecord::RAW              get the text regardless of 
permissions
         * @param User $user User object to check for, only if FOR_THIS_USER is 
passed
         *   to the $audience parameter
         * @return string Username of the user that made the last article 
revision
         */
-       public function getUserText( $audience = Revision::FOR_PUBLIC, User 
$user = null ) {
+       public function getUserText( $audience = RevisionRecord::FOR_PUBLIC, 
User $user = null ) {
                $this->loadLastEdit();
-               if ( $this->mLastRevision ) {
-                       return $this->mLastRevision->getUserText( $audience, 
$user );
+               if ( $this->mLastRevisionRecord ) {
+                       return $this->mLastRevisionRecord->getUserText( 
$audience, $user );
                } else {
                        return '';
                }
@@ -745,17 +800,18 @@
 
        /**
         * @param int $audience One of:
-        *   Revision::FOR_PUBLIC       to be displayed to all users
-        *   Revision::FOR_THIS_USER    to be displayed to the given user
-        *   Revision::RAW              get the text regardless of permissions
+        *   RevisionRecord::FOR_PUBLIC       to be displayed to all users
+        *   RevisionRecord::FOR_THIS_USER    to be displayed to the given user
+        *   RevisionRecord::RAW              get the text regardless of 
permissions
         * @param User $user User object to check for, only if FOR_THIS_USER is 
passed
         *   to the $audience parameter
         * @return string Comment stored for the last article revision
         */
-       public function getComment( $audience = Revision::FOR_PUBLIC, User 
$user = null ) {
+       public function getComment( $audience = RevisionRecord::FOR_PUBLIC, 
User $user = null ) {
                $this->loadLastEdit();
-               if ( $this->mLastRevision ) {
-                       return $this->mLastRevision->getComment( $audience, 
$user );
+               if ( $this->mLastRevisionRecord ) {
+                       $comment = $this->mLastRevisionRecord->getComment( 
$audience, $user );
+                       return $comment ? $comment->text : null;
                } else {
                        return '';
                }
@@ -768,8 +824,8 @@
         */
        public function getMinorEdit() {
                $this->loadLastEdit();
-               if ( $this->mLastRevision ) {
-                       return $this->mLastRevision->isMinor();
+               if ( $this->mLastRevisionRecord ) {
+                       return $this->mLastRevisionRecord->isMinor();
                } else {
                        return false;
                }
@@ -999,7 +1055,7 @@
                }
 
                // Username hidden?
-               $conds[] = "{$dbr->bitAnd( 'rev_deleted', 
Revision::DELETED_USER )} = 0";
+               $conds[] = "{$dbr->bitAnd( 'rev_deleted', 
RevisionRecord::DELETED_USER )} = 0";
 
                $jconds = [
                        'user' => [ 'LEFT JOIN', 'rev_user = user_id' ],
@@ -1176,6 +1232,8 @@
        /**
         * Update the page record to point to a newly saved revision.
         *
+        * @deprecated since 1.31 use updatePageOn() instead.
+        *
         * @param IDatabase $dbw
         * @param Revision $revision For ID number, and text used to set
         *   length and redirect status fields
@@ -1186,7 +1244,32 @@
         *   removing rows in redirect table.
         * @return bool Success; false if the page row was missing or 
page_latest changed
         */
-       public function updateRevisionOn( $dbw, $revision, $lastRevision = null,
+       public function updateRevisionOn( $dbw, Revision $revision, 
$lastRevision = null,
+               $lastRevIsRedirect = null
+       ) {
+               return $this->updatePageOn(
+                       $dbw,
+                       $revision->getRevisionRecord(),
+                       $lastRevision,
+                       $lastRevIsRedirect
+               );
+       }
+
+       /**
+        * Update the page record to point to a newly saved revision.
+        *
+        * @todo move to PageStore
+        *
+        * @param IDatabase $dbw
+        * @param RevisionRecord $revision For ID number, size, redirect 
status, etc.
+        * @param int $lastRevision If given, will not overwrite the page field
+        *   when different from the currently set value.
+        *   Giving 0 indicates the new page flag should be set on.
+        * @param bool $lastRevIsRedirect If given, will optimize adding and
+        *   removing rows in redirect table.
+        * @return bool Success; false if the page row was missing or 
page_latest changed
+        */
+       public function updatePageOn( $dbw, RevisionRecord $revision, 
$lastRevision = null,
                $lastRevIsRedirect = null
        ) {
                global $wgContentHandlerUseDB;
@@ -1198,9 +1281,11 @@
                        );
                }
 
-               $content = $revision->getContent();
-               $len = $content ? $content->getSize() : 0;
-               $rt = $content ? $content->getUltimateRedirectTarget() : null;
+               $publicMainContent = $revision->getContent( 'main', 
RevisionRecord::FOR_PUBLIC );
+               $rt = $publicMainContent ? 
$publicMainContent->getUltimateRedirectTarget() : null;
+
+               $mainContent = $revision->getContent( 'main', 
RevisionRecord::RAW );
+               $len = $revision->getSize();
 
                $conditions = [ 'page_id' => $this->getId() ];
 
@@ -1221,7 +1306,7 @@
                ];
 
                if ( $wgContentHandlerUseDB ) {
-                       $row['page_content_model'] = 
$revision->getContentModel();
+                       $row['page_content_model'] = $mainContent->getModel();
                }
 
                $dbw->update( 'page',
@@ -1242,7 +1327,7 @@
                                $len,
                                $this->mIsRedirect,
                                $this->mLatest,
-                               $revision->getContentModel()
+                               $mainContent->getModel()
                        );
                }
 
@@ -1292,10 +1377,14 @@
         * @deprecated since 1.24, use updateRevisionOn instead
         *
         * @param IDatabase $dbw
-        * @param Revision $revision
+        * @param Revision|RevisionRecord $revision
         * @return bool
         */
        public function updateIfNewerOn( $dbw, $revision ) {
+               if ( $revision instanceof  Revision ) {
+                       $revision = $revision->getRevisionRecord();
+               }
+
                $row = $dbw->selectRow(
                        [ 'revision', 'page' ],
                        [ 'rev_id', 'rev_timestamp', 'page_is_redirect' ],
@@ -1316,7 +1405,7 @@
                        $lastRevIsRedirect = null;
                }
 
-               $ret = $this->updateRevisionOn( $dbw, $revision, $prev, 
$lastRevIsRedirect );
+               $ret = $this->updatePageOn( $dbw, $revision, $prev, 
$lastRevIsRedirect );
 
                return $ret;
        }
@@ -1325,6 +1414,9 @@
         * Get the content that needs to be saved in order to undo all revisions
         * between $undo and $undoafter. Revisions must belong to the same page,
         * must exist and must not be deleted
+        *
+        * @deprecated since 1.31, use ContentHandler::getUndoContent instead.
+        *
         * @param Revision $undo
         * @param Revision $undoafter Must be an earlier revision than $undo
         * @return Content|bool Content on success, false on failure
@@ -1332,12 +1424,15 @@
         * Before we had the Content object, this was done in getUndoText
         */
        public function getUndoContent( Revision $undo, Revision $undoafter = 
null ) {
+               // TODO: undo must headle each content slot separately!
                $handler = $undo->getContentHandler();
                return $handler->getUndoContent( $this->getRevision(), $undo, 
$undoafter );
        }
 
        /**
         * Returns true if this page's content model supports sections.
+        *
+        * @deprecated since 1.31, use ContentHandler::supportsSections.
         *
         * @return bool
         *
@@ -1351,6 +1446,8 @@
        }
 
        /**
+        * @todo add support for other slots besides the main slot
+        *
         * @param string|int|null|bool $sectionId Section identifier as a 
number or string
         * (e.g. 0, 1 or 'T-1'), null/false or an empty string for the whole 
page
         * or 'new' for a new section.
@@ -1390,6 +1487,8 @@
        }
 
        /**
+        * @todo add support for other slots besides the main slot
+        *
         * @param string|int|null|bool $sectionId Section identifier as a 
number or string
         * (e.g. 0, 1 or 'T-1'), null/false or an empty string for the whole 
page
         * or 'new' for a new section.
@@ -1411,12 +1510,12 @@
                } else {
                        if ( !$this->supportsSections() ) {
                                throw new MWException( "sections not supported 
for content model " .
-                                       
$this->getContentHandler()->getModelID() );
+                                       
$this->getContentHandler()->getModelID() ); // TODO: we need to know the slot 
here
                        }
 
                        // T32711: always use current version when adding a new 
section
                        if ( is_null( $baseRevId ) || $sectionId === 'new' ) {
-                               $oldContent = $this->getContent();
+                               $oldContent = $this->getContent(); // TODO: we 
need to know the slot here
                        } else {
                                $rev = Revision::newFromId( $baseRevId );
                                if ( !$rev ) {
@@ -1563,7 +1662,7 @@
                }
 
                $old_revision = $this->getRevision(); // current revision
-               $old_content = $this->getContent( Revision::RAW ); // current 
revision's content
+               $old_content = $this->getContent( RevisionRecord::RAW ); // 
current revision's content
 
                if ( $old_content && $old_content->getModel() !== 
$content->getModel() ) {
                        $tags[] = 'mw-contentmodelchange';
@@ -1741,8 +1840,8 @@
                        // related variables correctly. Likewise for 
{{REVISIONUSER}} (T135261).
                        $revision->setId( $this->getLatest() );
                        $revision->setUserIdAndName(
-                               $this->getUser( Revision::RAW ),
-                               $this->getUserText( Revision::RAW )
+                               $this->getUser( RevisionRecord::RAW ),
+                               $this->getUserText( RevisionRecord::RAW )
                        );
                }
 
@@ -1971,7 +2070,7 @@
                        // use it, so performance here shouldn't be a worry.
                        if ( $revid !== null ) {
                                wfDeprecated( __METHOD__ . ' with $revision = 
revision ID', '1.25' );
-                               $revision = Revision::newFromId( $revid, 
Revision::READ_LATEST );
+                               $revision = Revision::newFromId( $revid, 
RevisionStore::READ_LATEST );
                        } else {
                                $revision = null;
                        }
@@ -2062,7 +2161,7 @@
                }
 
                $edit->newContent = $content;
-               $edit->oldContent = $this->getContent( Revision::RAW );
+               $edit->oldContent = $this->getContent( RevisionRecord::RAW );
 
                // NOTE: B/C for hooks! don't use these fields!
                $edit->newText = $edit->newContent
@@ -2259,8 +2358,18 @@
                        self::onArticleEdit( $this->mTitle, $revision );
                }
 
+               /** @var Revision|RevisionRecord|null $oldRev */
+               $oldRev = $options['oldrevision'];
+               $oldModel = null;
+
+               if ( $oldRev ) {
+                       $oldModel = $oldRev instanceof Revision
+                               ? $oldRev->getContentModel()
+                               : $oldRev->getSlot( 'main', RevisionRecord::RAW 
)->getModel();
+               }
+
                ResourceLoaderWikiModule::invalidateModuleCache(
-                       $this->mTitle, $options['oldrevision'], $revision, 
wfWikiID()
+                       $this->mTitle, $oldModel, $revision->getContentModel(), 
wfWikiID()
                );
        }
 
@@ -2781,7 +2890,7 @@
                // we need to remember the old content so we can use it to 
generate all deletion updates.
                $revision = $this->getRevision();
                try {
-                       $content = $this->getContent( Revision::RAW );
+                       $content = $this->getContent( RevisionRecord::RAW );
                } catch ( Exception $ex ) {
                        wfLogWarning( __METHOD__ . ': failed to load content 
during deletion! '
                                . $ex->getMessage() );
@@ -2792,12 +2901,12 @@
                $revCommentStore = new CommentStore( 'rev_comment' );
                $arCommentStore = new CommentStore( 'ar_comment' );
 
-               $fields = Revision::selectFields();
+               $fields = self::getRevisionStore()->selectRevisionFields();
                $bitfield = false;
 
                // Bitfields to further suppress the content
                if ( $suppress ) {
-                       $bitfield = Revision::SUPPRESSED_ALL;
+                       $bitfield = RevisionRecord::SUPPRESSED_ALL;
                        $fields = array_diff( $fields, [ 'rev_deleted' ] );
                }
 
@@ -2946,16 +3055,23 @@
        /**
         * Do some database updates after deletion
         *
+        * @deprecated since 1.31 internal use only!
+        * @todo Still called from Article::doDeleteUpdates(), make private 
when that is resolved.
+        *
         * @param int $id The page_id value of the page being deleted
         * @param Content|null $content Optional page content to be used when 
determining
         *   the required updates. This may be needed because 
$this->getContent()
         *   may already return null when the page proper was deleted.
-        * @param Revision|null $revision The latest page revision
+        * @param Revision|RevisionRecord|null $revision The latest page 
revision
         * @param User|null $user The user that caused the deletion
         */
        public function doDeleteUpdates(
-               $id, Content $content = null, Revision $revision = null, User 
$user = null
+               $id, Content $content = null, $revision = null, User $user = 
null
        ) {
+               if ( $revision instanceof  Revision ) {
+                       $revision = $revision->getRevisionRecord();
+               }
+
                try {
                        $countable = $this->isCountable();
                } catch ( Exception $ex ) {
@@ -2985,8 +3101,10 @@
 
                // Clear caches
                self::onArticleDelete( $this->mTitle );
+
+               $mainSlot = $revision->getSlot( 'main', RevisionRecord::RAW );
                ResourceLoaderWikiModule::invalidateModuleCache(
-                       $this->mTitle, $revision, null, wfWikiID()
+                       $this->mTitle, $mainSlot->getModel(), null, wfWikiID()
                );
 
                // Reset this object and the Title object
@@ -3103,8 +3221,8 @@
 
                // Get the last edit not by this person...
                // Note: these may not be public values
-               $user = intval( $current->getUser( Revision::RAW ) );
-               $user_text = $dbw->addQuotes( $current->getUserText( 
Revision::RAW ) );
+               $user = intval( $current->getUser( RevisionRecord::RAW ) );
+               $user_text = $dbw->addQuotes( $current->getUserText( 
RevisionRecord::RAW ) );
                $s = $dbw->selectRow( 'revision',
                        [ 'rev_id', 'rev_timestamp', 'rev_deleted' ],
                        [ 'rev_page' => $current->getPage(),
@@ -3116,15 +3234,15 @@
                if ( $s === false ) {
                        // No one else ever edited this page
                        return [ [ 'cantrollback' ] ];
-               } elseif ( $s->rev_deleted & Revision::DELETED_TEXT
-                       || $s->rev_deleted & Revision::DELETED_USER
+               } elseif ( $s->rev_deleted & RevisionRecord::DELETED_TEXT
+                       || $s->rev_deleted & RevisionRecord::DELETED_USER
                ) {
                        // Only admins can see this text
                        return [ [ 'notvisiblerev' ] ];
                }
 
                // Generate the edit summary if necessary
-               $target = Revision::newFromId( $s->rev_id, 
Revision::READ_LATEST );
+               $target = self::getRevisionStore()->getRevisionById( 
$s->rev_id, RevisionStore::READ_LATEST );
                if ( empty( $summary ) ) {
                        if ( $from == '' ) { // no public user name
                                $summary = wfMessage( 'revertpage-nouser' );
@@ -3159,7 +3277,13 @@
                        $flags |= EDIT_FORCE_BOT;
                }
 
-               $targetContent = $target->getContent();
+               // FIXME: roll back all slots!
+               // XXX: should this use RAW access? Can a user roll back to a 
revision they cannot see?
+               $targetContent = $target->getContent( 'main', 
RevisionRecord::FOR_THIS_USER, $guser );
+               if ( !$targetContent ) {
+                       return [ [ 'notvisiblerev' ] ];
+               }
+
                $changingContentModel = $targetContent->getModel() !== 
$current->getContentModel();
 
                // Actually store the edit
@@ -3205,7 +3329,8 @@
                $statusRev = isset( $status->value['revision'] )
                        ? $status->value['revision']
                        : null;
-               if ( !( $statusRev instanceof Revision ) ) {
+
+               if ( !$statusRev ) {
                        $resultDetails = [ 'current' => $current ];
                        return [ [ 'alreadyrolled',
                                        htmlspecialchars( 
$this->mTitle->getPrefixedText() ),
@@ -3232,12 +3357,13 @@
 
                $revId = $statusRev->getId();
 
+               // FIXME: type of $target changed to RevisionRecord!
                Hooks::run( 'ArticleRollbackComplete', [ $this, $guser, 
$target, $current ] );
 
                $resultDetails = [
                        'summary' => $summary,
                        'current' => $current,
-                       'target' => $target,
+                       'target' => $target, // FIXME: type of $target changed 
to RevisionRecord!
                        'newid' => $revId
                ];
 
@@ -3324,10 +3450,12 @@
        /**
         * Purge caches on page update etc
         *
+        * @deprecated since 1.31, for internal use only.
+        *
         * @param Title $title
-        * @param Revision|null $revision Revision that was just saved, may be 
null
+        * @param Revision|RevisionRecord|null $revision Revision that was just 
saved, may be null
         */
-       public static function onArticleEdit( Title $title, Revision $revision 
= null ) {
+       public static function onArticleEdit( Title $title, $revision = null ) {
                // Invalidate caches of articles which include this page
                DeferredUpdates::addUpdate( new HTMLCacheUpdate( $title, 
'templatelinks' ) );
 
@@ -3584,7 +3712,7 @@
                        // load content object, which may be used to determine 
the necessary updates.
                        // XXX: the content may not be needed to determine the 
updates.
                        try {
-                               $content = $this->getContent( Revision::RAW );
+                               $content = $this->getContent( 
RevisionRecord::RAW );
                        } catch ( Exception $ex ) {
                                // If we can't load the content, something is 
wrong. Perhaps that's why
                                // the user is trying to delete the page, so 
let's not fail in that case.
diff --git a/includes/resourceloader/ResourceLoaderWikiModule.php 
b/includes/resourceloader/ResourceLoaderWikiModule.php
index 6eddfc0..9bf2f2e 100644
--- a/includes/resourceloader/ResourceLoaderWikiModule.php
+++ b/includes/resourceloader/ResourceLoaderWikiModule.php
@@ -22,6 +22,7 @@
  * @author Roan Kattouw
  */
 
+use Wikimedia\Assert\Assert;
 use Wikimedia\Rdbms\Database;
 use Wikimedia\Rdbms\IDatabase;
 
@@ -434,20 +435,27 @@
         * Clear the preloadTitleInfo() cache for all wiki modules on this wiki 
on
         * page change if it was a JS or CSS page
         *
+        * @warn Prior to 1.31, the second and third parameter took a Revision 
object.
+        * This was changed without backwards compatibility, since these 
parameters
+        * were unused outside of WikiPage.
+        *
         * @param Title $title
-        * @param Revision|null $old Prior page revision
-        * @param Revision|null $new New page revision
+        * @param string|null $oldModel Content model of the old revision's 
main slot
+        * @param string|null $newModel Content model of the new revision's 
main slot
         * @param string $wikiId
         * @since 1.28
         */
        public static function invalidateModuleCache(
-               Title $title, Revision $old = null, Revision $new = null, 
$wikiId
+               Title $title, $oldModel = null, $newModel = null, $wikiId
        ) {
-               static $formats = [ CONTENT_FORMAT_CSS, 
CONTENT_FORMAT_JAVASCRIPT ];
+               static $models = [ CONTENT_MODEL_CSS, CONTENT_MODEL_JAVASCRIPT 
];
 
-               if ( $old && in_array( $old->getContentFormat(), $formats ) ) {
+               Assert::parameterType( 'string|null', $oldModel, '$oldModel' );
+               Assert::parameterType( 'string|null', $newModel, '$newModel' );
+
+               if ( $oldModel && in_array( $oldModel, $models ) ) {
                        $purge = true;
-               } elseif ( $new && in_array( $new->getContentFormat(), $formats 
) ) {
+               } elseif ( $newModel && in_array( $newModel, $models ) ) {
                        $purge = true;
                } else {
                        $purge = ( $title->isCssOrJsPage() || 
$title->isCssJsSubpage() );

-- 
To view, visit https://gerrit.wikimedia.org/r/387640
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I29d817b682ed556875e1f520d410f0623a4cc15b
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Daniel Kinzler <daniel.kinz...@wikimedia.de>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to