Cache NS_TEMPLATE/NS_FILE titles in LinkCache persistently
[lhc/web/wiklou.git] / includes / page / WikiPage.php
index e1d9f99..f1e59de 100644 (file)
@@ -21,6 +21,7 @@
  */
 
 use \MediaWiki\Logger\LoggerFactory;
+use \MediaWiki\MediaWikiServices;
 
 /**
  * Class representing a MediaWiki article and history.
@@ -134,7 +135,7 @@ class WikiPage implements Page, IDBAccessObject {
         *
         * @param int $id Article ID to load
         * @param string|int $from One of the following values:
-        *        - "fromdb" or WikiPage::READ_NORMAL to select from a slave database
+        *        - "fromdb" or WikiPage::READ_NORMAL to select from a replica DB
         *        - "fromdbmaster" or WikiPage::READ_LATEST to select from the master database
         *
         * @return WikiPage|null
@@ -146,7 +147,7 @@ class WikiPage implements Page, IDBAccessObject {
                }
 
                $from = self::convertSelectType( $from );
-               $db = wfGetDB( $from === self::READ_LATEST ? DB_MASTER : DB_SLAVE );
+               $db = wfGetDB( $from === self::READ_LATEST ? DB_MASTER : DB_REPLICA );
                $row = $db->selectRow(
                        'page', self::selectFields(), [ 'page_id' => $id ], __METHOD__ );
                if ( !$row ) {
@@ -161,7 +162,7 @@ class WikiPage implements Page, IDBAccessObject {
         * @since 1.20
         * @param object $row Database row containing at least fields returned by selectFields().
         * @param string|int $from Source of $data:
-        *        - "fromdb" or WikiPage::READ_NORMAL: from a slave DB
+        *        - "fromdb" or WikiPage::READ_NORMAL: from a replica DB
         *        - "fromdbmaster" or WikiPage::READ_LATEST: from the master DB
         *        - "forupdate" or WikiPage::READ_LOCKING: from the master DB using SELECT FOR UPDATE
         * @return WikiPage
@@ -346,7 +347,7 @@ class WikiPage implements Page, IDBAccessObject {
         *
         * @param object|string|int $from One of the following:
         *   - A DB query result object.
-        *   - "fromdb" or WikiPage::READ_NORMAL to get from a slave DB.
+        *   - "fromdb" or WikiPage::READ_NORMAL to get from a replica DB.
         *   - "fromdbmaster" or WikiPage::READ_LATEST to get from the master DB.
         *   - "forupdate"  or WikiPage::READ_LOCKING to get from the master DB
         *     using SELECT FOR UPDATE.
@@ -365,7 +366,7 @@ class WikiPage implements Page, IDBAccessObject {
                        $data = $this->pageDataFromTitle( wfGetDB( $index ), $this->mTitle, $opts );
 
                        if ( !$data
-                               && $index == DB_SLAVE
+                               && $index == DB_REPLICA
                                && wfGetLB()->getServerCount() > 1
                                && wfGetLB()->hasOrMadeRecentMasterChanges()
                        ) {
@@ -374,7 +375,7 @@ class WikiPage implements Page, IDBAccessObject {
                                $data = $this->pageDataFromTitle( wfGetDB( $index ), $this->mTitle, $opts );
                        }
                } else {
-                       // No idea from where the caller got this data, assume slave database.
+                       // No idea from where the caller got this data, assume replica DB.
                        $data = $from;
                        $from = self::READ_NORMAL;
                }
@@ -388,7 +389,7 @@ class WikiPage implements Page, IDBAccessObject {
         * @since 1.20
         * @param object|bool $data DB row containing fields returned by selectFields() or false
         * @param string|int $from One of the following:
-        *        - "fromdb" or WikiPage::READ_NORMAL if the data comes from a slave DB
+        *        - "fromdb" or WikiPage::READ_NORMAL if the data comes from a replica DB
         *        - "fromdbmaster" or WikiPage::READ_LATEST if the data comes from the master DB
         *        - "forupdate"  or WikiPage::READ_LOCKING if the data comes from
         *          the master DB using SELECT FOR UPDATE
@@ -552,9 +553,9 @@ class WikiPage implements Page, IDBAccessObject {
         */
        public function getOldestRevision() {
 
-               // Try using the slave database first, then try the master
+               // Try using the replica DB first, then try the master
                $continue = 2;
-               $db = wfGetDB( DB_SLAVE );
+               $db = wfGetDB( DB_REPLICA );
                $revSelectFields = Revision::selectFields();
 
                $row = null;
@@ -609,7 +610,7 @@ class WikiPage implements Page, IDBAccessObject {
                        $flags = Revision::READ_LOCKING;
                } 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 slave DB.
+                       // 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;
                } else {
@@ -831,7 +832,7 @@ class WikiPage implements Page, IDBAccessObject {
                                // links.
                                $hasLinks = (bool)count( $editInfo->output->getLinks() );
                        } else {
-                               $hasLinks = (bool)wfGetDB( DB_SLAVE )->selectField( 'pagelinks', 1,
+                               $hasLinks = (bool)wfGetDB( DB_REPLICA )->selectField( 'pagelinks', 1,
                                        [ 'pl_from' => $this->getId() ], __METHOD__ );
                        }
                }
@@ -856,7 +857,7 @@ class WikiPage implements Page, IDBAccessObject {
                }
 
                // Query the redirect table
-               $dbr = wfGetDB( DB_SLAVE );
+               $dbr = wfGetDB( DB_REPLICA );
                $row = $dbr->selectRow( 'redirect',
                        [ 'rd_namespace', 'rd_title', 'rd_fragment', 'rd_interwiki' ],
                        [ 'rd_from' => $this->getId() ],
@@ -989,7 +990,7 @@ class WikiPage implements Page, IDBAccessObject {
        public function getContributors() {
                // @todo FIXME: This is expensive; cache this info somewhere.
 
-               $dbr = wfGetDB( DB_SLAVE );
+               $dbr = wfGetDB( DB_REPLICA );
 
                if ( $dbr->implicitGroupby() ) {
                        $realNameField = 'user_real_name';
@@ -1386,7 +1387,7 @@ class WikiPage implements Page, IDBAccessObject {
 
                $baseRevId = null;
                if ( $edittime && $sectionId !== 'new' ) {
-                       $dbr = wfGetDB( DB_SLAVE );
+                       $dbr = wfGetDB( DB_REPLICA );
                        $rev = Revision::loadFromTimestamp( $dbr, $this->mTitle, $edittime );
                        // Try the master if this thread may have just added it.
                        // This could be abstracted into a Revision method, but we don't want
@@ -2110,7 +2111,7 @@ class WikiPage implements Page, IDBAccessObject {
                                // We get here if vary-revision is set. This means that this page references
                                // itself (such as via self-transclusion). In this case, we need to make sure
                                // that any such self-references refer to the newly-saved revision, and not
-                               // to the previous one, which could otherwise happen due to slave lag.
+                               // to the previous one, which could otherwise happen due to replica DB lag.
                                $oldCallback = $edit->popts->getCurrentRevisionCallback();
                                $edit->popts->setCurrentRevisionCallback(
                                        function ( Title $title, $parser = false ) use ( $revision, &$oldCallback ) {
@@ -2713,14 +2714,14 @@ class WikiPage implements Page, IDBAccessObject {
                $protectDescription = '';
 
                foreach ( array_filter( $limit ) as $action => $restrictions ) {
-                       # $action is one of $wgRestrictionTypes = array( 'create', 'edit', 'move', 'upload' ).
+                       # $action is one of $wgRestrictionTypes = [ 'create', 'edit', 'move', 'upload' ].
                        # All possible message keys are listed here for easier grepping:
                        # * restriction-create
                        # * restriction-edit
                        # * restriction-move
                        # * restriction-upload
                        $actionText = wfMessage( 'restriction-' . $action )->inContentLanguage()->text();
-                       # $restrictions is one of $wgRestrictionLevels = array( '', 'autoconfirmed', 'sysop' ),
+                       # $restrictions is one of $wgRestrictionLevels = [ '', 'autoconfirmed', 'sysop' ],
                        # with '' filtered out. All possible message keys are listed below:
                        # * protect-level-autoconfirmed
                        # * protect-level-sysop
@@ -2900,8 +2901,9 @@ class WikiPage implements Page, IDBAccessObject {
                        $bitfield |= Revision::DELETED_COMMENT;
                        $bitfield |= Revision::DELETED_USER;
                        $bitfield |= Revision::DELETED_RESTRICTED;
+                       $deletionFields = [ $dbw->addQuotes( $bitfield ) . ' AS deleted' ];
                } else {
-                       $bitfield = 'rev_deleted';
+                       $deletionFields = [ 'rev_deleted AS deleted' ];
                }
 
                // For now, shunt the revision data into the archive table.
@@ -2912,9 +2914,10 @@ class WikiPage implements Page, IDBAccessObject {
                // the rev_deleted field, which is reserved for this purpose.
 
                // Get all of the page revisions
+               $fields = array_diff( Revision::selectFields(), [ 'rev_deleted' ] );
                $res = $dbw->select(
                        'revision',
-                       Revision::selectFields(),
+                       array_merge( $fields, $deletionFields ),
                        [ 'rev_page' => $id ],
                        __METHOD__,
                        'FOR UPDATE'
@@ -2937,7 +2940,7 @@ class WikiPage implements Page, IDBAccessObject {
                                'ar_flags'      => '',
                                'ar_len'        => $row->rev_len,
                                'ar_page_id'    => $id,
-                               'ar_deleted'    => $bitfield,
+                               'ar_deleted'    => $row->deleted,
                                'ar_sha1'       => $row->rev_sha1,
                        ];
                        if ( $wgContentHandlerUseDB ) {
@@ -3319,9 +3322,11 @@ class WikiPage implements Page, IDBAccessObject {
                $title->purgeSquid();
                $title->deleteTitleProtection();
 
+               MediaWikiServices::getInstance()->getLinkCache()->invalidateTitle( $title );
+
                if ( $title->getNamespace() == NS_CATEGORY ) {
                        // Load the Category object, which will schedule a job to create
-                       // the category table row if necessary. Checking a slave is ok
+                       // the category table row if necessary. Checking a replica DB is ok
                        // here, in the worst case it'll run an unnecessary recount job on
                        // a category that probably doesn't have many members.
                        Category::newFromTitle( $title )->getID();
@@ -3344,6 +3349,8 @@ class WikiPage implements Page, IDBAccessObject {
                $title->touchLinks();
                $title->purgeSquid();
 
+               MediaWikiServices::getInstance()->getLinkCache()->invalidateTitle( $title );
+
                // File cache
                HTMLFileCache::clearFileCache( $title );
                InfoAction::invalidateCache( $title );
@@ -3387,6 +3394,8 @@ class WikiPage implements Page, IDBAccessObject {
                // Invalidate the caches of all pages which redirect here
                DeferredUpdates::addUpdate( new HTMLCacheUpdate( $title, 'redirect' ) );
 
+               MediaWikiServices::getInstance()->getLinkCache()->invalidateTitle( $title );
+
                // Purge CDN for this page only
                $title->purgeSquid();
                // Clear file cache for this page only
@@ -3412,7 +3421,7 @@ class WikiPage implements Page, IDBAccessObject {
                        return TitleArray::newFromResult( new FakeResultWrapper( [] ) );
                }
 
-               $dbr = wfGetDB( DB_SLAVE );
+               $dbr = wfGetDB( DB_REPLICA );
                $res = $dbr->select( 'categorylinks',
                        [ 'cl_to AS page_title, ' . NS_CATEGORY . ' AS page_namespace' ],
                        // Have to do that since DatabaseBase::fieldNamesWithAlias treats numeric indexes
@@ -3437,7 +3446,7 @@ class WikiPage implements Page, IDBAccessObject {
                        return [];
                }
 
-               $dbr = wfGetDB( DB_SLAVE );
+               $dbr = wfGetDB( DB_REPLICA );
                $res = $dbr->select( [ 'categorylinks', 'page_props', 'page' ],
                        [ 'cl_to' ],
                        [ 'cl_from' => $id, 'pp_page=page_id', 'pp_propname' => 'hiddencat',