Commit 257ced44c50 for woocommerce
commit 257ced44c501e42094b3e3cfeecbee5768c7cd3c
Author: Christopher Hertel <mail@christopher-hertel.de>
Date: Fri Nov 6 00:18:16 2026 +0100
Report whether product-delete trashed or permanently deleted a product (#70717)
* Report whether product-delete trashed or permanently deleted
* Add changelog entry for product-delete result status
* Describe only the requested product in the product-delete result
* Drop the always-true deleted field from the product-delete result
diff --git a/plugins/woocommerce/changelog/wooai-1655-trash-vs-permanent b/plugins/woocommerce/changelog/wooai-1655-trash-vs-permanent
new file mode 100644
index 00000000000..13feb0a8159
--- /dev/null
+++ b/plugins/woocommerce/changelog/wooai-1655-trash-vs-permanent
@@ -0,0 +1,4 @@
+Significance: patch
+Type: tweak
+
+Say in the product-delete ability result whether a product was moved to the trash or deleted permanently.
diff --git a/plugins/woocommerce/src/Internal/Abilities/Domain/ProductDelete.php b/plugins/woocommerce/src/Internal/Abilities/Domain/ProductDelete.php
index 76dfa59b35a..9582cc2dec8 100644
--- a/plugins/woocommerce/src/Internal/Abilities/Domain/ProductDelete.php
+++ b/plugins/woocommerce/src/Internal/Abilities/Domain/ProductDelete.php
@@ -8,6 +8,7 @@ declare( strict_types=1 );
namespace Automattic\WooCommerce\Internal\Abilities\Domain;
use Automattic\WooCommerce\Abilities\ActionableAbility;
+use Automattic\WooCommerce\Enums\ProductStatus;
use Automattic\WooCommerce\Internal\Abilities\Domain\Traits\DomainAbilityHelpers;
use Automattic\WooCommerce\Internal\Abilities\Domain\Traits\ProductAbilityTrait;
@@ -31,6 +32,11 @@ class ProductDelete extends ActionableAbility {
*/
public const ABILITY_NAME = 'woocommerce/product-delete';
+ /**
+ * The result status of a forced delete, which leaves nothing to restore.
+ */
+ private const STATUS_DELETED = 'deleted';
+
/**
* ID of the product the call deletes, kept because a forced delete clears the object's ID.
*
@@ -84,12 +90,12 @@ class ProductDelete extends ActionableAbility {
return array(
'label' => __( 'Delete product', 'woocommerce' ),
'description' => __(
- 'Delete, trash, or restore a product.',
+ 'Move a product to the trash, or delete it permanently.',
'woocommerce'
),
'category' => 'woocommerce',
'input_schema' => self::build_input_schema(),
- 'output_schema' => self::get_delete_output_schema(),
+ 'output_schema' => self::build_output_schema(),
'permission_callback' => array( __CLASS__, 'can_delete_product' ),
'meta' => array(
'show_in_rest' => true,
@@ -287,8 +293,8 @@ class ProductDelete extends ActionableAbility {
unset( $subject );
return array(
- 'deleted' => true,
- 'id' => $this->product_id,
+ 'id' => $this->product_id,
+ 'status' => $this->force ? self::STATUS_DELETED : ProductStatus::TRASH,
);
}
@@ -330,4 +336,27 @@ class ProductDelete extends ActionableAbility {
'additionalProperties' => false,
);
}
+
+ /**
+ * Get the output schema.
+ *
+ * @return array
+ */
+ private static function build_output_schema(): array {
+ return array(
+ 'type' => 'object',
+ 'properties' => array(
+ 'id' => array(
+ 'type' => 'integer',
+ 'description' => __( 'ID of the product.', 'woocommerce' ),
+ ),
+ 'status' => array(
+ 'type' => 'string',
+ 'enum' => array( ProductStatus::TRASH, self::STATUS_DELETED ),
+ 'description' => __( 'What happened to the product. "trash": the product was moved to the trash, and can be restored. "deleted": the product was permanently deleted, and cannot be restored.', 'woocommerce' ),
+ ),
+ ),
+ 'additionalProperties' => false,
+ );
+ }
}
diff --git a/plugins/woocommerce/src/Internal/Abilities/Domain/Traits/DomainAbilityHelpers.php b/plugins/woocommerce/src/Internal/Abilities/Domain/Traits/DomainAbilityHelpers.php
index 70aaabe15ba..2ac2de67c68 100644
--- a/plugins/woocommerce/src/Internal/Abilities/Domain/Traits/DomainAbilityHelpers.php
+++ b/plugins/woocommerce/src/Internal/Abilities/Domain/Traits/DomainAbilityHelpers.php
@@ -98,22 +98,6 @@ trait DomainAbilityHelpers {
);
}
- /**
- * Get a delete output schema.
- *
- * @return array
- */
- protected static function get_delete_output_schema(): array {
- return array(
- 'type' => 'object',
- 'properties' => array(
- 'deleted' => array( 'type' => 'boolean' ),
- 'id' => array( 'type' => 'integer' ),
- ),
- 'additionalProperties' => false,
- );
- }
-
/**
* Get an ID value from ability input.
*
diff --git a/plugins/woocommerce/tests/php/src/Internal/Abilities/AbilitiesLoaderTest.php b/plugins/woocommerce/tests/php/src/Internal/Abilities/AbilitiesLoaderTest.php
index 0c846de9aaf..a76dd2d999d 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Abilities/AbilitiesLoaderTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Abilities/AbilitiesLoaderTest.php
@@ -3900,8 +3900,8 @@ class AbilitiesLoaderTest extends \WC_Unit_Test_Case {
);
$this->assertNotWPError( $result );
- $this->assertTrue( $result['deleted'] );
$this->assertSame( $product->get_id(), $result['id'] );
+ $this->assertSame( 'deleted', $result['status'] );
$this->assertNull( get_post( $product->get_id() ) );
}
@@ -3919,7 +3919,7 @@ class AbilitiesLoaderTest extends \WC_Unit_Test_Case {
);
$this->assertNotWPError( $result );
- $this->assertTrue( $result['deleted'] );
+ $this->assertSame( 'deleted', $result['status'] );
$this->assertNull( get_post( $variation_id ) );
}
@@ -3937,7 +3937,7 @@ class AbilitiesLoaderTest extends \WC_Unit_Test_Case {
);
$this->assertNotWPError( $result );
- $this->assertTrue( $result['deleted'] );
+ $this->assertSame( 'trash', $result['status'] );
$this->assertSame( 'trash', get_post_status( $product->get_id() ) );
}
diff --git a/plugins/woocommerce/tests/php/src/Internal/AbilitiesApi/ExtensibleAbilitiesTest.php b/plugins/woocommerce/tests/php/src/Internal/AbilitiesApi/ExtensibleAbilitiesTest.php
index ef24c44d244..9e9c6704053 100644
--- a/plugins/woocommerce/tests/php/src/Internal/AbilitiesApi/ExtensibleAbilitiesTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/AbilitiesApi/ExtensibleAbilitiesTest.php
@@ -2958,7 +2958,7 @@ class ExtensibleAbilitiesTest extends \WC_REST_Unit_Test_Case {
$this->assertSame( 400, $refused->get_status() );
$this->assertStringEndsWith( 'test_keep', $refused->get_data()['code'] );
$this->assertInstanceOf( \WC_Product::class, wc_get_product( $kept->get_id() ) );
- $this->assertTrue( $deleted['deleted'] );
+ $this->assertSame( 'deleted', $deleted['status'] );
$this->assertFalse( wc_get_product( $created['product']['id'] ) );
$this->assertNull( get_post( $created['product']['variation_ids'][0] ), 'The variations go with the parent.' );
}
@@ -3080,7 +3080,7 @@ class ExtensibleAbilitiesTest extends \WC_REST_Unit_Test_Case {
$this->assertSame( 400, $refused->get_status() );
$this->assertSame( 'Keep it.', $refused->get_data()['message'] );
$this->assertInstanceOf( \WC_Product_Variable::class, $after );
- $this->assertTrue( $deleted['deleted'] );
+ $this->assertSame( 'deleted', $deleted['status'] );
foreach ( $created['product']['variation_ids'] as $variation_id ) {
$this->assertSame( array( 'woocommerce/product-delete', true ), $seen[ $variation_id ] );
}