phpwoocommerceproductcategoriescart

Prevent different defined categories in WooCommerce cart


I've been trying to adapt the code found in this thread to work across multiple categories.

I have set up multiple categories to reflect date: Market 1, Market 2, Market 3...

The code I've adapted works sometimes, but not constantly:

//*** Prevent mixture of market dates in same cart ***//
function dont_add_market_to_cart_containing_other_market($validation, $product_id) {

// Set flag false until we find a product in cat market (_1,_2_3...)
    $cart_has_market = false;

// Set $cat_check true if a cart item is in market cat
    foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item) {

        $product = $cart_item['data'];

        if ( has_term('market-1', 'product_cat', $product->id) || has_term('market-2', 'product_cat', $product->id) || has_term('market-3', 'product_cat', $product->id) ) {
            $cart_has_market = true;
            // break because we only need one "true" to matter here
            break;
        }
    }

    $product_is_market = false;
    if ( has_term('market-1', 'product_cat', $product_id) ||  has_term('market-2', 'product_cat', $product_id) || has_term('market-3', 'product_cat', $product_id) ) {
        $product_is_market = true;
    }

// Return true if cart empty
    if (!WC()->cart->get_cart_contents_count() == 0) {
        // If cart contains market date 1 and product to be added is not market, display error message and return false.
        if ($cart_has_market && !$product_is_market) {
            wc_add_notice('Sorry, you can only purchase indivifual market dates on their own. To purchase this product, please checkout your current cart or empty your cart and try again', 'error');
            $validation = false;
        }
        // If cart contains a product that is not market and product to be added is market, display error message and return false.
        elseif (!$cart_has_market && $product_is_market) {
            wc_add_notice('Sorry, you can only purchase indivifual market dates on their own. To purchase this product, please checkout your current cart or empty your cart and try again', 'error');
            $validation = false;
        }
    }
    // Otherwise, return true.
    return $validation;
}

add_filter('woocommerce_add_to_cart_validation', 'dont_add_market_to_cart_containing_other', 10, 2);

Additional info:

With date from Market 1 added to the cart I try and add dates from Market 2 to the cart (Fig A).

Market 2 is disallowed and the error message is triggered. However I'm getting an error message per product/date (Fig B).

enter image description here


Solution

  • There are some mistakes and complications in your code attempt. Try the following instead:

    add_filter('woocommerce_add_to_cart_validation', 'prevent_different_market_categories_in_cart', 10, 2);
    function prevent_different_market_categories_in_cart( $passed, $product_id ) {
        // Exit if cart is empty
        if ( WC()->cart->is_empty() ) {
            return $passed;
        }
        // Here define your categories
        $categories = array('market-1', 'market-2', 'market-3');
        $taxonomy = 'product_cat'; // Product category taxonomy
        $categories_found = array(); // Initializing
    
        // Check the current product
        foreach( $categories as $category ) {
            if ( has_term( $category, 'product_cat', $product_id ) ) {
                $categories_found[$category] = $category;
            }
        }
        
        // Check cart items
        foreach ( WC()->cart->get_cart() as $cart_item ) {
            foreach( $categories as $category ) {
                if ( has_term( $category, $taxonomy, $cart_item['product_id']) ) {
                    $categories_found[$category] = $category;
                    break;
                }
            }
        }
    
        // If there is more than 1 different market categories found, avoid add to cart
        if ( count($categories_found) > 1 ) {
            wc_add_notice( __('Sorry, you can only purchase indivifual market dates on their own. To purchase this product, please checkout your current cart or empty your cart and try again'), 'error');
            $passed = false;
        }
        return $passed;
    }
    

    It should work.