Avoid duplicate refreshCounts() updates
authorAaron Schulz <aschulz@wikimedia.org>
Wed, 10 May 2017 22:38:00 +0000 (15:38 -0700)
committerAaron Schulz <aschulz@wikimedia.org>
Wed, 10 May 2017 22:38:00 +0000 (15:38 -0700)
The refresh method uses the initialize() method, which itself
might trigger the refresh method again after the row is created.

Change-Id: I6702bebea66fcb8b94cd2e6a496e55f52fa70b69

includes/Category.php

index 50ffeec..5c7cb8d 100644 (file)
@@ -40,15 +40,19 @@ class Category {
        /** Counts of membership (cat_pages, cat_subcats, cat_files) */
        private $mPages = null, $mSubcats = null, $mFiles = null;
 
+       const LOAD_ONLY = 0;
+       const LAZY_INIT_ROW = 1;
+
        private function __construct() {
        }
 
        /**
         * Set up all member variables using a database query.
+        * @param integer $mode
         * @throws MWException
         * @return bool True on success, false on failure.
         */
-       protected function initialize() {
+       protected function initialize( $mode = self::LOAD_ONLY ) {
                if ( $this->mName === null && $this->mID === null ) {
                        throw new MWException( __METHOD__ . ' has both names and IDs null' );
                } elseif ( $this->mID === null ) {
@@ -80,7 +84,7 @@ class Category {
                                $this->mFiles = 0;
 
                                # If the title exists, call refreshCounts to add a row for it.
-                               if ( $this->mTitle->exists() ) {
+                               if ( $mode === self::LAZY_INIT_ROW && $this->mTitle->exists() ) {
                                        DeferredUpdates::addCallableUpdate( [ $this, 'refreshCounts' ] );
                                }
 
@@ -104,7 +108,9 @@ class Category {
                        $this->mSubcats = max( $this->mSubcats, 0 );
                        $this->mFiles = max( $this->mFiles, 0 );
 
-                       DeferredUpdates::addCallableUpdate( [ $this, 'refreshCounts' ] );
+                       if ( $mode === self::LAZY_INIT_ROW ) {
+                               DeferredUpdates::addCallableUpdate( [ $this, 'refreshCounts' ] );
+                       }
                }
 
                return true;
@@ -247,7 +253,7 @@ class Category {
                        return $this->mTitle;
                }
 
-               if ( !$this->initialize() ) {
+               if ( !$this->initialize( self::LAZY_INIT_ROW ) ) {
                        return false;
                }
 
@@ -258,7 +264,7 @@ class Category {
        /**
         * Fetch a TitleArray of up to $limit category members, beginning after the
         * category sort key $offset.
-        * @param int $limit
+        * @param int|bool $limit
         * @param string $offset
         * @return TitleArray TitleArray object for category members.
         */
@@ -297,7 +303,7 @@ class Category {
         * @return bool
         */
        private function getX( $key ) {
-               if ( !$this->initialize() ) {
+               if ( !$this->initialize( self::LAZY_INIT_ROW ) ) {
                        return false;
                }
                return $this->{$key};
@@ -316,7 +322,7 @@ class Category {
                # If we have just a category name, find out whether there is an
                # existing row. Or if we have just an ID, get the name, because
                # that's what categorylinks uses.
-               if ( !$this->initialize() ) {
+               if ( !$this->initialize( self::LOAD_ONLY ) ) {
                        return false;
                }
 
@@ -325,7 +331,7 @@ class Category {
                $name = __METHOD__ . ':' . md5( $this->mName );
                $scopedLock = $dbw->getScopedLockAndFlush( $name, __METHOD__, 1 );
                if ( !$scopedLock ) {
-                       return;
+                       return false;
                }
 
                $dbw->startAtomic( __METHOD__ );