Commit 4b8ad3641a8 for woocommerce
commit 4b8ad3641a827c2eb46fe1f99e69f33dee8fd5d3
Author: Albert Juhé Lluveras <contact@albertjuhe.com>
Date: Fri Nov 6 16:56:46 2026 +0100
CartController test and types enhancements (#70711)
* Improve CartController types
* Update PHPStan
* Test correct 'Invalid value posted' is shown when trying to add variations to cart with incorrect values
* Add changelog file
* Improve comments
diff --git a/plugins/woocommerce/changelog/update-CartController-fixes b/plugins/woocommerce/changelog/update-CartController-fixes
new file mode 100644
index 00000000000..2e524c67e98
--- /dev/null
+++ b/plugins/woocommerce/changelog/update-CartController-fixes
@@ -0,0 +1,5 @@
+Significance: patch
+Type: dev
+Comment: CartController test and types enhancements
+
+
diff --git a/plugins/woocommerce/phpstan-baseline.neon b/plugins/woocommerce/phpstan-baseline.neon
index 9c4f5683eaf..6378bb66407 100644
--- a/plugins/woocommerce/phpstan-baseline.neon
+++ b/plugins/woocommerce/phpstan-baseline.neon
@@ -12757,13 +12757,13 @@ parameters:
path: includes/class-wc-order.php
-
- message: '#^PHPDoc tag @param has invalid value \(WC_Order \$this Order object\.\)\: Unexpected token "\$this", expected variable at offset 192 on line 6$#'
+ message: '#^PHPDoc tag @param has invalid value \(WC_Order \$this Order object\.\)\: Unexpected token "\$this", expected variable at offset 187 on line 6$#'
identifier: phpDoc.parseError
count: 1
path: includes/class-wc-order.php
-
- message: '#^PHPDoc tag @param has invalid value \(WC_Order \$this Order object\.\)\: Unexpected token "\$this", expected variable at offset 187 on line 6$#'
+ message: '#^PHPDoc tag @param has invalid value \(WC_Order \$this Order object\.\)\: Unexpected token "\$this", expected variable at offset 192 on line 6$#'
identifier: phpDoc.parseError
count: 1
path: includes/class-wc-order.php
@@ -66882,12 +66882,6 @@ parameters:
count: 1
path: src/StoreApi/Utilities/CartController.php
- -
- message: '#^Call to method is_type\(\) on an unknown class Automattic\\WooCommerce\\StoreApi\\Utilities\\Error\.$#'
- identifier: class.notFound
- count: 2
- path: src/StoreApi/Utilities/CartController.php
-
-
message: '#^Cannot call method get_id\(\) on WC_Product\|false\|null\.$#'
identifier: method.nonObject
@@ -66954,12 +66948,6 @@ parameters:
count: 1
path: src/StoreApi/Utilities/CartController.php
- -
- message: '#^Method Automattic\\WooCommerce\\StoreApi\\Utilities\\CartController\:\:get_product_for_cart\(\) has invalid return type Automattic\\WooCommerce\\StoreApi\\Utilities\\Error\.$#'
- identifier: class.notFound
- count: 1
- path: src/StoreApi/Utilities/CartController.php
-
-
message: '#^Method Automattic\\WooCommerce\\StoreApi\\Utilities\\CartController\:\:get_remaining_stock_for_product\(\) should return int but returns float\|int\.$#'
identifier: return.type
@@ -67062,42 +67050,6 @@ parameters:
count: 1
path: src/StoreApi/Utilities/CartController.php
- -
- message: '#^Parameter \#1 \$product of function wc_get_cart_item_data_hash expects WC_Product, Automattic\\WooCommerce\\StoreApi\\Utilities\\Error\|WC_Product given\.$#'
- identifier: argument.type
- count: 1
- path: src/StoreApi/Utilities/CartController.php
-
- -
- message: '#^Parameter \#1 \$product of method Automattic\\WooCommerce\\StoreApi\\Utilities\\CartController\:\:get_product_id\(\) expects WC_Product, Automattic\\WooCommerce\\StoreApi\\Utilities\\Error\|WC_Product given\.$#'
- identifier: argument.type
- count: 3
- path: src/StoreApi/Utilities/CartController.php
-
- -
- message: '#^Parameter \#1 \$product of method Automattic\\WooCommerce\\StoreApi\\Utilities\\CartController\:\:get_variable_product_attributes\(\) expects WC_Product, Automattic\\WooCommerce\\StoreApi\\Utilities\\Error\|WC_Product given\.$#'
- identifier: argument.type
- count: 1
- path: src/StoreApi/Utilities/CartController.php
-
- -
- message: '#^Parameter \#1 \$product of method Automattic\\WooCommerce\\StoreApi\\Utilities\\CartController\:\:get_variation_id\(\) expects WC_Product, Automattic\\WooCommerce\\StoreApi\\Utilities\\Error\|WC_Product given\.$#'
- identifier: argument.type
- count: 3
- path: src/StoreApi/Utilities/CartController.php
-
- -
- message: '#^Parameter \#1 \$product of method Automattic\\WooCommerce\\StoreApi\\Utilities\\CartController\:\:validate_add_to_cart\(\) expects WC_Product, Automattic\\WooCommerce\\StoreApi\\Utilities\\Error\|WC_Product given\.$#'
- identifier: argument.type
- count: 1
- path: src/StoreApi/Utilities/CartController.php
-
- -
- message: '#^Parameter \#1 \$product of method Automattic\\WooCommerce\\StoreApi\\Utilities\\QuantityLimits\:\:get_add_to_cart_limits\(\) expects WC_Product, Automattic\\WooCommerce\\StoreApi\\Utilities\\Error\|WC_Product given\.$#'
- identifier: argument.type
- count: 2
- path: src/StoreApi/Utilities/CartController.php
-
-
message: '#^Parameter \#1 \$str of function md5 expects string, string\|false given\.$#'
identifier: argument.type
@@ -67110,12 +67062,6 @@ parameters:
count: 1
path: src/StoreApi/Utilities/CartController.php
- -
- message: '#^Parameter \#2 \$product of method Automattic\\WooCommerce\\StoreApi\\Utilities\\CartController\:\:get_variation_id_from_variation_data\(\) expects WC_Product, Automattic\\WooCommerce\\StoreApi\\Utilities\\Error\|WC_Product given\.$#'
- identifier: argument.type
- count: 1
- path: src/StoreApi/Utilities/CartController.php
-
-
message: '#^Parameter \#2 \$quantity of method WC_Cart\:\:set_quantity\(\) expects int, float\|int given\.$#'
identifier: argument.type
diff --git a/plugins/woocommerce/src/StoreApi/Utilities/CartController.php b/plugins/woocommerce/src/StoreApi/Utilities/CartController.php
index 79ddd787e79..3a80f89eb34 100644
--- a/plugins/woocommerce/src/StoreApi/Utilities/CartController.php
+++ b/plugins/woocommerce/src/StoreApi/Utilities/CartController.php
@@ -1138,12 +1138,12 @@ class CartController {
* @throws RouteException Exception if invalid data is detected.
*
* @param array $request Add to cart request params.
- * @return \WC_Product|Error Returns a product object if purchasable.
+ * @return \WC_Product Product to add. Throws if it does not exist or is trashed.
*/
protected function get_product_for_cart( $request ) {
$product = wc_get_product( $request['id'] );
- if ( ! $product || ProductStatus::TRASH === $product->get_status() ) {
+ if ( ! $product instanceof \WC_Product || ProductStatus::TRASH === $product->get_status() ) {
throw new RouteException(
'woocommerce_rest_cart_invalid_product',
sprintf(
diff --git a/plugins/woocommerce/tests/php/src/Blocks/StoreApi/Utilities/CartControllerTests.php b/plugins/woocommerce/tests/php/src/Blocks/StoreApi/Utilities/CartControllerTests.php
index e274fd059e3..ebf01549546 100644
--- a/plugins/woocommerce/tests/php/src/Blocks/StoreApi/Utilities/CartControllerTests.php
+++ b/plugins/woocommerce/tests/php/src/Blocks/StoreApi/Utilities/CartControllerTests.php
@@ -3,6 +3,7 @@ declare( strict_types = 1 );
namespace Automattic\WooCommerce\Tests\Blocks\StoreApi\Utilities;
+use Automattic\WooCommerce\StoreApi\Exceptions\RouteException;
use Automattic\WooCommerce\StoreApi\Utilities\CartController;
use Automattic\WooCommerce\Tests\Blocks\Helpers\FixtureData;
use Automattic\WooCommerce\Enums\ProductStockStatus;
@@ -389,4 +390,48 @@ class CartControllerTests extends \WC_Unit_Test_Case {
$this->assertSame( array( 1, $product->get_id(), (int) $variation['variation_id'] ), $captured );
$this->assertSame( 4, wc()->cart->get_cart_item( $cart_id )['quantity'] );
}
+
+ /**
+ * @testdox Add to cart rejects an attribute value outside the configured options, including when an Any variation exists.
+ */
+ public function test_add_to_cart_rejects_attribute_value_outside_options_when_any_variation_exists(): void {
+ $product = new \WC_Product_Variable();
+ $attribute = new \WC_Product_Attribute();
+ $attribute->set_name( 'Color' );
+ $attribute->set_options( array( 'Red', 'Blue' ) );
+ $attribute->set_variation( true );
+ $product->set_attributes( array( $attribute ) );
+ $product->save();
+
+ $red = new \WC_Product_Variation();
+ $red->set_parent_id( $product->get_id() );
+ $red->set_attributes( array( 'color' => 'Red' ) );
+ $red->set_regular_price( '5' );
+ $red->save();
+
+ $any = new \WC_Product_Variation();
+ $any->set_parent_id( $product->get_id() );
+ $any->set_attributes( array( 'color' => '' ) );
+ $any->set_regular_price( '4' );
+ $any->save();
+
+ try {
+ ( new CartController() )->add_to_cart(
+ array(
+ 'id' => $product->get_id(),
+ 'quantity' => 1,
+ 'variation' => array(
+ array(
+ 'attribute' => 'Color',
+ 'value' => 'Green',
+ ),
+ ),
+ )
+ );
+ $this->fail( 'Posting an attribute value that is not an option should be rejected, including when an Any variation exists.' );
+ } catch ( RouteException $exception ) {
+ $this->assertSame( 'woocommerce_rest_invalid_variation_data', $exception->getErrorCode() );
+ $this->assertStringContainsString( 'Invalid value posted for Color', $exception->getMessage() );
+ }
+ }
}