Reputation: 143
I want to prevent users from adding products from different categories into cart at once. Say if the user navigates to another categories and tries to add product to cart, they get the cart cleared out first. Please anybody know how i might approach this? I am a newbie at things like this. Thanks
Upvotes: 7
Views: 6806
Reputation: 216
Here is my solution for this (You can replace 'city' by 'product_cat' to make it work for product categories:
function validate_add_cart_item( $passed, $product_id, $quantity, $variation_id = '', $variations= '' ) {
// Get the list of cities for the item to be added
$product_cities = get_the_terms( $product_id, 'city' );
$cities_array = array_map(function($city){
return $city->slug;
}, $product_cities);
// Get the cart items
$item_in_cart = WC()->cart->get_cart();
// Check for each item if the city is different
foreach ($item_in_cart as $item){
$cities = get_the_terms( $item['product_id'], 'city' );
foreach ($cities as $city){
if(!in_array($city->slug, $cities_array)){
$passed = false;
wc_add_notice( __( 'You cannot mix products from two cities', 'domain' ), 'error' );
}
}
}
return $passed;
}
add_filter( 'woocommerce_add_to_cart_validation', 'validate_add_cart_item', 10, 5 );
Upvotes: 0
Reputation: 640
I've solved this before. My write-up is here.
It differs slightly from your request in that instead of clearing the cart when they try to add a second category it keeps the original item in the cart and displays a warning.
For posterity:
<?php
// Enforce single parent category items in cart at a time based on first item in cart
function get_product_top_level_category ( $product_id ) {
$product_terms = get_the_terms ( $product_id, 'product_cat' );
$product_category_term = $product_terms[0];
$product_category_parent = $product_terms[0]->parent;
while ( $product_category_parent != 0 ) {
$product_category_term = get_term($product_category_parent, 'product_cat' );
$product_category_parent = $product_category_term->parent;
}
return $product_category_term;
}
add_filter ( 'woocommerce_before_cart', 'restrict_cart_to_single_category' );
function restrict_cart_to_single_category() {
global $woocommerce;
$cart_contents = $woocommerce->cart->get_cart( );
$cart_item_keys = array_keys ( $cart_contents );
$cart_item_count = count ( $cart_item_keys );
// Do nothing if the cart is empty
// Do nothing if the cart only has one item
if ( ! $cart_contents || $cart_item_count == 1 ) {
return null;
}
// Multiple Items in cart
$first_item = $cart_item_keys[0];
$first_item_id = $cart_contents[$first_item]['product_id'];
$first_item_top_category = get_product_top_level_category ( $first_item_id );
$first_item_top_category_term = get_term ( $first_item_top_category, 'product_cat' );
$first_item_top_category_name = $first_item_top_category_term->name;
// Now we check each subsequent items top-level parent category
foreach ( $cart_item_keys as $key ) {
if ( $key == $first_item ) {
continue;
}
else {
$product_id = $cart_contents[$key]['product_id'];
$product_top_category = get_product_top_level_category( $product_id );
if ( $product_top_category != $first_item_top_category ) {
$woocommerce->cart->set_quantity ( $key, 0, true );
$mismatched_categories = 1;
}
}
}
// we really only want to display this message once for anyone, including those that have carts already prefilled
if ( isset ( $mismatched_categories ) ) {
echo '<p class="woocommerce-error">Only one category allowed in cart at a time.<br />You are currently allowed only <strong>'.$first_item_top_category_name.'</strong> items in your cart.<br />To order a different category empty your cart first.</p>';
}
}
?>
Upvotes: 8