Search code examples
phpwordpresswoocommerceproductcart

WooCommerce guest cart items merged with items when user logs in issue


In WooCommerce I have set a variable product with 4 variations and have checked the "Sold individually" checkbox so only 1 of this product could be added to cart. Moving forward, I will refer to the 4 variations of this product as 'Packages'.

I'm also using this code snippet to empty the cart when 1 of the 4 packages gets added to cart:

add_filter( 'woocommerce_add_to_cart_validation', 'custom_empty_cart', 10, 3 );
function custom_empty_cart( $passed, $product_id, $quantity ) {
    if( ( ! WC()->cart->is_empty() ) && in_array( $product_id, [7193, 7194, 7195, 7196] ) )
        WC()->cart->empty_cart();

    return $passed;
}

Basically, it should not be possible to add more than 1 package to cart, which is what I want.

However, here's the issue:

1. A user logs out of an account with a package left in the cart

2. The user then adds 1 of the 4 packages to cart as a guest

3. And then the user logs back in to the account

4. 2 packages appear in the cart: the one left in the cart before logging out and the other one added to cart as a guest before logging back in

Is there a way to prevent this? Only the latest package added to cart while being logged out should appear in the cart.


Solution

  • To avoid this problem use additionally the following code:

    add_action( 'woocommerce_before_calculate_totals', 'keep_last_defined_package_in_cart', 20, 1 );
    function keep_last_defined_package_in_cart( $cart ){
        if ( is_admin() && ! defined('DOING_AJAX' ) )
            return;
        
        $targeted_ids  = array( 7193, 7194, 7195, 7196 );
        $cart_items    = $cart->get_cart();
        $targeted_keys = array();
    
        if ( count( $cart_items ) > 1 ) {
            foreach ( $cart_items as $item_key => $item ) {
                if ( array_intersect( $targeted_ids, array($item['product_id'], $item['variation_id']) ) ) {
                    $targeted_keys[] = $item_key;
                }
            }
            
            // Remove first related item when more than one
            if ( count( $targeted_keys ) > 1 ) {
                $cart->remove_cart_item( reset($targeted_keys) ); 
            }
        }
    }
    

    Code goes in functions.php file of the active child theme (or active theme). It should work.