Commit 7ba1bdbc9a for woocommerce
commit 7ba1bdbc9a4bbb2e95e13e2ba93a55268bfc8911
Author: Alba Rincón <albarin@users.noreply.github.com>
Date: Fri Feb 13 09:34:34 2026 +0100
Defer `has_products()` check to shutdown hook for bulk delete/trash (#63261)
* Defer has_products() check to shutdown hook for bulk operations
When bulk-trashing or bulk-deleting products, revert_task_completion()
was firing once per product, each triggering a has_products() DB query.
This defers the check to a shutdown hook using a static flag so that
bulk operations only run a single query at the end of the request.
* Add changefile(s) from automation for the following project(s): woocommerce
---------
Co-authored-by: woocommercebot <woocommercebot@users.noreply.github.com>
diff --git a/plugins/woocommerce/changelog/63261-fix-products-task-bulk-trash-performance b/plugins/woocommerce/changelog/63261-fix-products-task-bulk-trash-performance
new file mode 100644
index 0000000000..128589a287
--- /dev/null
+++ b/plugins/woocommerce/changelog/63261-fix-products-task-bulk-trash-performance
@@ -0,0 +1,4 @@
+Significance: minor
+Type: performance
+
+Defer has_products() check to shutdown hook for bulk delete/trash products.
\ No newline at end of file
diff --git a/plugins/woocommerce/src/Admin/Features/OnboardingTasks/Tasks/Products.php b/plugins/woocommerce/src/Admin/Features/OnboardingTasks/Tasks/Products.php
index 90f06cbd8c..14dc0147fb 100644
--- a/plugins/woocommerce/src/Admin/Features/OnboardingTasks/Tasks/Products.php
+++ b/plugins/woocommerce/src/Admin/Features/OnboardingTasks/Tasks/Products.php
@@ -13,6 +13,13 @@ use Automattic\WooCommerce\Internal\Admin\Onboarding\OnboardingProfile;
class Products extends Task {
const HAS_PRODUCT_TRANSIENT = 'woocommerce_product_task_has_product_transient';
+ /**
+ * Whether a deferred revert check has already been scheduled for this request.
+ *
+ * @var bool
+ */
+ private static $revert_scheduled = false;
+
/**
* Constructor
*
@@ -206,13 +213,34 @@ class Products extends Task {
}
/**
- * Re-check whether valid products still exist and revert task completion if none remain.
+ * Schedule a deferred check to revert task completion if no products remain.
+ *
+ * Uses the shutdown hook so that bulk operations (e.g. trashing many products
+ * at once) only trigger a single has_products() query instead of one per product.
*
* @return void
*/
- private function revert_task_completion() {
+ private function revert_task_completion(): void {
delete_transient( self::HAS_PRODUCT_TRANSIENT );
+ if ( self::$revert_scheduled ) {
+ return;
+ }
+
+ self::$revert_scheduled = true;
+ add_action( 'shutdown', array( $this, 'maybe_revert_on_shutdown' ) );
+ }
+
+ /**
+ * Re-check whether valid products still exist and revert task completion if none remain.
+ *
+ * Runs once at the end of the request via the shutdown hook.
+ *
+ * @return void
+ */
+ public function maybe_revert_on_shutdown(): void {
+ self::$revert_scheduled = false;
+
if ( self::has_products() ) {
return;
}