Merge "Implement WikiPage::getOldestRevision() in terms of Title::getFirstRevision()"
[lhc/web/wiklou.git] / includes / page / WikiPage.php
index 1c1412a..7044e6a 100644 (file)
@@ -22,6 +22,8 @@
 
 use \MediaWiki\Logger\LoggerFactory;
 use \MediaWiki\MediaWikiServices;
+use Wikimedia\Rdbms\FakeResultWrapper;
+use Wikimedia\Rdbms\IDatabase;
 
 /**
  * Class representing a MediaWiki article and history.
@@ -83,9 +85,10 @@ class WikiPage implements Page, IDBAccessObject {
         */
        protected $mLinksUpdated = '19700101000000';
 
-       const PURGE_CDN_CACHE = 1; // purge CDN cache for page variant URLs
-       const PURGE_CLUSTER_PCACHE = 2; // purge parser cache in the local datacenter
-       const PURGE_GLOBAL_PCACHE = 4; // set page_touched to clear parser cache in all datacenters
+       /** @deprecated since 1.29. Added in 1.28 for partial purging, no longer used. */
+       const PURGE_CDN_CACHE = 1;
+       const PURGE_CLUSTER_PCACHE = 2;
+       const PURGE_GLOBAL_PCACHE = 4;
        const PURGE_ALL = 7;
 
        /**
@@ -151,7 +154,7 @@ class WikiPage implements Page, IDBAccessObject {
         * @return WikiPage|null
         */
        public static function newFromID( $id, $from = 'fromdb' ) {
-               // page id's are never 0 or negative, see bug 61166
+               // page ids are never 0 or negative, see T63166
                if ( $id < 1 ) {
                        return null;
                }
@@ -257,7 +260,7 @@ class WikiPage implements Page, IDBAccessObject {
                $this->mTimestamp = '';
                $this->mIsRedirect = false;
                $this->mLatest = false;
-               // Bug 57026: do not clear mPreparedEdit since prepareTextForEdit() already checks
+               // T59026: do not clear mPreparedEdit since prepareTextForEdit() already checks
                // the requested rev ID and content against the cached one for equality. For most
                // content types, the output should not change during the lifetime of this cache.
                // Clearing it can cause extra parses on edit for no reason.
@@ -323,7 +326,7 @@ class WikiPage implements Page, IDBAccessObject {
 
                $row = $dbr->selectRow( 'page', $fields, $conditions, __METHOD__, $options );
 
-               Hooks::run( 'ArticlePageDataAfter', [ &$this, &$row ] );
+               Hooks::run( 'ArticlePageDataAfter', [ &$wikiPage, &$row ] );
 
                return $row;
        }
@@ -424,7 +427,7 @@ class WikiPage implements Page, IDBAccessObject {
                        $this->mLinksUpdated = wfTimestampOrNull( TS_MW, $data->page_links_updated );
                        $this->mIsRedirect = intval( $data->page_is_redirect );
                        $this->mLatest = intval( $data->page_latest );
-                       // Bug 37225: $latest may no longer match the cached latest Revision object.
+                       // 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 ) {
                                $this->mLastRevision = null;
@@ -573,37 +576,12 @@ class WikiPage implements Page, IDBAccessObject {
         * @return Revision|null
         */
        public function getOldestRevision() {
-
                // Try using the replica DB first, then try the master
-               $continue = 2;
-               $db = wfGetDB( DB_REPLICA );
-               $revSelectFields = Revision::selectFields();
-
-               $row = null;
-               while ( $continue ) {
-                       $row = $db->selectRow(
-                               [ 'page', 'revision' ],
-                               $revSelectFields,
-                               [
-                                       'page_namespace' => $this->mTitle->getNamespace(),
-                                       'page_title' => $this->mTitle->getDBkey(),
-                                       'rev_page = page_id'
-                               ],
-                               __METHOD__,
-                               [
-                                       'ORDER BY' => 'rev_timestamp ASC'
-                               ]
-                       );
-
-                       if ( $row ) {
-                               $continue = 0;
-                       } else {
-                               $db = wfGetDB( DB_MASTER );
-                               $continue--;
-                       }
+               $rev = $this->mTitle->getFirstRevision();
+               if ( !$rev ) {
+                       $rev = $this->mTitle->getFirstRevision( Title::GAID_FOR_UPDATE );
                }
-
-               return $row ? Revision::newFromRow( $row ) : null;
+               return $rev;
        }
 
        /**
@@ -621,7 +599,7 @@ class WikiPage implements Page, IDBAccessObject {
                }
 
                if ( $this->mDataLoadedFrom == self::READ_LOCKING ) {
-                       // Bug 37225: if session S1 loads the page row FOR UPDATE, the result always
+                       // T39225: if session S1 loads the page row FOR UPDATE, the result always
                        // includes the latest changes committed. This is true even within REPEATABLE-READ
                        // transactions, where S1 normally only sees changes committed before the first S1
                        // SELECT. Thus we need S1 to also gets the revision row FOR UPDATE; otherwise, it
@@ -1120,10 +1098,11 @@ class WikiPage implements Page, IDBAccessObject {
 
        /**
         * Perform the actions of a page purging
-        * @param integer $flags Bitfield of WikiPage::PURGE_* constants
         * @return bool
+        * @note In 1.28 (and only 1.28), this took a $flags parameter that
+        *  controlled how much purging was done.
         */
-       public function doPurge( $flags = self::PURGE_ALL ) {
+       public function doPurge() {
                // Avoid PHP 7.1 warning of passing $this by reference
                $wikiPage = $this;
 
@@ -1131,30 +1110,15 @@ class WikiPage implements Page, IDBAccessObject {
                        return false;
                }
 
-               if ( ( $flags & self::PURGE_GLOBAL_PCACHE ) == self::PURGE_GLOBAL_PCACHE ) {
-                       // Set page_touched in the database to invalidate all DC caches
-                       $this->mTitle->invalidateCache();
-               } elseif ( ( $flags & self::PURGE_CLUSTER_PCACHE ) == self::PURGE_CLUSTER_PCACHE ) {
-                       // Delete the parser options key in the local cluster to invalidate the DC cache
-                       ParserCache::singleton()->deleteOptionsKey( $this );
-                       // Avoid sending HTTP 304s in ViewAction to the client who just issued the purge
-                       $cache = ObjectCache::getLocalClusterInstance();
-                       $cache->set(
-                               $cache->makeKey( 'page', 'last-dc-purge', $this->getId() ),
-                               wfTimestamp( TS_MW ),
-                               $cache::TTL_HOUR
-                       );
-               }
+               $this->mTitle->invalidateCache();
 
-               if ( ( $flags & self::PURGE_CDN_CACHE ) == self::PURGE_CDN_CACHE ) {
-                       // Clear any HTML file cache
-                       HTMLFileCache::clearFileCache( $this->getTitle() );
-                       // Send purge after any page_touched above update was committed
-                       DeferredUpdates::addUpdate(
-                               new CdnCacheUpdate( $this->mTitle->getCdnUrls() ),
-                               DeferredUpdates::PRESEND
-                       );
-               }
+               // Clear file cache
+               HTMLFileCache::clearFileCache( $this->getTitle() );
+               // Send purge after above page_touched update was committed
+               DeferredUpdates::addUpdate(
+                       new CdnCacheUpdate( $this->mTitle->getCdnUrls() ),
+                       DeferredUpdates::PRESEND
+               );
 
                if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
                        $messageCache = MessageCache::singleton();
@@ -1169,11 +1133,11 @@ class WikiPage implements Page, IDBAccessObject {
         *
         * @return string|bool TS_MW timestamp or false
         * @since 1.28
+        * @deprecated since 1.29. It will always return false.
         */
        public function getLastPurgeTimestamp() {
-               $cache = ObjectCache::getLocalClusterInstance();
-
-               return $cache->get( $cache->makeKey( 'page', 'last-dc-purge', $this->getId() ) );
+               wfDeprecated( __METHOD__, '1.29' );
+               return false;
        }
 
        /**
@@ -1462,7 +1426,7 @@ class WikiPage implements Page, IDBAccessObject {
                                        $this->getContentHandler()->getModelID() );
                        }
 
-                       // Bug 30711: always use current version when adding a new section
+                       // T32711: always use current version when adding a new section
                        if ( is_null( $baseRevId ) || $sectionId === 'new' ) {
                                $oldContent = $this->getContent();
                        } else {
@@ -1697,7 +1661,7 @@ class WikiPage implements Page, IDBAccessObject {
 
                        return $status;
                } elseif ( !$oldContent ) {
-                       // Sanity check for bug 37225
+                       // Sanity check for T39225
                        throw new MWException( "Could not find text for current revision {$oldid}." );
                }
 
@@ -1785,7 +1749,7 @@ class WikiPage implements Page, IDBAccessObject {
                        $dbw->endAtomic( __METHOD__ );
                        $this->mTimestamp = $now;
                } else {
-                       // Bug 32948: revision ID must be set to page {{REVISIONID}} and
+                       // T34948: revision ID must be set to page {{REVISIONID}} and
                        // related variables correctly. Likewise for {{REVISIONUSER}} (T135261).
                        $revision->setId( $this->getLatest() );
                        $revision->setUserIdAndName(
@@ -2025,7 +1989,7 @@ class WikiPage implements Page, IDBAccessObject {
                $user = is_null( $user ) ? $wgUser : $user;
                // XXX: check $user->getId() here???
 
-               // Use a sane default for $serialFormat, see bug 57026
+               // Use a sane default for $serialFormat, see T59026
                if ( $serialFormat === null ) {
                        $serialFormat = $content->getContentHandler()->getDefaultFormat();
                }
@@ -2197,7 +2161,7 @@ class WikiPage implements Page, IDBAccessObject {
 
                // Update the links tables and other secondary data
                if ( $content ) {
-                       $recursive = $options['changed']; // bug 50785
+                       $recursive = $options['changed']; // T52785
                        $updates = $content->getSecondaryDataUpdates(
                                $this->getTitle(), null, $recursive, $editInfo->output
                        );
@@ -2299,7 +2263,7 @@ class WikiPage implements Page, IDBAccessObject {
 
                if ( $options['created'] ) {
                        self::onArticleCreate( $this->mTitle );
-               } elseif ( $options['changed'] ) { // bug 50785
+               } elseif ( $options['changed'] ) { // T52785
                        self::onArticleEdit( $this->mTitle, $revision );
                }
 
@@ -2913,7 +2877,7 @@ class WikiPage implements Page, IDBAccessObject {
 
                $dbw->onTransactionPreCommitOrIdle(
                        function () use ( $dbw, $logEntry, $logid ) {
-                               // Bug 56776: avoid deadlocks (especially from FileDeleteForm)
+                               // T58776: avoid deadlocks (especially from FileDeleteForm)
                                $logEntry->publish( $logid );
                        },
                        __METHOD__
@@ -3193,7 +3157,7 @@ class WikiPage implements Page, IDBAccessObject {
                );
 
                // Set patrolling and bot flag on the edits, which gets rollbacked.
-               // This is done even on edit failure to have patrolling in that case (bug 62157).
+               // This is done even on edit failure to have patrolling in that case (T64157).
                $set = [];
                if ( $bot && $guser->isAllowed( 'markbotedits' ) ) {
                        // Mark all reverted edits as bot