Commit 20949b8c161 for woocommerce
commit 20949b8c161e518123bd3afabf0f439c92786498
Author: Taha Paksu <3295+tpaksu@users.noreply.github.com>
Date: Mon Nov 9 22:29:14 2026 +0300
Fix fulfillment erasure skipped by a non-array filter return (#70725)
diff --git a/plugins/woocommerce/changelog/70725-wooairr-717-ai-regression-reviewtrunk-an-extension-returning-a-non-array b/plugins/woocommerce/changelog/70725-wooairr-717-ai-regression-reviewtrunk-an-extension-returning-a-non-array
new file mode 100644
index 00000000000..4058ec0bec1
--- /dev/null
+++ b/plugins/woocommerce/changelog/70725-wooairr-717-ai-regression-reviewtrunk-an-extension-returning-a-non-array
@@ -0,0 +1,5 @@
+Significance: patch
+Type: dev
+Comment: Fix an unreleased fulfillment privacy filter fallback; nothing merchant-facing changes.
+
+
diff --git a/plugins/woocommerce/src/Admin/Features/Fulfillments/FulfillmentsPrivacy.php b/plugins/woocommerce/src/Admin/Features/Fulfillments/FulfillmentsPrivacy.php
index d3a2f9dc5ff..50f7dcf9738 100644
--- a/plugins/woocommerce/src/Admin/Features/Fulfillments/FulfillmentsPrivacy.php
+++ b/plugins/woocommerce/src/Admin/Features/Fulfillments/FulfillmentsPrivacy.php
@@ -263,9 +263,13 @@ class FulfillmentsPrivacy {
return;
}
+ $default_keys = array( '_tracking_number', '_tracking_url' );
+
/**
* Filters the fulfillment meta keys redacted during personal-data erasure.
*
+ * A non-array return is ignored and the default keys are cleared instead. An empty array clears nothing.
+ *
* @since 11.4.0
*
* @param string[] $meta_keys The meta keys to clear.
@@ -273,12 +277,16 @@ class FulfillmentsPrivacy {
*/
$meta_keys = apply_filters(
'woocommerce_privacy_remove_fulfillment_personal_data_meta',
- array( '_tracking_number', '_tracking_url' ),
+ $default_keys,
$order
);
if ( ! is_array( $meta_keys ) ) {
- return;
+ wc_get_logger()->warning(
+ 'The woocommerce_privacy_remove_fulfillment_personal_data_meta filter returned a non-array value for order ' . $order->get_id() . ', so the default keys were used.',
+ array( 'source' => 'fulfillments' )
+ );
+ $meta_keys = $default_keys;
}
$meta_keys = array_values(
diff --git a/plugins/woocommerce/tests/php/src/Admin/Features/Fulfillments/FulfillmentsPrivacyTest.php b/plugins/woocommerce/tests/php/src/Admin/Features/Fulfillments/FulfillmentsPrivacyTest.php
index 95bdff0c82a..e6fff756191 100644
--- a/plugins/woocommerce/tests/php/src/Admin/Features/Fulfillments/FulfillmentsPrivacyTest.php
+++ b/plugins/woocommerce/tests/php/src/Admin/Features/Fulfillments/FulfillmentsPrivacyTest.php
@@ -620,4 +620,78 @@ class FulfillmentsPrivacyTest extends WC_Unit_Test_Case {
$reloaded = $this->reload_fulfillment( $order->get_id(), $fulfillment->get_id() );
$this->assertNull( $reloaded->get_tracking_number(), 'The valid key should be redacted and the non-scalar entry ignored.' );
}
+
+ /**
+ * @testdox The eraser falls back to the default meta keys and logs a warning when the filter returns a non-array.
+ *
+ * @dataProvider provider_non_array_filter_values
+ *
+ * @param mixed $filtered_value The invalid value returned by the filter.
+ */
+ public function test_eraser_falls_back_to_default_keys_for_non_array_filter_value( $filtered_value ): void {
+ list( $order, $fulfillment ) = $this->create_order_with_fulfillment(
+ array(
+ '_tracking_number' => 'TRACK123456',
+ '_tracking_url' => 'https://example.com/track/TRACK123456',
+ )
+ );
+
+ $logger = $this->createMock( \WC_Logger_Interface::class );
+ $logger->expects( $this->once() )
+ ->method( 'warning' )
+ ->with( $this->stringContains( 'order ' . $order->get_id() ), $this->arrayHasKey( 'source' ) );
+ add_filter(
+ 'woocommerce_logging_class',
+ function () use ( $logger ) {
+ return $logger;
+ }
+ );
+ add_filter(
+ 'woocommerce_privacy_remove_fulfillment_personal_data_meta',
+ function () use ( $filtered_value ) {
+ return $filtered_value;
+ }
+ );
+
+ $this->sut->remove_fulfillment_personal_data( $order );
+
+ $reloaded = $this->reload_fulfillment( $order->get_id(), $fulfillment->get_id() );
+ $this->assertNull( $reloaded->get_tracking_number(), 'The default tracking number key should still be cleared.' );
+ $this->assertNull( $reloaded->get_tracking_url(), 'The default tracking URL key should still be cleared.' );
+ }
+
+ /**
+ * @return array<string, array<mixed>>
+ */
+ public function provider_non_array_filter_values(): array {
+ return array(
+ 'string' => array( 'invalid' ),
+ 'null' => array( null ),
+ 'false' => array( false ),
+ );
+ }
+
+ /**
+ * @testdox The eraser clears nothing, without a warning, when the filter explicitly returns an empty array.
+ */
+ public function test_eraser_clears_nothing_when_filter_returns_empty_array(): void {
+ list( $order, $fulfillment ) = $this->create_order_with_fulfillment(
+ array( '_tracking_number' => 'TRACK123456' )
+ );
+
+ $logger = $this->createMock( \WC_Logger_Interface::class );
+ $logger->expects( $this->never() )->method( 'warning' );
+ add_filter(
+ 'woocommerce_logging_class',
+ function () use ( $logger ) {
+ return $logger;
+ }
+ );
+ add_filter( 'woocommerce_privacy_remove_fulfillment_personal_data_meta', '__return_empty_array' );
+
+ $this->sut->remove_fulfillment_personal_data( $order );
+
+ $reloaded = $this->reload_fulfillment( $order->get_id(), $fulfillment->get_id() );
+ $this->assertSame( 'TRACK123456', $reloaded->get_tracking_number(), 'An explicit empty array is an opt-out and should clear nothing.' );
+ }
}