Reputation: 67
My WooCommerce website is selling 2 limited edition products to raise money for cancer research. One is a men's shoe, the other is a women's shoe.
Because these products are going to be offered as a pre-sale (they won't be ready to ship out until September) I want to ensure any orders that contain 1 of these shoes cannot have other products in the cart (because this will cause the order to be partially fulfilled, which will cause confusion for everyone).
Here is the behavior I want:
Just for reference, the WooCommerce product IDs for the 2 products are: 348455 and 348443. They are both in a product category called 'EMI' and the product category ID is 348.
Here is the code I have written so far, based on a similar Stackoverflow question from 2017 I found. The problem with my code below is, if I add a normal product to my cart first, then one of the limited edition shoes, it will remove the limited edition shoe from my cart instead of the normal product.
It works properly if I add the limited edition shoe first, then a normal product after. Can someone help me find out what is wrong?
add_action( 'woocommerce_add_to_cart', 'check_product_added_to_cart', 10, 6 );
function check_product_added_to_cart($cart_item_key, $product_id, $quantity, $variation_id, $variation, $cart_item_data) {
// Set HERE your targeted product IDs
$target_product_id_one = 348455;
$target_product_id_two = 348443;
// Initialising some variables
$has_item = false;
$is_product_id = false;
foreach( WC()->cart->get_cart() as $key => $item ){
// Check if there are other products in the cart with the 2 limited edition shoes
if( $item['product_id'] !== $target_product_id_one && $item['product_id'] !== $target_product_id_two ){
$has_item = true;
$key_to_remove = $key;
}
// Check if we add to cart the targeted product ID
if( $product_id == $target_product_id_one || $product_id == $target_product_id_two ){
$is_product_id = true;
}
}
if( $has_item && $is_product_id ){
WC()->cart->remove_cart_item($key_to_remove);
// Optionaly displaying a notice for the removed item:
wc_add_notice( __( 'Due to the presale, EMI products cannot be purchased with other products in the same order.', 'theme_domain' ), 'notice' );
}
}
Upvotes: 2
Views: 1641
Reputation: 505
I found some code that should work for you. It checks if the product is in the cart when the 2nd (or subsequent) item is added to your cart and removes everything else if the special shoe is the 1st thing added to the cart, and removes the special shoe if a normal product is the 1st thing added to the cart.
// Remove conditionally cart items based on a specific product (item)
add_action( 'woocommerce_before_calculate_totals', 'remove_cart_items_conditionally_a', 10, 1 );
function remove_cart_items_conditionally_a( $cart ) {
// HERE define your specific product ID
$specific_product_id = 348455;
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
$cart_items = $cart->get_cart(); // Cart items array
$items_count = count($cart_items); // Different cart items count
// Continue if cart has at least 2 different cart items
if ( $items_count < 2 )
return;
$last_item = end($cart_items); // Last cart item data array
$is_last_item = false; // Initializing
// Check if the specific product is the last added item
if ( in_array($specific_product_id, array( $last_item['product_id'], $last_item['variation_id'] ) ) ) {
$is_last_item = true;
}
// Loop through cart items
foreach ( $cart_items as $cart_item_key => $cart_item ) {
// Remove all others cart items when specific product ID is --the last-- added to cart
if ( ! in_array($specific_product_id, array( $cart_item['product_id'], $cart_item['variation_id'] ) ) && $is_last_item ) {
$cart->remove_cart_item( $cart_item_key );
// Optionaly displaying a notice for the removed item:
wc_add_notice( __( 'Due to the presale, AMI products cannot be purchased with other products in the same order.', 'theme_domain' ), 'notice' );
}
// Remove the specific item when its is not the last added to cart
elseif ( in_array($specific_product_id, array( $cart_item['product_id'], $cart_item['variation_id'] ) ) && ! $is_last_item ) {
$cart->remove_cart_item( $cart_item_key );
// Optionaly displaying a notice for the removed item:
wc_add_notice( __( 'Due to the presale, AMI products cannot be purchased with other products in the same order.', 'theme_domain' ), 'notice' );
}
}
}
Upvotes: 3