Commit 1720f5739ee for woocommerce

commit 1720f5739eedc6f60528abe605347abdf7000b21
Author: Vladimir Reznichenko <kalessil@gmail.com>
Date:   Wed Jul 29 10:11:56 2026 +0200

    [Performance] Temporary deactivate product status counters (#67058)

    Temporarily switch back from the persistent product counters API to the WordPress API (once we investigate where integer-status is coming from, introduce normalization/hardening, and re-enable).

diff --git a/plugins/woocommerce/changelog/fix-counters-relax-product-status-type-requirements b/plugins/woocommerce/changelog/fix-counters-relax-product-status-type-requirements
new file mode 100644
index 00000000000..900094bb051
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-counters-relax-product-status-type-requirements
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Temporary deactivate persistent product status counters and rollback to WordPress API usage.
diff --git a/plugins/woocommerce/includes/admin/list-tables/class-wc-admin-list-table-products.php b/plugins/woocommerce/includes/admin/list-tables/class-wc-admin-list-table-products.php
index 35eb8117ba7..53a296e5d40 100644
--- a/plugins/woocommerce/includes/admin/list-tables/class-wc-admin-list-table-products.php
+++ b/plugins/woocommerce/includes/admin/list-tables/class-wc-admin-list-table-products.php
@@ -60,7 +60,7 @@ class WC_Admin_List_Table_Products extends WC_Admin_List_Table {
 		add_filter( 'posts_clauses', array( $this, 'posts_clauses' ), 10, 2 );

 		// Use hooks to prime various caches and improve products page performance.
-		add_action( 'load-edit.php', array( $this, 'prime_status_counts_cache' ) );
+		// Until persistent counters reactivated, disable callback for load-edit.php action.
 		add_filter( 'the_posts', array( $this, 'prime_thumbnail_caches' ), 10, 2 );

 		$cogs_controller              = wc_get_container()->get( CostOfGoodsSoldController::class );
diff --git a/plugins/woocommerce/src/Caches/ProductCountCacheService.php b/plugins/woocommerce/src/Caches/ProductCountCacheService.php
index 2b673dbd21b..a1df2cc3dc4 100644
--- a/plugins/woocommerce/src/Caches/ProductCountCacheService.php
+++ b/plugins/woocommerce/src/Caches/ProductCountCacheService.php
@@ -55,17 +55,13 @@ class ProductCountCacheService {
 	final public function init(): void {
 		$this->product_count_cache = new ProductCountCache();

-		add_action( 'action_scheduler_ensure_recurring_actions', array( $this, 'schedule_background_actions' ) );
+		add_action( 'action_scheduler_ensure_recurring_actions', array( $this, 'unschedule_background_actions' ) );
 		add_action( self::BACKGROUND_EVENT_HOOK, array( $this, 'prime_cache_if_cold' ) );
 		if ( defined( 'WC_PLUGIN_BASENAME' ) ) {
 			add_action( 'deactivate_' . WC_PLUGIN_BASENAME, array( $this, 'unschedule_background_actions' ) );
 		}

-		// transition_post_status owns all mid-lifecycle status changes; woocommerce_new_product corrects for creation-time
-		// ephemeral transitions before the final status is committed; before_delete_post closes the lifecycle.
-		add_action( 'woocommerce_new_product', array( $this, 'update_on_new_product' ), 10, 2 );
-		add_action( 'transition_post_status', array( $this, 'update_on_product_status_changed' ), 10, 3 );
-		add_action( 'before_delete_post', array( $this, 'update_on_product_deleted' ), 10, 2 );
+		// Until persistent counters reactivated, disable callbacks for woocommerce_new_product, transition_post_status, before_delete_post hooks.
 	}

 	/**
@@ -75,11 +71,7 @@ class ProductCountCacheService {
 	 * @return void
 	 */
 	public function prime_cache_if_cold( string $product_type = 'product' ): void {
-		// Cache warm-up is only effective when an object cache plugin is active, and the cache entry is missing.
-		if ( wp_using_ext_object_cache() && null === $this->product_count_cache->get( $product_type ) ) {
-			$this->product_count_cache->flush( $product_type );
-			wc_get_container()->get( ProductUtil::class )->get_counts_for_type( $product_type );
-		}
+		// Until persistent counters reactivated, this task is no-op.
 	}

 	/**
diff --git a/plugins/woocommerce/src/Internal/Utilities/ProductUtil.php b/plugins/woocommerce/src/Internal/Utilities/ProductUtil.php
index 8b4c4455798..1d9acc2a517 100644
--- a/plugins/woocommerce/src/Internal/Utilities/ProductUtil.php
+++ b/plugins/woocommerce/src/Internal/Utilities/ProductUtil.php
@@ -144,7 +144,7 @@ class ProductUtil {
 	}

 	/**
-	 * Counts per-status number of products of a given post type.
+	 * Counts per-status number of products.
 	 *
 	 * @since 11.0.0
 	 *
@@ -152,18 +152,7 @@ class ProductUtil {
 	 * @return array<string,int>
 	 */
 	public function get_counts_for_type( string $post_type ): array {
-		$product_count_cache = wc_get_container()->get( ProductCountCache::class );
-		$count_per_status    = $product_count_cache->get( $post_type );
-
-		if ( null === $count_per_status ) {
-			$count_per_status = array_merge(
-				array_fill_keys( array_keys( get_post_stati() ), 0 ),
-				(array) wp_count_posts( $post_type )
-			);
-
-			$product_count_cache->set_multiple( $post_type, $count_per_status );
-		}
-
-		return array_map( 'intval', $count_per_status );
+		// Until persistent counters reactivated, switch back to WordPress API for accessing post status counters.
+		return array_map( 'intval', (array) wp_count_posts( $post_type ) );
 	}
 }
diff --git a/plugins/woocommerce/tests/php/src/Caching/ProductCountCacheServiceTest.php b/plugins/woocommerce/tests/php/src/Caching/ProductCountCacheServiceTest.php
index 85aeb04d176..fb1bbbd1ee0 100644
--- a/plugins/woocommerce/tests/php/src/Caching/ProductCountCacheServiceTest.php
+++ b/plugins/woocommerce/tests/php/src/Caching/ProductCountCacheServiceTest.php
@@ -187,6 +187,8 @@ final class ProductCountCacheServiceTest extends \WC_Unit_Test_Case {
 	 * @testdox Source status count is decremented correctly when only the source slot is warm and the destination slot is cold.
 	 */
 	public function test_count_decremented_when_only_source_status_is_cached(): void {
+		$this->markTestSkipped( 'Until persistent counters reactivated, skip this test.' );
+
 		$product = WC_Helper_Product::create_simple_product();
 		$product->set_status( ProductStatus::DRAFT );
 		$product->save();
@@ -211,6 +213,8 @@ final class ProductCountCacheServiceTest extends \WC_Unit_Test_Case {
 	 * @testdox Final status is not double-incremented when a plugin permanently changes product status during creation.
 	 */
 	public function test_count_not_double_incremented_on_new_product_with_mid_creation_status_change(): void {
+		$this->markTestSkipped( 'Until persistent counters reactivated, skip this test.' );
+
 		// Warm all status slots and record the publish count before the test.
 		$this->product_util->get_counts_for_type( 'product' );
 		$publish_before = $this->product_cache->get( 'product', array( ProductStatus::PUBLISH ) )[ ProductStatus::PUBLISH ];
@@ -242,6 +246,8 @@ final class ProductCountCacheServiceTest extends \WC_Unit_Test_Case {
 	 * @testdox Source status count is not corrupted when a plugin permanently changes product status during creation.
 	 */
 	public function test_source_count_not_corrupted_on_new_product_with_mid_creation_status_change(): void {
+		$this->markTestSkipped( 'Until persistent counters reactivated, skip this test.' );
+
 		// Warm all status slots and record both counts before the test.
 		$this->product_util->get_counts_for_type( 'product' );
 		$draft_before   = $this->product_cache->get( 'product', array( ProductStatus::DRAFT ) )[ ProductStatus::DRAFT ];
@@ -285,6 +291,8 @@ final class ProductCountCacheServiceTest extends \WC_Unit_Test_Case {
 	 * @testdox Cache is populated when it is cold and an external object cache is active.
 	 */
 	public function test_prime_cache_if_cold_when_cache_is_cold(): void {
+		$this->markTestSkipped( 'Until persistent counters reactivated, skip this test.' );
+
 		global $_wp_using_ext_object_cache;
 		$_before                    = $_wp_using_ext_object_cache;
 		$_wp_using_ext_object_cache = true; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited