Fix cloning cart keeps wrong reference in session and fee (#39282)
This commit is contained in:
commit
60fa13e21b
|
@ -1,4 +1,4 @@
|
||||||
Significance: patch
|
Significance: patch
|
||||||
Type: fix
|
Type: fix
|
||||||
|
|
||||||
Fixes PHP error when WooCommerce menus are created without a position and when users view the WordPress admin dashboard without having WooCommerce admin permissions.
|
Use correct object reference when cloning a cart
|
||||||
|
|
|
@ -26,14 +26,6 @@ final class WC_Cart_Fees {
|
||||||
*/
|
*/
|
||||||
private $fees = array();
|
private $fees = array();
|
||||||
|
|
||||||
/**
|
|
||||||
* Reference to cart object.
|
|
||||||
*
|
|
||||||
* @since 3.2.0
|
|
||||||
* @var WC_Cart
|
|
||||||
*/
|
|
||||||
private $cart;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* New fees are made out of these props.
|
* New fees are made out of these props.
|
||||||
*
|
*
|
||||||
|
@ -51,16 +43,18 @@ final class WC_Cart_Fees {
|
||||||
/**
|
/**
|
||||||
* Constructor. Reference to the cart.
|
* Constructor. Reference to the cart.
|
||||||
*
|
*
|
||||||
|
* @param null $deprecated Deprecated since WooCommerce 8.2.0.
|
||||||
|
*
|
||||||
* @since 3.2.0
|
* @since 3.2.0
|
||||||
* @throws Exception If missing WC_Cart object.
|
|
||||||
* @param WC_Cart $cart Cart object.
|
|
||||||
*/
|
*/
|
||||||
public function __construct( &$cart ) {
|
public function __construct( $deprecated = null ) {
|
||||||
if ( ! is_a( $cart, 'WC_Cart' ) ) {
|
if ( isset( $deprecated ) ) {
|
||||||
throw new Exception( 'A valid WC_Cart object is required' );
|
wc_doing_it_wrong(
|
||||||
|
'new WC_Cart_Fees',
|
||||||
|
'You don\'t need to pass a cart parameter to the WC_Cart_Fees constructor anymore',
|
||||||
|
'8.2.0'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->cart = $cart;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -33,14 +33,24 @@ final class WC_Cart_Session {
|
||||||
*
|
*
|
||||||
* @param WC_Cart $cart Cart object to calculate totals for.
|
* @param WC_Cart $cart Cart object to calculate totals for.
|
||||||
*/
|
*/
|
||||||
public function __construct( &$cart ) {
|
public function __construct( $cart ) {
|
||||||
if ( ! is_a( $cart, 'WC_Cart' ) ) {
|
if ( ! is_a( $cart, 'WC_Cart' ) ) {
|
||||||
throw new Exception( 'A valid WC_Cart object is required' );
|
throw new Exception( 'A valid WC_Cart object is required' );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->set_cart( $cart );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the cart instance.
|
||||||
|
*
|
||||||
|
* @param WC_Cart $cart Cart object.
|
||||||
|
*/
|
||||||
|
public function set_cart( WC_Cart $cart ) {
|
||||||
$this->cart = $cart;
|
$this->cart = $cart;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register methods for this object on the appropriate WordPress hooks.
|
* Register methods for this object on the appropriate WordPress hooks.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -98,7 +98,7 @@ class WC_Cart extends WC_Legacy_Cart {
|
||||||
*/
|
*/
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
$this->session = new WC_Cart_Session( $this );
|
$this->session = new WC_Cart_Session( $this );
|
||||||
$this->fees_api = new WC_Cart_Fees( $this );
|
$this->fees_api = new WC_Cart_Fees();
|
||||||
|
|
||||||
// Register hooks for the objects.
|
// Register hooks for the objects.
|
||||||
$this->session->init();
|
$this->session->init();
|
||||||
|
@ -120,6 +120,8 @@ class WC_Cart extends WC_Legacy_Cart {
|
||||||
public function __clone() {
|
public function __clone() {
|
||||||
$this->session = clone $this->session;
|
$this->session = clone $this->session;
|
||||||
$this->fees_api = clone $this->fees_api;
|
$this->fees_api = clone $this->fees_api;
|
||||||
|
|
||||||
|
$this->session->set_cart( $this );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -667,7 +669,7 @@ class WC_Cart extends WC_Legacy_Cart {
|
||||||
public function get_cart_contents_weight() {
|
public function get_cart_contents_weight() {
|
||||||
$weight = 0.0;
|
$weight = 0.0;
|
||||||
|
|
||||||
foreach ( $this->get_cart() as $cart_item_key => $values ) {
|
foreach ( $this->get_cart() as $values ) {
|
||||||
if ( $values['data']->has_weight() ) {
|
if ( $values['data']->has_weight() ) {
|
||||||
$weight += (float) $values['data']->get_weight() * $values['quantity'];
|
$weight += (float) $values['data']->get_weight() * $values['quantity'];
|
||||||
}
|
}
|
||||||
|
@ -684,7 +686,7 @@ class WC_Cart extends WC_Legacy_Cart {
|
||||||
public function get_cart_item_quantities() {
|
public function get_cart_item_quantities() {
|
||||||
$quantities = array();
|
$quantities = array();
|
||||||
|
|
||||||
foreach ( $this->get_cart() as $cart_item_key => $values ) {
|
foreach ( $this->get_cart() as $values ) {
|
||||||
$product = $values['data'];
|
$product = $values['data'];
|
||||||
$quantities[ $product->get_stock_managed_by_id() ] = isset( $quantities[ $product->get_stock_managed_by_id() ] ) ? $quantities[ $product->get_stock_managed_by_id() ] + $values['quantity'] : $values['quantity'];
|
$quantities[ $product->get_stock_managed_by_id() ] = isset( $quantities[ $product->get_stock_managed_by_id() ] ) ? $quantities[ $product->get_stock_managed_by_id() ] + $values['quantity'] : $values['quantity'];
|
||||||
}
|
}
|
||||||
|
@ -759,7 +761,7 @@ class WC_Cart extends WC_Legacy_Cart {
|
||||||
$product_qty_in_cart = $this->get_cart_item_quantities();
|
$product_qty_in_cart = $this->get_cart_item_quantities();
|
||||||
$current_session_order_id = isset( WC()->session->order_awaiting_payment ) ? absint( WC()->session->order_awaiting_payment ) : 0;
|
$current_session_order_id = isset( WC()->session->order_awaiting_payment ) ? absint( WC()->session->order_awaiting_payment ) : 0;
|
||||||
|
|
||||||
foreach ( $this->get_cart() as $cart_item_key => $values ) {
|
foreach ( $this->get_cart() as $values ) {
|
||||||
$product = $values['data'];
|
$product = $values['data'];
|
||||||
|
|
||||||
// Check stock based on stock-status.
|
// Check stock based on stock-status.
|
||||||
|
@ -818,7 +820,7 @@ class WC_Cart extends WC_Legacy_Cart {
|
||||||
$cross_sells = array();
|
$cross_sells = array();
|
||||||
$in_cart = array();
|
$in_cart = array();
|
||||||
if ( ! $this->is_empty() ) {
|
if ( ! $this->is_empty() ) {
|
||||||
foreach ( $this->get_cart() as $cart_item_key => $values ) {
|
foreach ( $this->get_cart() as $values ) {
|
||||||
if ( $values['quantity'] > 0 ) {
|
if ( $values['quantity'] > 0 ) {
|
||||||
$cross_sells = array_merge( $values['data']->get_cross_sell_ids(), $cross_sells );
|
$cross_sells = array_merge( $values['data']->get_cross_sell_ids(), $cross_sells );
|
||||||
$in_cart[] = $values['product_id'];
|
$in_cart[] = $values['product_id'];
|
||||||
|
@ -908,7 +910,7 @@ class WC_Cart extends WC_Legacy_Cart {
|
||||||
public function get_cart_item_tax_classes() {
|
public function get_cart_item_tax_classes() {
|
||||||
$found_tax_classes = array();
|
$found_tax_classes = array();
|
||||||
|
|
||||||
foreach ( WC()->cart->get_cart() as $item ) {
|
foreach ( $this->get_cart() as $item ) {
|
||||||
if ( $item['data'] && ( $item['data']->is_taxable() || $item['data']->is_shipping_taxable() ) ) {
|
if ( $item['data'] && ( $item['data']->is_taxable() || $item['data']->is_shipping_taxable() ) ) {
|
||||||
$found_tax_classes[] = $item['data']->get_tax_class();
|
$found_tax_classes[] = $item['data']->get_tax_class();
|
||||||
}
|
}
|
||||||
|
@ -925,7 +927,7 @@ class WC_Cart extends WC_Legacy_Cart {
|
||||||
public function get_cart_item_tax_classes_for_shipping() {
|
public function get_cart_item_tax_classes_for_shipping() {
|
||||||
$found_tax_classes = array();
|
$found_tax_classes = array();
|
||||||
|
|
||||||
foreach ( WC()->cart->get_cart() as $item ) {
|
foreach ( $this->get_cart() as $item ) {
|
||||||
if ( $item['data'] && ( $item['data']->is_shipping_taxable() ) ) {
|
if ( $item['data'] && ( $item['data']->is_shipping_taxable() ) ) {
|
||||||
$found_tax_classes[] = $item['data']->get_tax_class();
|
$found_tax_classes[] = $item['data']->get_tax_class();
|
||||||
}
|
}
|
||||||
|
@ -1536,7 +1538,7 @@ class WC_Cart extends WC_Legacy_Cart {
|
||||||
}
|
}
|
||||||
$needs_shipping = false;
|
$needs_shipping = false;
|
||||||
|
|
||||||
foreach ( $this->get_cart_contents() as $cart_item_key => $values ) {
|
foreach ( $this->get_cart_contents() as $values ) {
|
||||||
if ( $values['data']->needs_shipping() ) {
|
if ( $values['data']->needs_shipping() ) {
|
||||||
$needs_shipping = true;
|
$needs_shipping = true;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -14,7 +14,7 @@ class WC_Tests_WC_Cart_Fees extends WC_Unit_Test_Case {
|
||||||
*/
|
*/
|
||||||
public function test_set_get_remove_fees() {
|
public function test_set_get_remove_fees() {
|
||||||
|
|
||||||
$cart_fees = new WC_Cart_Fees( wc()->cart );
|
$cart_fees = new WC_Cart_Fees();
|
||||||
|
|
||||||
// Test add_fee.
|
// Test add_fee.
|
||||||
$args = array(
|
$args = array(
|
||||||
|
|
|
@ -96,6 +96,37 @@ class WC_Cart_Test extends \WC_Unit_Test_Case {
|
||||||
$variable_product->delete( true );
|
$variable_product->delete( true );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test cloning cart holds no references in session
|
||||||
|
*/
|
||||||
|
public function test_cloning_cart_session() {
|
||||||
|
$product = WC_Helper_Product::create_simple_product();
|
||||||
|
|
||||||
|
// Initialize $cart1 and $cart2 as empty carts.
|
||||||
|
$cart1 = WC()->cart;
|
||||||
|
$cart1->empty_cart();
|
||||||
|
$cart2 = clone $cart1;
|
||||||
|
|
||||||
|
// Create a cart in session.
|
||||||
|
$cart1->add_to_cart( $product->get_id(), 1 );
|
||||||
|
$cart1->set_session();
|
||||||
|
|
||||||
|
// Empty the cart without clearing the session.
|
||||||
|
$cart1->set_cart_contents( array() );
|
||||||
|
|
||||||
|
// Both carts are empty at that point.
|
||||||
|
$this->assertTrue( $cart2->is_empty() );
|
||||||
|
$this->assertTrue( $cart1->is_empty() );
|
||||||
|
|
||||||
|
$cart2->get_cart_from_session();
|
||||||
|
|
||||||
|
// We retrieved $cart2 from the previously set session so it should not be empty.
|
||||||
|
$this->assertFalse( $cart2->is_empty() );
|
||||||
|
|
||||||
|
// We didn't touch $cart1 so it should still be empty.
|
||||||
|
$this->assertTrue( $cart1->is_empty() );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test show shipping.
|
* Test show shipping.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue