Rename PhpBugTests -> PhpXMLBugTester
[lhc/web/wiklou.git] / includes / Category.php
index fe3dd0d..77f1212 100644 (file)
@@ -25,8 +25,6 @@
  * Category objects are immutable, strictly speaking. If you call methods that change the database,
  * like to refresh link counts, the objects will be appropriately reinitialized.
  * Member variables are lazy-initialized.
- *
- * @todo Move some stuff from CategoryPage.php to here, and use that.
  */
 class Category {
        /** Name of the category, normalized to DB-key form */
@@ -299,10 +297,10 @@ class Category {
        /**
         * Generic accessor
         * @param string $key
-        * @return bool
+        * @return mixed
         */
        private function getX( $key ) {
-               if ( !$this->initialize( self::LAZY_INIT_ROW ) ) {
+               if ( $this->{$key} === null && !$this->initialize( self::LAZY_INIT_ROW ) ) {
                        return false;
                }
                return $this->{$key};
@@ -337,13 +335,7 @@ class Category {
 
                // Lock the `category` row before locking `categorylinks` rows to try
                // to avoid deadlocks with LinksDeletionUpdate (T195397)
-               $dbw->selectField(
-                       'category',
-                       1,
-                       [ 'cat_title' => $this->mName ],
-                       __METHOD__,
-                       [ 'FOR UPDATE' ]
-               );
+               $dbw->lockForUpdate( 'category', [ 'cat_title' => $this->mName ], __METHOD__ );
 
                // Lock all the `categorylinks` records and gaps for this category;
                // this is a separate query due to postgres/oracle limitations
@@ -426,4 +418,45 @@ class Category {
 
                return true;
        }
+
+       /**
+        * Call refreshCounts() if there are no entries in the categorylinks table
+        * or if the category table has a row that states that there are no entries
+        *
+        * Due to lock errors or other failures, the precomputed counts can get out of sync,
+        * making it hard to know when to delete the category row without checking the
+        * categorylinks table.
+        *
+        * @return bool Whether links were refreshed
+        * @since 1.32
+        */
+       public function refreshCountsIfEmpty() {
+               $dbw = wfGetDB( DB_MASTER );
+
+               $hasLink = $dbw->selectField(
+                       'categorylinks',
+                       '1',
+                       [ 'cl_to' => $this->getName() ],
+                       __METHOD__
+               );
+               if ( !$hasLink ) {
+                       $this->refreshCounts(); // delete any category table entry
+
+                       return true;
+               }
+
+               $hasBadRow = $dbw->selectField(
+                       'category',
+                       '1',
+                       [ 'cat_title' => $this->getName(), 'cat_pages <= 0' ],
+                       __METHOD__
+               );
+               if ( $hasBadRow ) {
+                       $this->refreshCounts(); // clean up this row
+
+                       return true;
+               }
+
+               return false;
+       }
 }