Merge "Avoid calling Block::deleteIfExpired() when not needed"
[lhc/web/wiklou.git] / includes / page / Article.php
index 54db19c..af1f00b 100644 (file)
@@ -191,7 +191,7 @@ class Article implements Page {
        }
 
        /**
-        * Note that getContent/loadContent do not follow redirects anymore.
+        * Note that getContent does not follow redirects anymore.
         * If you need to fetch redirectable content easily, try
         * the shortcut in WikiPage::getRedirectTarget()
         *
@@ -212,7 +212,7 @@ class Article implements Page {
         * Returns a Content object representing the pages effective display content,
         * not necessarily the revision's content!
         *
-        * Note that getContent/loadContent do not follow redirects anymore.
+        * Note that getContent does not follow redirects anymore.
         * If you need to fetch redirectable content easily, try
         * the shortcut in WikiPage::getRedirectTarget()
         *
@@ -309,16 +309,6 @@ class Article implements Page {
                return $oldid;
        }
 
-       /**
-        * Load the revision (including text) into this object
-        *
-        * @deprecated since 1.19; use fetchContent()
-        */
-       function loadContent() {
-               wfDeprecated( __METHOD__, '1.19' );
-               $this->fetchContent();
-       }
-
        /**
         * Get text of an article from database
         * Does *NOT* follow redirects.
@@ -379,7 +369,7 @@ class Article implements Page {
 
                # Pre-fill content with error message so that if something
                # fails we'll have something telling us what we intended.
-               //XXX: this isn't page content but a UI message. horrible.
+               // XXX: this isn't page content but a UI message. horrible.
                $this->mContentObject = new MessageContent( 'missing-revision', array( $oldid ) );
 
                if ( $oldid ) {
@@ -696,7 +686,7 @@ class Article implements Page {
 
                                        # Don't cache a dirty ParserOutput object
                                        if ( $poolArticleView->getIsDirty() ) {
-                                               $outputPage->setSquidMaxage( 0 );
+                                               $outputPage->setCdnMaxage( 0 );
                                                $outputPage->addHTML( "<!-- parser cache is expired, " .
                                                        "sending anyway due to pool overload-->\n" );
                                        }
@@ -1075,7 +1065,6 @@ class Article implements Page {
 
                $outputPage = $this->getContext()->getOutput();
                $user = $this->getContext()->getUser();
-               $cache = wfGetMainCache();
                $rc = false;
 
                if ( !$this->getTitle()->quickUserCan( 'patrol', $user )
@@ -1091,11 +1080,6 @@ class Article implements Page {
                // to get the recentchanges row belonging to that entry
                // (with rc_new = 1).
 
-               // Check for cached results
-               if ( $cache->get( wfMemcKey( 'NotPatrollablePage', $this->getTitle()->getArticleID() ) ) ) {
-                       return false;
-               }
-
                if ( $this->mRevision
                        && !RecentChange::isInRCLifespan( $this->mRevision->getTimestamp(), 21600 )
                ) {
@@ -1104,6 +1088,13 @@ class Article implements Page {
                        return false;
                }
 
+               // Check for cached results
+               $key = wfMemcKey( 'unpatrollable-page', $this->getTitle()->getArticleID() );
+               $cache = ObjectCache::getMainWANInstance();
+               if ( $cache->get( $key ) ) {
+                       return false;
+               }
+
                $dbr = wfGetDB( DB_SLAVE );
                $oldestRevisionTimestamp = $dbr->selectField(
                        'revision',
@@ -1121,20 +1112,29 @@ class Article implements Page {
                                        'rc_new' => 1,
                                        'rc_timestamp' => $oldestRevisionTimestamp,
                                        'rc_namespace' => $this->getTitle()->getNamespace(),
-                                       'rc_cur_id' => $this->getTitle()->getArticleID(),
-                                       'rc_patrolled' => 0
+                                       'rc_cur_id' => $this->getTitle()->getArticleID()
                                ),
-                               __METHOD__,
-                               array( 'USE INDEX' => 'new_name_timestamp' )
+                               __METHOD__
                        );
+               } else {
+                       // Cache the information we gathered above in case we can't patrol
+                       // Don't cache in case we can patrol as this could change
+                       $cache->set( $key, '1' );
                }
 
                if ( !$rc ) {
-                       // No RC entry around
+                       // Don't cache: This can be hit if the page gets accessed very fast after
+                       // its creation or in case we have high slave lag. In case the revision is
+                       // too old, we will already return above.
+                       return false;
+               }
+
+               if ( $rc->getAttribute( 'rc_patrolled' ) ) {
+                       // Patrolled RC entry around
 
                        // Cache the information we gathered above in case we can't patrol
                        // Don't cache in case we can patrol as this could change
-                       $cache->set( wfMemcKey( 'NotPatrollablePage', $this->getTitle()->getArticleID() ), '1' );
+                       $cache->set( $key, '1' );
 
                        return false;
                }
@@ -1224,18 +1224,33 @@ class Article implements Page {
 
                Hooks::run( 'ShowMissingArticle', array( $this ) );
 
-               // Give extensions a chance to hide their (unrelated) log entries
-               $logTypes = array( 'delete', 'move' );
-               $conds = array( "log_action != 'revision'" );
-               Hooks::run( 'Article::MissingArticleConditions', array( &$conds, $logTypes ) );
-
-               # Show delete and move logs
-               LogEventsList::showLogExtract( $outputPage, $logTypes, $title, '',
-                       array( 'lim' => 10,
-                               'conds' => $conds,
-                               'showIfEmpty' => false,
-                               'msgKey' => array( 'moveddeleted-notice' ) )
-               );
+               # Show delete and move logs if there were any such events.
+               # The logging query can DOS the site when bots/crawlers cause 404 floods,
+               # so be careful showing this. 404 pages must be cheap as they are hard to cache.
+               $cache = ObjectCache::getMainStashInstance();
+               $key = wfMemcKey( 'page-recent-delete', md5( $title->getPrefixedText() ) );
+               $loggedIn = $this->getContext()->getUser()->isLoggedIn();
+               if ( $loggedIn || $cache->get( $key ) ) {
+                       $logTypes = array( 'delete', 'move' );
+                       $conds = array( "log_action != 'revision'" );
+                       // Give extensions a chance to hide their (unrelated) log entries
+                       Hooks::run( 'Article::MissingArticleConditions', array( &$conds, $logTypes ) );
+                       LogEventsList::showLogExtract(
+                               $outputPage,
+                               $logTypes,
+                               $title,
+                               '',
+                               array(
+                                       'lim' => 10,
+                                       'conds' => $conds,
+                                       'showIfEmpty' => false,
+                                       'msgKey' => array( $loggedIn
+                                               ? 'moveddeleted-notice'
+                                               : 'moveddeleted-notice-recent'
+                                       )
+                               )
+                       );
+               }
 
                if ( !$this->mPage->hasViewableContent() && $wgSend404Code && !$validUserPage ) {
                        // If there's no backing content, send a 404 Not Found
@@ -1911,7 +1926,7 @@ class Article implements Page {
         * @return ParserOutput|bool ParserOutput or false if the given revision ID is not found
         */
        public function getParserOutput( $oldid = null, User $user = null ) {
-               //XXX: bypasses mParserOptions and thus setParserOptions()
+               // XXX: bypasses mParserOptions and thus setParserOptions()
 
                if ( $user === null ) {
                        $parserOptions = $this->getParserOptions();
@@ -1984,7 +1999,7 @@ class Article implements Page {
         */
        public function __get( $fname ) {
                if ( property_exists( $this->mPage, $fname ) ) {
-                       #wfWarn( "Access to raw $fname field " . __CLASS__ );
+                       # wfWarn( "Access to raw $fname field " . __CLASS__ );
                        return $this->mPage->$fname;
                }
                trigger_error( 'Inaccessible property via __get(): ' . $fname, E_USER_NOTICE );
@@ -1999,7 +2014,7 @@ class Article implements Page {
         */
        public function __set( $fname, $fvalue ) {
                if ( property_exists( $this->mPage, $fname ) ) {
-                       #wfWarn( "Access to raw $fname field of " . __CLASS__ );
+                       # wfWarn( "Access to raw $fname field of " . __CLASS__ );
                        $this->mPage->$fname = $fvalue;
                // Note: extensions may want to toss on new fields
                } elseif ( !in_array( $fname, array( 'mContext', 'mPage' ) ) ) {
@@ -2019,7 +2034,7 @@ class Article implements Page {
         */
        public function __call( $fname, $args ) {
                if ( is_callable( array( $this->mPage, $fname ) ) ) {
-                       #wfWarn( "Call to " . __CLASS__ . "::$fname; please use WikiPage instead" );
+                       # wfWarn( "Call to " . __CLASS__ . "::$fname; please use WikiPage instead" );
                        return call_user_func_array( array( $this->mPage, $fname ), $args );
                }
                trigger_error( 'Inaccessible function via __call(): ' . $fname, E_USER_ERROR );
@@ -2063,15 +2078,15 @@ class Article implements Page {
        /**
         * @param string $reason
         * @param bool $suppress
-        * @param int $id
-        * @param bool $commit
+        * @param int $u1 Unused
+        * @param bool $u2 Unused
         * @param string $error
         * @return bool
         */
-       public function doDeleteArticle( $reason, $suppress = false, $id = 0,
-               $commit = true, &$error = ''
+       public function doDeleteArticle(
+               $reason, $suppress = false, $u1 = null, $u2 = null, &$error = ''
        ) {
-               return $this->mPage->doDeleteArticle( $reason, $suppress, $id, $commit, $error );
+               return $this->mPage->doDeleteArticle( $reason, $suppress, $u1, $u2, $error );
        }
 
        /**