Merge "Improve ExtensionRegistry test coverage"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Tue, 13 Feb 2018 04:45:01 +0000 (04:45 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Tue, 13 Feb 2018 04:45:01 +0000 (04:45 +0000)
includes/SiteStats.php
includes/SiteStatsInit.php
includes/deferred/SiteStatsUpdate.php
includes/installer/Installer.php
includes/page/WikiPage.php

index 0346f23..7b2b8d3 100644 (file)
 use Wikimedia\Rdbms\Database;
 use Wikimedia\Rdbms\IDatabase;
 use MediaWiki\MediaWikiServices;
+use Wikimedia\Rdbms\LoadBalancer;
 
 /**
  * Static accessor class for site_stats and related things
  */
 class SiteStats {
-       /** @var bool|stdClass */
+       /** @var stdClass */
        private static $row;
 
-       /** @var bool */
-       private static $loaded = false;
-       /** @var int[] */
-       private static $pageCount = [];
-
-       static function unload() {
-               self::$loaded = false;
-       }
-
-       static function recache() {
-               self::load( true );
-       }
-
        /**
-        * @param bool $recache
+        * Trigger a reload next time a field is accessed
         */
-       static function load( $recache = false ) {
-               if ( self::$loaded && !$recache ) {
-                       return;
-               }
-
-               self::$row = self::loadAndLazyInit();
+       public static function unload() {
+               self::$row = null;
+       }
 
-               self::$loaded = true;
+       protected static function load() {
+               if ( self::$row === null ) {
+                       self::$row = self::loadAndLazyInit();
+               }
        }
 
        /**
-        * @return bool|stdClass
+        * @return stdClass
         */
-       static function loadAndLazyInit() {
-               global $wgMiserMode;
+       protected static function loadAndLazyInit() {
+               $config = MediaWikiServices::getInstance()->getMainConfig();
 
+               $lb = self::getLB();
+               $dbr = $lb->getConnection( DB_REPLICA );
                wfDebug( __METHOD__ . ": reading site_stats from replica DB\n" );
-               $row = self::doLoad( wfGetDB( DB_REPLICA ) );
+               $row = self::doLoadFromDB( $dbr );
 
-               if ( !self::isSane( $row ) ) {
-                       $lb = MediaWikiServices::getInstance()->getDBLoadBalancer();
-                       if ( $lb->hasOrMadeRecentMasterChanges() ) {
-                               // Might have just been initialized during this request? Underflow?
-                               wfDebug( __METHOD__ . ": site_stats damaged or missing on replica DB\n" );
-                               $row = self::doLoad( wfGetDB( DB_MASTER ) );
-                       }
+               if ( !self::isSane( $row ) && $lb->hasOrMadeRecentMasterChanges() ) {
+                       // Might have just been initialized during this request? Underflow?
+                       wfDebug( __METHOD__ . ": site_stats damaged or missing on replica DB\n" );
+                       $row = self::doLoadFromDB( $lb->getConnection( DB_MASTER ) );
                }
 
                if ( !self::isSane( $row ) ) {
-                       if ( $wgMiserMode ) {
+                       if ( $config->get( 'MiserMode' ) ) {
                                // Start off with all zeroes, assuming that this is a new wiki or any
                                // repopulations where done manually via script.
                                SiteStatsInit::doPlaceholderInit();
@@ -86,14 +73,15 @@ class SiteStats {
                                // broken, however, for instance when importing from a dump into a
                                // clean schema with mwdumper.
                                wfDebug( __METHOD__ . ": initializing damaged or missing site_stats\n" );
-                               SiteStatsInit::doAllAndCommit( wfGetDB( DB_REPLICA ) );
+                               SiteStatsInit::doAllAndCommit( $dbr );
                        }
 
-                       $row = self::doLoad( wfGetDB( DB_MASTER ) );
+                       $row = self::doLoadFromDB( $lb->getConnection( DB_MASTER ) );
                }
 
                if ( !self::isSane( $row ) ) {
                        wfDebug( __METHOD__ . ": site_stats persistently nonsensical o_O\n" );
+                       // Always return a row-like object
                        $row = (object)array_fill_keys( self::selectFields(), 0 );
                }
 
@@ -102,9 +90,9 @@ class SiteStats {
 
        /**
         * @param IDatabase $db
-        * @return bool|stdClass
+        * @return stdClass|bool
         */
-       static function doLoad( $db ) {
+       private static function doLoadFromDB( IDatabase $db ) {
                return $db->selectRow(
                        'site_stats',
                        self::selectFields(),
@@ -114,63 +102,56 @@ class SiteStats {
        }
 
        /**
-        * Return the total number of page views. Except we don't track those anymore.
-        * Stop calling this function, it will be removed some time in the future. It's
-        * kept here simply to prevent fatal errors.
-        *
-        * @deprecated since 1.25
         * @return int
         */
-       static function views() {
-               wfDeprecated( __METHOD__, '1.25' );
-               return 0;
-       }
-
-       /**
-        * @return int
-        */
-       static function edits() {
+       public static function edits() {
                self::load();
+
                return self::$row->ss_total_edits;
        }
 
        /**
         * @return int
         */
-       static function articles() {
+       public static function articles() {
                self::load();
+
                return self::$row->ss_good_articles;
        }
 
        /**
         * @return int
         */
-       static function pages() {
+       public static function pages() {
                self::load();
+
                return self::$row->ss_total_pages;
        }
 
        /**
         * @return int
         */
-       static function users() {
+       public static function users() {
                self::load();
+
                return self::$row->ss_users;
        }
 
        /**
         * @return int
         */
-       static function activeUsers() {
+       public static function activeUsers() {
                self::load();
+
                return self::$row->ss_active_users;
        }
 
        /**
         * @return int
         */
-       static function images() {
+       public static function images() {
                self::load();
+
                return self::$row->ss_images;
        }
 
@@ -179,17 +160,17 @@ class SiteStats {
         * @param string $group Name of group
         * @return int
         */
-       static function numberingroup( $group ) {
+       public static function numberingroup( $group ) {
                $cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
+
                return $cache->getWithSetCallback(
                        $cache->makeKey( 'SiteStats', 'groupcounts', $group ),
                        $cache::TTL_HOUR,
                        function ( $oldValue, &$ttl, array &$setOpts ) use ( $group ) {
-                               $dbr = wfGetDB( DB_REPLICA );
-
+                               $dbr = self::getLB()->getConnection( DB_REPLICA );
                                $setOpts += Database::getCacheSetOptions( $dbr );
 
-                               return $dbr->selectField(
+                               return (int)$dbr->selectField(
                                        'user_groups',
                                        'COUNT(*)',
                                        [
@@ -207,8 +188,9 @@ class SiteStats {
         * Total number of jobs in the job queue.
         * @return int
         */
-       static function jobs() {
+       public static function jobs() {
                $cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
+
                return $cache->getWithSetCallback(
                        $cache->makeKey( 'SiteStats', 'jobscount' ),
                        $cache::TTL_MINUTE,
@@ -226,20 +208,27 @@ class SiteStats {
 
        /**
         * @param int $ns
-        *
         * @return int
         */
-       static function pagesInNs( $ns ) {
-               if ( !isset( self::$pageCount[$ns] ) ) {
-                       $dbr = wfGetDB( DB_REPLICA );
-                       self::$pageCount[$ns] = (int)$dbr->selectField(
-                               'page',
-                               'COUNT(*)',
-                               [ 'page_namespace' => $ns ],
-                               __METHOD__
-                       );
-               }
-               return self::$pageCount[$ns];
+       public static function pagesInNs( $ns ) {
+               $cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
+
+               return $cache->getWithSetCallback(
+                       $cache->makeKey( 'SiteStats', 'page-in-namespace', $ns ),
+                       $cache::TTL_HOUR,
+                       function ( $oldValue, &$ttl, array &$setOpts ) use ( $ns ) {
+                               $dbr = self::getLB()->getConnection( DB_REPLICA );
+                               $setOpts += Database::getCacheSetOptions( $dbr );
+
+                               return (int)$dbr->selectField(
+                                       'page',
+                                       'COUNT(*)',
+                                       [ 'page_namespace' => $ns ],
+                                       __METHOD__
+                               );
+                       },
+                       [ 'pcTTL' => $cache::TTL_PROC_LONG ]
+               );
        }
 
        /**
@@ -283,6 +272,14 @@ class SiteStats {
                                return false;
                        }
                }
+
                return true;
        }
+
+       /**
+        * @return LoadBalancer
+        */
+       private static function getLB() {
+               return MediaWikiServices::getInstance()->getDBLoadBalancer();
+       }
 }
index 775963f..f888690 100644 (file)
  * @file
  */
 use Wikimedia\Rdbms\IDatabase;
+use MediaWiki\MediaWikiServices;
 
 /**
  * Class designed for counting of stats.
  */
 class SiteStatsInit {
-
-       // Database connection
-       private $db;
-
-       // Various stats
-       private $mEdits = null, $mArticles = null, $mPages = null;
-       private $mUsers = null, $mFiles = null;
+       /* @var IDatabase */
+       private $dbr;
+       /** @var int */
+       private $edits;
+       /** @var int */
+       private $articles;
+       /** @var int */
+       private $pages;
+       /** @var int */
+       private $users;
+       /** @var int */
+       private $files;
 
        /**
         * @param bool|IDatabase $database
@@ -38,11 +44,11 @@ class SiteStatsInit {
         */
        public function __construct( $database = false ) {
                if ( $database instanceof IDatabase ) {
-                       $this->db = $database;
+                       $this->dbr = $database;
                } elseif ( $database ) {
-                       $this->db = wfGetDB( DB_MASTER );
+                       $this->dbr = self::getDB( DB_MASTER );
                } else {
-                       $this->db = wfGetDB( DB_REPLICA, 'vslow' );
+                       $this->dbr = self::getDB( DB_REPLICA, 'vslow' );
                }
        }
 
@@ -51,9 +57,10 @@ class SiteStatsInit {
         * @return int
         */
        public function edits() {
-               $this->mEdits = $this->db->selectField( 'revision', 'COUNT(*)', '', __METHOD__ );
-               $this->mEdits += $this->db->selectField( 'archive', 'COUNT(*)', '', __METHOD__ );
-               return $this->mEdits;
+               $this->edits = $this->dbr->selectField( 'revision', 'COUNT(*)', '', __METHOD__ );
+               $this->edits += $this->dbr->selectField( 'archive', 'COUNT(*)', '', __METHOD__ );
+
+               return $this->edits;
        }
 
        /**
@@ -61,7 +68,7 @@ class SiteStatsInit {
         * @return int
         */
        public function articles() {
-               global $wgArticleCountMethod;
+               $config = MediaWikiServices::getInstance()->getMainConfig();
 
                $tables = [ 'page' ];
                $conds = [
@@ -69,10 +76,10 @@ class SiteStatsInit {
                        'page_is_redirect' => 0,
                ];
 
-               if ( $wgArticleCountMethod == 'link' ) {
+               if ( $config->get( 'ArticleCountMethod' ) == 'link' ) {
                        $tables[] = 'pagelinks';
                        $conds[] = 'pl_from=page_id';
-               } elseif ( $wgArticleCountMethod == 'comma' ) {
+               } elseif ( $config->get( 'ArticleCountMethod' ) == 'comma' ) {
                        // To make a correct check for this, we would need, for each page,
                        // to load the text, maybe uncompress it, maybe decode it and then
                        // check if there's one comma.
@@ -81,9 +88,14 @@ class SiteStatsInit {
                        $conds[] = 'page_len > 0';
                }
 
-               $this->mArticles = $this->db->selectField( $tables, 'COUNT(DISTINCT page_id)',
-                       $conds, __METHOD__ );
-               return $this->mArticles;
+               $this->articles = $this->dbr->selectField(
+                       $tables,
+                       'COUNT(DISTINCT page_id)',
+                       $conds,
+                       __METHOD__
+               );
+
+               return $this->articles;
        }
 
        /**
@@ -91,8 +103,9 @@ class SiteStatsInit {
         * @return int
         */
        public function pages() {
-               $this->mPages = $this->db->selectField( 'page', 'COUNT(*)', '', __METHOD__ );
-               return $this->mPages;
+               $this->pages = $this->dbr->selectField( 'page', 'COUNT(*)', '', __METHOD__ );
+
+               return $this->pages;
        }
 
        /**
@@ -100,8 +113,9 @@ class SiteStatsInit {
         * @return int
         */
        public function users() {
-               $this->mUsers = $this->db->selectField( 'user', 'COUNT(*)', '', __METHOD__ );
-               return $this->mUsers;
+               $this->users = $this->dbr->selectField( 'user', 'COUNT(*)', '', __METHOD__ );
+
+               return $this->users;
        }
 
        /**
@@ -109,8 +123,9 @@ class SiteStatsInit {
         * @return int
         */
        public function files() {
-               $this->mFiles = $this->db->selectField( 'image', 'COUNT(*)', '', __METHOD__ );
-               return $this->mFiles;
+               $this->files = $this->dbr->selectField( 'image', 'COUNT(*)', '', __METHOD__ );
+
+               return $this->files;
        }
 
        /**
@@ -127,7 +142,7 @@ class SiteStatsInit {
                $options += [ 'update' => false, 'activeUsers' => false ];
 
                // Grab the object and count everything
-               $counter = new SiteStatsInit( $database );
+               $counter = new self( $database );
 
                $counter->edits();
                $counter->articles();
@@ -139,7 +154,7 @@ class SiteStatsInit {
 
                // Count active users if need be
                if ( $options['activeUsers'] ) {
-                       SiteStatsUpdate::cacheUpdate( wfGetDB( DB_MASTER ) );
+                       SiteStatsUpdate::cacheUpdate( self::getDB( DB_MASTER ) );
                }
        }
 
@@ -147,7 +162,7 @@ class SiteStatsInit {
         * Insert a dummy row with all zeroes if no row is present
         */
        public static function doPlaceholderInit() {
-               $dbw = wfGetDB( DB_MASTER );
+               $dbw = self::getDB( DB_MASTER );
                $exists = $dbw->selectField( 'site_stats', '1', [ 'ss_row_id' => 1 ],  __METHOD__ );
                if ( $exists === false ) {
                        $dbw->insert(
@@ -165,14 +180,27 @@ class SiteStatsInit {
        public function refresh() {
                $values = [
                        'ss_row_id' => 1,
-                       'ss_total_edits' => ( $this->mEdits === null ? $this->edits() : $this->mEdits ),
-                       'ss_good_articles' => ( $this->mArticles === null ? $this->articles() : $this->mArticles ),
-                       'ss_total_pages' => ( $this->mPages === null ? $this->pages() : $this->mPages ),
-                       'ss_users' => ( $this->mUsers === null ? $this->users() : $this->mUsers ),
-                       'ss_images' => ( $this->mFiles === null ? $this->files() : $this->mFiles ),
+                       'ss_total_edits' => $this->edits === null ? $this->edits() : $this->edits,
+                       'ss_good_articles' => $this->articles === null ? $this->articles() : $this->articles,
+                       'ss_total_pages' => $this->pages === null ? $this->pages() : $this->pages,
+                       'ss_users' => $this->users === null ? $this->users() : $this->users,
+                       'ss_images' => $this->files === null ? $this->files() : $this->files,
                ];
 
-               $dbw = wfGetDB( DB_MASTER );
-               $dbw->upsert( 'site_stats', $values, [ 'ss_row_id' ], $values, __METHOD__ );
+               self::getDB( DB_MASTER )->upsert(
+                       'site_stats',
+                       $values,
+                       [ 'ss_row_id' ],
+                       $values,
+                       __METHOD__
+               );
+       }
+
+       /**
+        * @param int $index
+        * @return IDatabase
+        */
+       private static function getDB( $index ) {
+               return MediaWikiServices::getInstance()->getDBLoadBalancer()->getConnection( $index );
        }
 }
index 44876a6..ad1f172 100644 (file)
@@ -25,6 +25,8 @@ use Wikimedia\Rdbms\IDatabase;
  * Class for handling updates to the site_stats table
  */
 class SiteStatsUpdate implements DeferrableUpdate, MergeableUpdate {
+       /** @var BagOStuff */
+       protected $stash;
        /** @var int */
        protected $edits = 0;
        /** @var int */
@@ -44,6 +46,8 @@ class SiteStatsUpdate implements DeferrableUpdate, MergeableUpdate {
                $this->articles = $good;
                $this->pages = $pages;
                $this->users = $users;
+
+               $this->stash = MediaWikiServices::getInstance()->getMainObjectStash();
        }
 
        public function merge( MergeableUpdate $update ) {
@@ -72,11 +76,9 @@ class SiteStatsUpdate implements DeferrableUpdate, MergeableUpdate {
        }
 
        public function doUpdate() {
-               global $wgSiteStatsAsyncFactor;
-
                $this->doUpdateContextStats();
 
-               $rate = $wgSiteStatsAsyncFactor; // convenience
+               $rate = MediaWikiServices::getInstance()->getMainConfig()->get( 'SiteStatsAsyncFactor' );
                // If set to do so, only do actual DB updates 1 every $rate times.
                // The other times, just update "pending delta" values in memcached.
                if ( $rate && ( $rate < 0 || mt_rand( 0, $rate - 1 ) != 0 ) ) {
@@ -91,12 +93,13 @@ class SiteStatsUpdate implements DeferrableUpdate, MergeableUpdate {
         * Do not call this outside of SiteStatsUpdate
         */
        public function tryDBUpdateInternal() {
-               global $wgSiteStatsAsyncFactor;
+               $services = MediaWikiServices::getInstance();
+               $config = $services->getMainConfig();
 
-               $dbw = wfGetDB( DB_MASTER );
-               $lockKey = wfWikiID() . ':site_stats'; // prepend wiki ID
+               $dbw = $services->getDBLoadBalancer()->getConnection( DB_MASTER );
+               $lockKey = $dbw->getDomainID() . ':site_stats'; // prepend wiki ID
                $pd = [];
-               if ( $wgSiteStatsAsyncFactor ) {
+               if ( $config->get( 'SiteStatsAsyncFactor' ) ) {
                        // Lock the table so we don't have double DB/memcached updates
                        if ( !$dbw->lockIsFree( $lockKey, __METHOD__ )
                                || !$dbw->lock( $lockKey, __METHOD__, 1 ) // 1 sec timeout
@@ -125,7 +128,7 @@ class SiteStatsUpdate implements DeferrableUpdate, MergeableUpdate {
                        $dbw->update( 'site_stats', [ $updates ], [], __METHOD__ );
                }
 
-               if ( $wgSiteStatsAsyncFactor ) {
+               if ( $config->get( 'SiteStatsAsyncFactor' ) ) {
                        // Decrement the async deltas now that we applied them
                        $this->removePendingDeltas( $pd );
                        // Commit the updates and unlock the table
@@ -140,9 +143,11 @@ class SiteStatsUpdate implements DeferrableUpdate, MergeableUpdate {
         * @param IDatabase $dbw
         * @return bool|mixed
         */
-       public static function cacheUpdate( $dbw ) {
-               global $wgActiveUserDays;
-               $dbr = wfGetDB( DB_REPLICA, 'vslow' );
+       public static function cacheUpdate( IDatabase $dbw ) {
+               $services = MediaWikiServices::getInstance();
+               $config = $services->getMainConfig();
+
+               $dbr = $services->getDBLoadBalancer()->getConnection( DB_REPLICA, 'vslow' );
                # Get non-bot users than did some recent action other than making accounts.
                # If account creation is included, the number gets inflated ~20+ fold on enwiki.
                $activeUsers = $dbr->selectField(
@@ -153,8 +158,8 @@ class SiteStatsUpdate implements DeferrableUpdate, MergeableUpdate {
                                'rc_user != 0',
                                'rc_bot' => 0,
                                'rc_log_type != ' . $dbr->addQuotes( 'newusers' ) . ' OR rc_log_type IS NULL',
-                               'rc_timestamp >= ' . $dbr->addQuotes( $dbr->timestamp( wfTimestamp( TS_UNIX )
-                                       - $wgActiveUserDays * 24 * 3600 ) ),
+                               'rc_timestamp >= ' . $dbr->addQuotes(
+                                       $dbr->timestamp( time() - $config->get( 'ActiveUserDays' ) * 24 * 3600 ) ),
                        ],
                        __METHOD__
                );
@@ -208,13 +213,13 @@ class SiteStatsUpdate implements DeferrableUpdate, MergeableUpdate {
        }
 
        /**
-        * @param BagOStuff $cache
+        * @param BagOStuff $stash
         * @param string $type
         * @param string $sign ('+' or '-')
         * @return string
         */
-       private function getTypeCacheKey( BagOStuff $cache, $type, $sign ) {
-               return $cache->makeKey( 'sitestatsupdate', 'pendingdelta', $type, $sign );
+       private function getTypeCacheKey( BagOStuff $stash, $type, $sign ) {
+               return $stash->makeKey( 'sitestatsupdate', 'pendingdelta', $type, $sign );
        }
 
        /**
@@ -224,15 +229,14 @@ class SiteStatsUpdate implements DeferrableUpdate, MergeableUpdate {
         * @param int $delta Delta (positive or negative)
         */
        protected function adjustPending( $type, $delta ) {
-               $cache = MediaWikiServices::getInstance()->getMainObjectStash();
                if ( $delta < 0 ) { // decrement
-                       $key = $this->getTypeCacheKey( $cache, $type, '-' );
+                       $key = $this->getTypeCacheKey( $this->stash, $type, '-' );
                } else { // increment
-                       $key = $this->getTypeCacheKey( $cache, $type, '+' );
+                       $key = $this->getTypeCacheKey( $this->stash, $type, '+' );
                }
 
                $magnitude = abs( $delta );
-               $cache->incrWithInit( $key, 0, $magnitude, $magnitude );
+               $this->stash->incrWithInit( $key, 0, $magnitude, $magnitude );
        }
 
        /**
@@ -240,16 +244,20 @@ class SiteStatsUpdate implements DeferrableUpdate, MergeableUpdate {
         * @return array Positive and negative deltas for each type
         */
        protected function getPendingDeltas() {
-               $cache = MediaWikiServices::getInstance()->getMainObjectStash();
-
                $pending = [];
                foreach ( [ 'ss_total_edits',
                        'ss_good_articles', 'ss_total_pages', 'ss_users', 'ss_images' ] as $type
                ) {
                        // Get pending increments and pending decrements
                        $flg = BagOStuff::READ_LATEST;
-                       $pending[$type]['+'] = (int)$cache->get( $this->getTypeCacheKey( $cache, $type, '+' ), $flg );
-                       $pending[$type]['-'] = (int)$cache->get( $this->getTypeCacheKey( $cache, $type, '-' ), $flg );
+                       $pending[$type]['+'] = (int)$this->stash->get(
+                               $this->getTypeCacheKey( $this->stash, $type, '+' ),
+                               $flg
+                       );
+                       $pending[$type]['-'] = (int)$this->stash->get(
+                               $this->getTypeCacheKey( $this->stash, $type, '-' ),
+                               $flg
+                       );
                }
 
                return $pending;
@@ -260,12 +268,11 @@ class SiteStatsUpdate implements DeferrableUpdate, MergeableUpdate {
         * @param array $pd Result of getPendingDeltas(), used for DB update
         */
        protected function removePendingDeltas( array $pd ) {
-               $cache = MediaWikiServices::getInstance()->getMainObjectStash();
-
                foreach ( $pd as $type => $deltas ) {
                        foreach ( $deltas as $sign => $magnitude ) {
                                // Lower the pending counter now that we applied these changes
-                               $cache->decr( $this->getTypeCacheKey( $cache, $type, $sign ), $magnitude );
+                               $key = $this->getTypeCacheKey( $this->stash, $type, $sign );
+                               $this->stash->decr( $key, $magnitude );
                        }
                }
        }
index f22b63d..dbd143c 100644 (file)
@@ -1564,7 +1564,7 @@ abstract class Installer {
                        $user->saveSettings();
 
                        // Update user count
-                       $ssUpdate = new SiteStatsUpdate( 0, 0, 0, 0, 1 );
+                       $ssUpdate = SiteStatsUpdate::factory( [ 'users' => 1 ] );
                        $ssUpdate->doUpdate();
                }
                $status = Status::newGood();
index a7eed5a..c7bb8ec 100644 (file)
@@ -2271,7 +2271,9 @@ class WikiPage implements Page, IDBAccessObject {
                $edits = $options['changed'] ? 1 : 0;
                $total = $options['created'] ? 1 : 0;
 
-               DeferredUpdates::addUpdate( new SiteStatsUpdate( 0, $edits, $good, $total ) );
+               DeferredUpdates::addUpdate( SiteStatsUpdate::factory(
+                       [ 'edits' => $edits, 'articles' => $good, 'total' => $total ]
+               ) );
                DeferredUpdates::addUpdate( new SearchUpdate( $id, $title, $content ) );
 
                // If this is another user's talk page, update newtalk.
@@ -3018,7 +3020,9 @@ class WikiPage implements Page, IDBAccessObject {
                }
 
                // Update site status
-               DeferredUpdates::addUpdate( new SiteStatsUpdate( 0, 1, - (int)$countable, -1 ) );
+               DeferredUpdates::addUpdate( SiteStatsUpdate::factory(
+                       [ 'edits' => 1, 'articles' => -$countable, 'pages' => -1 ]
+               ) );
 
                // Delete pagelinks, update secondary indexes, etc
                $updates = $this->getDeletionUpdates( $content );