X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2FCategory.php;h=77f1212fcfb2287493e7633fc4dcd823a40f0e7a;hb=79502d48e636a31c05ef5f52753a634767cbc4cb;hp=fe3dd0d80ea32e941c1ee4cdf36f8e9fd9efd6cc;hpb=939bd15d960b39a089f10a7db62220d48fe165a5;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/Category.php b/includes/Category.php index fe3dd0d80e..77f1212fcf 100644 --- a/includes/Category.php +++ b/includes/Category.php @@ -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; + } }