Commit c5539fc87bd for woocommerce
commit c5539fc87bde81d5cc25f09a7c753de64a5cfa62
Author: Anuj Singh <80690679+Anuj-Rathore24@users.noreply.github.com>
Date: Fri Jul 3 13:58:28 2026 +0530
fix: `woocommerce_add_to_cart_quantity` filter now receives `$variation_id` (#63679)
* fix: pass variation_id, variation, and cart_item_data to `woocommerce_add_to_cart_quantity` filter
* test: assert `woocommerce_add_to_cart_quantity` filter receives variation_id for variable products
* feat: Adds changelog for changes in `woocommerce_add_to_cart_quantity` filter
* refactor: Revert changes.
* refactor: Revert changes
* feat: Change type from `add` to `enhancement`
* fix: update `woocommerce_add_to_cart_quantity` filter to pass variation_id only
* tests: Update `woocommerce_add_to_cart_quantity` filter to pass variation_id.
- Adds teardown for filter.
- Adds test for simple product to confirm variation_id as 0.
* feat: Update docblock for filter `woocommerce_add_to_cart_quantity`
* fix: adds variation_id param docblock and guard against false product_id from wp_get_post_parent_id
* refactor: Update version comments
* refactor: Resolve phpcs linting errors
* feat: Update PHPStan baseline to remove resolved WC_Cart error
* Fix: Update parameter name in docblock to match $quantity
---------
Co-authored-by: Karol Manijak <20098064+kmanijak@users.noreply.github.com>
diff --git a/plugins/woocommerce/changelog/fix-add-variation-id-to-add-to-cart-quantity-filter b/plugins/woocommerce/changelog/fix-add-variation-id-to-add-to-cart-quantity-filter
new file mode 100644
index 00000000000..68c1f67147b
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-add-variation-id-to-add-to-cart-quantity-filter
@@ -0,0 +1,4 @@
+Significance: patch
+Type: enhancement
+
+`woocommerce_add_to_cart_quantity` filter now receives `$variation_id`.
diff --git a/plugins/woocommerce/includes/class-wc-cart.php b/plugins/woocommerce/includes/class-wc-cart.php
index 2a01387a2c5..d513a481073 100644
--- a/plugins/woocommerce/includes/class-wc-cart.php
+++ b/plugins/woocommerce/includes/class-wc-cart.php
@@ -1154,11 +1154,26 @@ class WC_Cart extends WC_Legacy_Cart {
// Ensure we don't add a variation to the cart directly by variation ID.
if ( 'product_variation' === get_post_type( $product_id ) ) {
$variation_id = $product_id;
- $product_id = wp_get_post_parent_id( $variation_id );
+
+ // Guard against wp_get_post_parent_id returning false for invalid posts.
+ $product_id = wp_get_post_parent_id( $variation_id );
+ if ( false === $product_id ) {
+ return false;
+ }
}
$product_data = wc_get_product( $variation_id ? $variation_id : $product_id );
- $quantity = apply_filters( 'woocommerce_add_to_cart_quantity', $quantity, $product_id );
+
+ /**
+ * Filters the change the quantity to add to cart.
+ *
+ * @since 3.1.0
+ * @since 11.0.0 Added the `$variation_id` parameter.
+ * @param number $quantity The default quantity.
+ * @param number $product_id The product id.
+ * @param number $variation_id The variation ID.
+ */
+ $quantity = apply_filters( 'woocommerce_add_to_cart_quantity', $quantity, $product_id, $variation_id );
if ( $quantity <= 0 || ! $product_data || ProductStatus::TRASH === $product_data->get_status() ) {
return false;
diff --git a/plugins/woocommerce/phpstan-baseline.neon b/plugins/woocommerce/phpstan-baseline.neon
index a41c4e3b44a..3f9e35eca02 100644
--- a/plugins/woocommerce/phpstan-baseline.neon
+++ b/plugins/woocommerce/phpstan-baseline.neon
@@ -10290,12 +10290,6 @@ parameters:
count: 3
path: includes/class-wc-cart.php
- -
- message: '#^Parameter \#1 \$product_id of method WC_Cart\:\:generate_cart_id\(\) expects int, int\|false given\.$#'
- identifier: argument.type
- count: 1
- path: includes/class-wc-cart.php
-
-
message: '#^Parameter \#1 \$stock_quantity of function wc_format_stock_quantity_for_display expects int, int\|null given\.$#'
identifier: argument.type
diff --git a/plugins/woocommerce/src/Blocks/BlockTypes/ProductButton.php b/plugins/woocommerce/src/Blocks/BlockTypes/ProductButton.php
index 6b28dd2e1ff..91f2bf93a2e 100644
--- a/plugins/woocommerce/src/Blocks/BlockTypes/ProductButton.php
+++ b/plugins/woocommerce/src/Blocks/BlockTypes/ProductButton.php
@@ -132,10 +132,12 @@ class ProductButton extends AbstractBlock {
* Filters the change the quantity to add to cart.
*
* @since 8.5.0
+ * @since 11.0.0 Added the `$variation_id` parameter.
* @param number $default_quantity The default quantity.
* @param number $product_id The product id.
+ * @param number $variation_id The variation ID. Always 0 in this context.
*/
- $default_quantity = apply_filters( 'woocommerce_add_to_cart_quantity', $default_quantity, $product->get_id() );
+ $default_quantity = apply_filters( 'woocommerce_add_to_cart_quantity', $default_quantity, $product->get_id(), 0 );
}
$add_to_cart_text = null !== $product->add_to_cart_text() ? $product->add_to_cart_text() : __( 'Add to cart', 'woocommerce' );
diff --git a/plugins/woocommerce/tests/php/includes/class-wc-cart-test.php b/plugins/woocommerce/tests/php/includes/class-wc-cart-test.php
index 90543dbe637..bda64ad40f1 100644
--- a/plugins/woocommerce/tests/php/includes/class-wc-cart-test.php
+++ b/plugins/woocommerce/tests/php/includes/class-wc-cart-test.php
@@ -12,6 +12,14 @@ use Automattic\WooCommerce\Tests\Blocks\Helpers\FixtureData;
* Class WC_Cart_Test
*/
class WC_Cart_Test extends \WC_Unit_Test_Case {
+
+ /**
+ * Stores arguments received by the woocommerce_add_to_cart_quantity filter.
+ *
+ * @var array
+ */
+ protected $add_to_cart_quantity_filter_args = array();
+
/**
* Called before every test.
*/
@@ -30,6 +38,8 @@ class WC_Cart_Test extends \WC_Unit_Test_Case {
WC()->cart->empty_cart();
WC()->customer->set_is_vat_exempt( false );
WC()->session->set( 'wc_notices', null );
+
+ remove_filter( 'woocommerce_add_to_cart_quantity', array( $this, 'capture_add_to_cart_quantity_filter_args' ), 10 );
}
/**
@@ -1458,6 +1468,64 @@ class WC_Cart_Test extends \WC_Unit_Test_Case {
$product->delete( true );
}
+
+ /**
+ * Capture all arguments passed to the filter without modifying the quantity.
+ *
+ * @param int $quantity The quantity to add to cart.
+ * @param int $product_id The parent product ID.
+ * @param int $variation_id The variation ID being added.
+ *
+ * @return int
+ */
+ public function capture_add_to_cart_quantity_filter_args( $quantity, $product_id, $variation_id ) {
+ $this->add_to_cart_quantity_filter_args = func_get_args();
+ return $quantity;
+ }
+
+ /**
+ * @testdox woocommerce_add_to_cart_quantity filter should receive variation_id when a variable product is added to cart.
+ */
+ public function test_add_to_cart_quantity_filter_receives_variation_id() {
+ add_filter( 'woocommerce_add_to_cart_quantity', array( $this, 'capture_add_to_cart_quantity_filter_args' ), 10, 3 );
+
+ // Create a variable product and pick the first available variation to add.
+ $product = WC_Helper_Product::create_variation_product();
+ $variations = $product->get_available_variations();
+ $variation = $variations[0];
+
+ WC()->cart->add_to_cart(
+ $product->get_id(),
+ 1,
+ $variation['variation_id'],
+ $variation['attributes']
+ );
+
+ // Ensure all 3 arguments were passed before accessing individual indexes.
+ $this->assertCount( 3, $this->add_to_cart_quantity_filter_args, 'Filter should receive exactly 3 arguments.' );
+
+ $this->assertEquals( 1, $this->add_to_cart_quantity_filter_args[0] );
+ $this->assertEquals( $product->get_id(), $this->add_to_cart_quantity_filter_args[1] );
+ $this->assertEquals( $variation['variation_id'], $this->add_to_cart_quantity_filter_args[2] );
+ }
+
+ /**
+ * @testdox woocommerce_add_to_cart_quantity filter should receive 0 as variation_id when a simple product is added to cart.
+ */
+ public function test_add_to_cart_quantity_filter_receives_zero_variation_id_for_simple_product() {
+ add_filter( 'woocommerce_add_to_cart_quantity', array( $this, 'capture_add_to_cart_quantity_filter_args' ), 10, 3 );
+
+ $product = WC_Helper_Product::create_simple_product();
+
+ WC()->cart->add_to_cart( $product->get_id(), 1 );
+
+ $this->assertCount( 3, $this->add_to_cart_quantity_filter_args, 'Filter should receive exactly 3 arguments.' );
+
+ $this->assertEquals( 1, $this->add_to_cart_quantity_filter_args[0] );
+ $this->assertEquals( $product->get_id(), $this->add_to_cart_quantity_filter_args[1] );
+ $this->assertEquals( 0, $this->add_to_cart_quantity_filter_args[2] );
+ }
+
/**
* Applying the same coupon a second time returns false and leaves the discount total unchanged.
*/