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.
 	 *