Commit 5adb658475b for woocommerce
commit 5adb658475b884207c184bd3aa0a26545f3972ac
Author: Chris Lilitsas <1105590+xristos3490@users.noreply.github.com>
Date: Tue Sep 8 15:51:23 2026 +0300
Fix back-in-stock email CTA dropping the selected "Any" attribute (#68355)
* fix: keep posted "Any" attributes in back-in-stock notification product link
* chore: drop resolved PHPStan baseline entry for Notification::get_product_permalink
* fix: drop posted attributes that no longer belong to the variation from the link
diff --git a/plugins/woocommerce/changelog/fix-bis-email-cta-drops-attribute b/plugins/woocommerce/changelog/fix-bis-email-cta-drops-attribute
new file mode 100644
index 00000000000..f9139cdd7cc
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-bis-email-cta-drops-attribute
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Fix the back-in-stock notification email CTA dropping the selected "Any" attribute from the product link.
diff --git a/plugins/woocommerce/phpstan-baseline.neon b/plugins/woocommerce/phpstan-baseline.neon
index 2203de29141..91d140c01be 100644
--- a/plugins/woocommerce/phpstan-baseline.neon
+++ b/plugins/woocommerce/phpstan-baseline.neon
@@ -66762,12 +66762,6 @@ parameters:
count: 1
path: src/Internal/StockNotifications/Notification.php
- -
- message: '#^Method WC_Product\:\:get_permalink\(\) invoked with 1 parameter, 0 required\.$#'
- identifier: arguments.count
- count: 1
- path: src/Internal/StockNotifications/Notification.php
-
-
message: '#^Property Automattic\\WooCommerce\\Internal\\StockNotifications\\Notification\:\:\$product \(WC_Product\) does not accept null\.$#'
identifier: assign.propertyType
diff --git a/plugins/woocommerce/src/Internal/StockNotifications/Notification.php b/plugins/woocommerce/src/Internal/StockNotifications/Notification.php
index 791594e05a9..116782edc2e 100644
--- a/plugins/woocommerce/src/Internal/StockNotifications/Notification.php
+++ b/plugins/woocommerce/src/Internal/StockNotifications/Notification.php
@@ -428,11 +428,17 @@ class Notification extends \WC_Data {
return '';
}
- if ( $product->is_type( 'variation' ) && ! empty( $this->get_meta( 'posted_attributes' ) ) ) {
- return $product->get_permalink( array( 'item_meta_array' => $this->get_meta( 'posted_attributes' ) ) );
- } else {
+ $posted_attributes = $this->get_meta( 'posted_attributes' );
+ if ( ! $product instanceof \WC_Product_Variation || empty( $posted_attributes ) || ! is_array( $posted_attributes ) ) {
return $product->get_permalink();
}
+
+ // Posted attributes hold only the values chosen for "Any" attributes, so merge them over the variation's own attributes to build a complete link.
+ // Keys that no longer belong to the variation (e.g. a removed attribute) are dropped so they don't leak into the URL.
+ $variation_attributes = $product->get_variation_attributes();
+ $attributes = array_merge( $variation_attributes, array_intersect_key( $posted_attributes, $variation_attributes ) );
+
+ return $product->get_permalink( array( 'variation' => $attributes ) );
}
/**
diff --git a/plugins/woocommerce/tests/php/src/Internal/StockNotifications/NotificationTests.php b/plugins/woocommerce/tests/php/src/Internal/StockNotifications/NotificationTests.php
index ce844a9d95c..8a275f99eec 100644
--- a/plugins/woocommerce/tests/php/src/Internal/StockNotifications/NotificationTests.php
+++ b/plugins/woocommerce/tests/php/src/Internal/StockNotifications/NotificationTests.php
@@ -104,6 +104,38 @@ class NotificationTests extends \WC_Unit_Test_Case {
$this->assertEquals( $variation_product->get_permalink(), $permalink );
}
+ /**
+ * @testdox Should include both the variation's own attributes and the posted "Any" attributes in the permalink.
+ */
+ public function test_get_product_permalink_with_posted_attributes(): void {
+ $variable_product = \WC_Helper_Product::create_variation_product();
+ // The first variation only sets "size"; "colour" is left as "Any".
+ $variation_id = $variable_product->get_children()[0];
+
+ $notification = new Notification();
+ $notification->set_product_id( $variation_id );
+ $notification->set_user_email( 'test@example.com' );
+ // "attribute_pa_stale" is not a variation attribute and must not end up in the URL.
+ $notification->update_meta_data(
+ 'posted_attributes',
+ array(
+ 'attribute_pa_colour' => 'red',
+ 'attribute_pa_stale' => 'gone',
+ )
+ );
+ $notification->save();
+
+ $expected = add_query_arg(
+ array(
+ 'attribute_pa_size' => 'small',
+ 'attribute_pa_colour' => 'red',
+ ),
+ get_permalink( $variable_product->get_id() )
+ );
+
+ $this->assertSame( $expected, $notification->get_product_permalink(), 'Permalink should carry the variation attribute and the posted "Any" attribute, and nothing else' );
+ }
+
/**
* Test the get_product_name method.
*/