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