Commit 9e658735be for woocommerce
commit 9e658735be1146d0fd935cb73a27c1134453d2cf
Author: Alba Rincón <albarin@users.noreply.github.com>
Date: Thu Feb 12 09:24:56 2026 +0100
Allow the Products onboarding task to revert to incomplete when all products are removed (#63239)
* Allow the Products onboarding task to revert to incomplete when all products are removed
Previously, once the Products task was marked complete via has_previously_completed(),
it could never revert — even if all products were trashed or deleted. This contradicts
the expected behavior where the task should reflect the actual store state.
Add hooks for trashed_post and deleted_post_product that clear the product transient
cache and remove the task from the tracked completed list when no valid products remain.
* Add changefile(s) from automation for the following project(s): woocommerce
* Fix phpstan error
* Rename function
* 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/63239-fix-56534-revert-products-task b/plugins/woocommerce/changelog/63239-fix-56534-revert-products-task
new file mode 100644
index 0000000000..3bc714f088
--- /dev/null
+++ b/plugins/woocommerce/changelog/63239-fix-56534-revert-products-task
@@ -0,0 +1,4 @@
+Significance: minor
+Type: fix
+
+Allow the Products onboarding task to revert to incomplete when all products are removed
\ 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 8043a902cf..90f06cbd8c 100644
--- a/plugins/woocommerce/src/Admin/Features/OnboardingTasks/Tasks/Products.php
+++ b/plugins/woocommerce/src/Admin/Features/OnboardingTasks/Tasks/Products.php
@@ -27,6 +27,9 @@ class Products extends Task {
add_action( 'woocommerce_new_product', array( $this, 'maybe_set_has_product_transient' ), 10, 2 );
add_action( 'untrashed_post', array( $this, 'maybe_set_has_product_transient_on_untrashed_post' ) );
add_action( 'current_screen', array( $this, 'maybe_redirect_to_add_product_tasklist' ), 30, 0 );
+
+ add_action( 'trashed_post', array( $this, 'on_product_trashed' ) );
+ add_action( 'deleted_post_product', array( $this, 'on_product_deleted' ) );
}
/**
@@ -179,6 +182,50 @@ class Products extends Task {
}
}
+ /**
+ * Handle product trashing via the trashed_post hook.
+ *
+ * @param int $post_id Post ID.
+ * @return void
+ */
+ public function on_product_trashed( $post_id ) {
+ if ( get_post_type( $post_id ) !== 'product' ) {
+ return;
+ }
+
+ $this->revert_task_completion();
+ }
+
+ /**
+ * Handle permanent product deletion via the deleted_post_product hook.
+ *
+ * @return void
+ */
+ public function on_product_deleted() {
+ $this->revert_task_completion();
+ }
+
+ /**
+ * Re-check whether valid products still exist and revert task completion if none remain.
+ *
+ * @return void
+ */
+ private function revert_task_completion() {
+ delete_transient( self::HAS_PRODUCT_TRANSIENT );
+
+ if ( self::has_products() ) {
+ return;
+ }
+
+ $completed_tasks = get_option( self::COMPLETED_OPTION, array() );
+ $task_id = $this->get_id();
+
+ if ( in_array( $task_id, $completed_tasks, true ) ) {
+ $completed_tasks = array_values( array_diff( $completed_tasks, array( $task_id ) ) );
+ update_option( self::COMPLETED_OPTION, $completed_tasks );
+ }
+ }
+
/**
* Check if the product qualifies as a user created product.
*