WooCommerce Cart - Conditional Items categories validation - php

We have an exclusive category X and others regular categories Y. What I would like:
When someone orders anything from category X, other category items cannot be added to cart and should display a warning
category Y products should not be mixed with X.
How could I achieve that?
I got this code from other post, but its outdated and not satisfactory:
<?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 = $product_terms[0]->parent;
$product_category_term = get_term ( $product_category, 'product_cat' );
$product_category_parent = $product_category_term->parent;
$product_top_category = $product_category_term->term_id;
while ( $product_category_parent != 0 ) {
$product_category_term = get_term ( $product_category_parent, 'product_cat' );
$product_category_parent = $product_category_term->parent;
$product_top_category = $product_category_term->term_id;
}
return $product_top_category;
}
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>';
}
}
?>
Thanks

Updated (2019)
Like everything is turning around your exclusive category category X, you need to use a conditional for this category.
And you have chance because there is a special function that you can use in combination with woocommerce product categories. Lets say that **cat_x** is the slug for your exclusive category, as you know it yet product_cat is the argument to get products categories.
So with has_term () conditional function, you are going to use this:
if ( has_term ('cat_x', 'product_cat', $item_id ) ) { // or $product_id
// doing something when product item has 'cat_x'
} else {
// doing something when product item has NOT 'cat_x'
}
We need to run the cart items 2 times in a foreach loop:
To detect if there is a cat_x item in that car.
To remove other items if cat_x is detected for one item in the cart and to fire the right messages.
In the code below, I have changed to a more useful hook. This hook will check what you have in your cart. The idea is to removed other categories items in the cart when there is a 'cat_x' item added in cart.
The code is well commented. At the end you will find different notices that are fired. You will need to put your real text in each.
add_action( 'woocommerce_check_cart_items', 'checking_cart_items' );
function checking_cart_items() {
// Set your product category slug
$category = 'cat_x';
$number_of_items = sizeof( WC()->cart->get_cart() );
$found = false; // Initializing
$notice = ''; // Initializing
if ( $number_of_items > 0 ) {
// Loop through cart items
foreach ( WC()->cart->get_cart() as $cart_item ) {
$product = $cart_item['data'];
$product_id = $cart_item['product_id'];
// Detecting if the defined category is in cart
if ( has_term( $category, 'product_cat', $product_id ) ) {
$found = true;
break; // Stop the loop
}
}
// Re-loop through cart items
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
$product = $cart_item['data'];
$product_id = $cart_item['product_id'];
if ( $found ) // If the defined product category is in cart
{
if ( $number_of_items == 1 ) { // only one defined product category
if ( empty( $notice ) ){
$notice = '1';
}
}
if ( $number_of_items >= 2 ) { // The defined product category + other categories in cart
// removing other categories items from cart
if ( ! has_term( $category, 'product_cat', $product_id ) ) {
WC()->cart->remove_cart_item( $cart_item_key ); // removing item from cart
if ( empty( $notice ) || $notice == '1' ){
$notice = '2';
}
}
}
} else { // Only other categories items
if ( empty( $notice ) ){
$notice = '3';
}
}
}
// Firing woocommerce notices
if ( $notice == '1' ) { // message for an 'cat_x' item only (alone)
wc_add_notice( sprintf( '<p class="woocommerce-error">bla bla bla one category X item in the cart</p>' ), 'success' );
} elseif ( $notice == '2' ) { // message for an 'cat_x' item and other ones => removed other ones
wc_add_notice( sprintf( '<p class="woocommerce-error">bla bla bla ther is already category X in the cart => Other category items has been removed</p>' ), 'error' );
} elseif ( $notice == '3' ) { // message for other categories items (if needed)
wc_add_notice( sprintf( '<p class="woocommerce-error">bla bla bla NOT category X in the cart</p>' ), 'success' );
}
}
}
Is not possible for me to really test this code (but it doesn't throws errors)…
#edit
We can use something else than notices… everything is possible. But it's a good starting solution, to fine tune.
You will need to replace 'cat_x' by your real category slug (in the beginning)…

Answer in 2020
Recently, I need almost the same requirement. But instead of a single category, I have to check if the item is in a group of categories.
Consider that I have 6 categories. I will group 6 categories into 3 groups. My customer can only purchase items in a single category group (but multiple categories) in a single order.
The code snippet is given below.
function sa45er_category_group_validation($valid, $product_id, $quantity) {
global $woocommerce;
if($woocommerce->cart->cart_contents_count == 0){
return $valid;
}
$target_cat_group = array(
array(17,20), // Update your product category
array(19,18), // Update your product category
);
$this_product_terms = get_the_terms( $product_id, 'product_cat' );
foreach ($this_product_terms as $term) {
$this_product_cat_ids[] = $term->term_id;
}
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
$terms = get_the_terms( $_product->get_ID(), 'product_cat' );
foreach ($terms as $term) {
$cart_cat_ids[] = $term->term_id;
}
}
$all_cats = array_merge($this_product_cat_ids,$cart_cat_ids);
$result = array();
foreach($target_cat_group as $target_cat_group_item){
$intrsct = array_intersect($all_cats, $target_cat_group_item);
if( !empty( $intrsct ) ){
$result[] = $intrsct;
}
}
if(count($result) > 1){
wc_add_notice( 'You can\'t add this product with your current cart items.', 'error' );
return false;
}
return $valid;
}
add_filter( 'woocommerce_add_to_cart_validation', 'sa45er_category_group_validation',10,3);

Related

Remove add on product from cart when product category is removed

I am working on an ecommerce store selling a variety of products. We have one line where there is an ice pack included to make sure our shipping prices are accurate. I have added code so the product gets added. The issue is when they remove the products the ice pack stays in the cart. I am looking to have it be auto removed as well.
I have added this code into the functions.php of my child theme
function df_add_ticket_surcharge( $cart_object ) {
global $woocommerce;
$specialfeecat = 45; // category id you want to check for
$spfee = 0.00; // initialize special fee
$spfeeperprod = 0.00; //special fee per product
$found = $false; //required to make the code later only add the item once, also stop loops.
$product_id = 1414; //product id of the one you want to add
foreach ( $cart_object->cart_contents as $key => $value ) {
$proid = $value['product_id']; //get the product id from cart
$quantity = $value['quantity']; //get quantity from cart
$itmprice = $value['data']->price; //get product price
//check if the desired product is already in cart.
if ( sizeof( $woocommerce->cart->get_cart() ) > 0 ) {
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
if ( $_product->id == $product_id )
$found = true;
}
}
//check for the category and add desired product
$terms = get_the_terms( $proid, 'product_cat' ); //get taxonomy of the products
if ( $terms && ! is_wp_error( $terms ) ) :
foreach ( $terms as $term ) {
$catid = $term->term_id;
if($specialfeecat == $catid && ! $found) {
WC()->cart->add_to_cart( 1414 );
}
}
endif;
}
}
add_action( 'woocommerce_cart_calculate_fees', 'df_add_ticket_surcharge' );

If Customer Has Never Bought, Add Product to Cart - Code Not Working

I am trying to implement a function that will check if a customer has ever bought ANY product from my shop before, and if not - provide them with a free "sign-up gift" on first purchase.
I am able to automatically add the product to the cart fine enough, but the issue occurs afterwards - the product keeps getting added to the cart even after a customer has made a purchase.
Code below - can't figure what the issue might be.
function has_bought( $user_id = 0 ) {
global $wpdb;
$customer_id = $user_id == 0 ? get_current_user_id() : $user_id;
$paid_order_statuses = array_map( 'esc_sql', wc_get_is_paid_statuses() );
$results = $wpdb->get_col( "
SELECT p.ID FROM {$wpdb->prefix}posts AS p
INNER JOIN {$wpdb->prefix}postmeta AS pm ON p.ID = pm.post_id
WHERE p.post_status IN ( 'wc-" . implode( "','wc-", $paid_order_statuses ) . "' )
AND p.post_type LIKE 'shop_order'
AND pm.meta_key = '_customer_user'
AND pm.meta_value = $customer_id
" );
// Count number of orders and return a boolean value depending if higher than 0
return count( $results ) > 0 ? true : false;
}
function aaptc_add_product_to_cart() {
if( ! has_bought() && ! is_admin() && is_user_logged_in() ) {
$product_id = 2449; // Product Id of the free product which will get added to cart
$found = false;
//check if product already in cart
if ( sizeof( WC()->cart->get_cart() ) > 0 ) {
foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
if ( $_product->get_id() == $product_id )
$found = true;
}
// if product not found, add it
if ( ! $found )
WC()->cart->add_to_cart( $product_id );
} else {
// if no products in cart, add it
WC()->cart->add_to_cart( $product_id );
}
}
}
add_action( 'init', 'aaptc_add_product_to_cart' );
**** EDIT ****
Based on the support provided I have some new code that auto-adds the product to the cart, checks for orders and removes the product if orders exist.
Can someone please confirm whether the code below is correct?
/*
* Automatically add product to cart
*/
function insta_add_product_to_cart() {
if ( ! is_admin() ) {
$product_id = 2449; // Product Id of the free product which will get added to cart
$found = false;
//check if product already in cart
if ( sizeof( WC()->cart->get_cart() ) > 0 ) {
foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
if ( $_product->get_id() == $product_id )
$found = true;
}
// if product not found, add it
if ( ! $found )
WC()->cart->add_to_cart( $product_id );
} else {
// if no products in cart, add it
WC()->cart->add_to_cart( $product_id );
}
}
}
add_action( 'init', 'insta_add_product_to_cart' );
function remove_shirt_returning_customer() {
$product_id = 2449; // Product Id of the free product which will get added to cart
$user_id = get_current_user_id();
// Get orders by customer.
$args = array(
'customer_id' => $user_id,
);
$orders = wc_get_orders( $args );
if ( !empty($orders) ) {
WC()->cart->remove_cart_item( $product_id );
}
}
add_action( 'init', 'remove_shirt_returning_customer' );
**** EDIT ***
THE SOLUTION
So the previous code still gave me errors. What seems to work effectively (in my localhost environment) is the code below.
/*
* Automatically add product to cart
*/
function insta_add_product_to_cart() {
if ( ! is_admin() ) {
$product_id = 51; // Product Id of the free product which will get added to cart
$found = false;
//check if product already in cart
if ( sizeof( WC()->cart->get_cart() ) > 0 ) {
foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
if ( $_product->get_id() == $product_id )
$found = true;
}
// if product not found, add it
if ( ! $found )
WC()->cart->add_to_cart( $product_id );
} else {
// if no products in cart, add it
WC()->cart->add_to_cart( $product_id );
}
}
}
add_action( 'init', 'insta_add_product_to_cart' );
/*
* Remove item from cart if previous order exists
*/
function remove_shirt_returning_customer() {
if ( ! is_admin() ) {
$cart_items = WC()->cart->get_cart();
$product_id = 51; // Product Id of the free product which will get added to cart
$user_id = get_current_user_id();
// Get orders by customer.
$args = array(
'customer_id' => $user_id,
);
$orders = wc_get_orders( $args );
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
if ( $cart_item['product_id'] == $product_id && !empty( $orders ) ) {
WC()->cart->remove_cart_item( $cart_item_key );
}
}
}
}
add_action( 'init', 'remove_shirt_returning_customer' );
Instead of using that custom query try using the wc_get_orders function you can retrieve all the orders from a customer using the email address or the user id
// Get orders by customer with ID 12.
$args = array(
'customer_id' => 12,
);
$orders = wc_get_orders( $args );
More info about the wp_get_orders can be found here
You're only going to be able to tell whether the user has ordered from you before or not if they are logged into an account. So if the user is on your site and is logged into the account, you will have to find out which user that is:
$user_id = get_current_user_id();
From there use Enrique's answer to obtain whether that customer has placed an order with you or not.
$user_id = get_current_user_id();
$args = array(
'customer_id' => 12,
);
$orders = wc_get_orders( $args );
From there, test whether $orders is empty or not, if empty leave the item as a default in the cart, if not remove it.
A better approach would be to just automatically have the item in all carts, then conditionally check whether this user is logged in, and has placed an order with you before. If so, remove the item.

Check for Product Category in cart items with WooCommerce

I'm trying to make a condition, where a function displays on WooCommerce checkout page only, if any product from category ilutulestik is present in the shopping cart.
Currently, however, it does not seem to be able to obtain cart info. I assume that because, if I use if ( $cat_in_cart ) condition on a code, the function I use it on, does not display, even if I have a product from ilutulestik category present in the shopping cart.
I've tried many different methods to obtain cart info, but none have seemed to work. I'll include 2 ways of how I tried below:
Try 1
add_action('woocommerce_before_cart', 'kontrollime_ilutulestiku_olemasolu');
function kontrollime_ilutulestiku_olemasolu()
{
global $woocommerce;
$cat_in_cart = false;
foreach ( WC()->cart->get_cart() as $cart_item_key => $values )
{
$item = $values['data'];
$item_id = $item->id;
if ( has_term( 'ilutulestik-2', 'product_cat', $item_id ) )
{
$cat_in_cart = true;
break;
}
}
}
Try 2
add_action('woocommerce_before_cart', 'kontrollime_ilutulestiku_olemasolu');
function kontrollime_ilutulestiku_olemasolu($package)
{
global $woocommerce;
$cat_in_cart = false;
foreach ($package['contents'] as $product)
{
// get product categories
$product_cats = wp_get_post_terms(
$product['product_id'], 'product_cat', array('fields' => 'names') );
// if it has category_name unset flat rate
if( in_array('ilutulestik-2', $product_cats) )
{
$cat_in_cart = true;
break;
}
}
}
I expect this piece of code to check if there is a product in cart that belongs to category Ilutulestik (or slug ilutulestik-2) and if it does, change $cat_in_cart value to true, so later I could activate any code with if ( $cat_in_cart ).
The correct way for cart items to be used with product categories is:
add_action('woocommerce_before_cart', 'action_before_cart');
function action_before_cart() {
$categories = array('ilutulestik-2');
$has_category = false;
// Loop through cart items
foreach ( WC()->cart->get_cart() as $cart_item ) {
// Check for product categories
if ( has_term( $categories, 'product_cat', $cart_item['product_id'] ) ) {
$has_category = true;
break;
}
}
// Testing output (display a notice)
if ( $has_category ) {
wc_print_notice( sprintf( 'Product category "%s" is in cart!', reset($categories)), 'notice' );
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
If you need to check also for parent terms with product categories, you will use instead:
// Custom conditional function that handle parent product categories too
function has_product_categories( $categories, $product_id = 0 ) {
$parent_term_ids = $categories_ids = array(); // Initializing
$taxonomy = 'product_cat';
$product_id = $product_id == 0 ? get_the_id() : $product_id;
if( is_string( $categories ) ) {
$categories = (array) $categories; // Convert string to array
}
// Convert categories term names and slugs to categories term ids
foreach ( $categories as $category ){
$result = (array) term_exists( $category, $taxonomy );
if ( ! empty( $result ) ) {
$categories_ids[] = reset($result);
}
}
// Loop through the current product category terms to get only parent main category term
foreach( get_the_terms( $product_id, $taxonomy ) as $term ){
if( $term->parent > 0 ){
$parent_term_ids[] = $term->parent; // Set the parent product category
$parent_term_ids[] = $term->term_id; // (and the child)
} else {
$parent_term_ids[] = $term->term_id; // It is the Main category term and we set it.
}
}
return array_intersect( $categories_ids, array_unique($parent_term_ids) ) ? true : false;
}
add_action('woocommerce_before_cart', 'action_before_cart');
function action_before_cart() {
$categories = array('ilutulestik-2');
$has_category = false;
// Loop through cart items
foreach ( WC()->cart->get_cart() as $cart_item ) {
// Check for product categories
if ( has_product_categories( $cart_item['product_id'], $categories ) ) {
$has_category = true;
break;
}
}
// Testing output (display a notice)
if ( $has_category ) {
wc_print_notice( sprintf( 'Product category "%s" is in cart!', reset($categories)), 'notice' );
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.

Restricting cart items to be from the same product category in WooCommerce

I am using the code below to remove other WooCommerce product category items from the cart when there is an item with a special product category 'cat_x' added in cart and display some different custom notices. The code came from this thread and just works well:
add_action( 'woocommerce_check_cart_items', 'checking_cart_items' );
function checking_cart_items() {
$special = false;
$catx = 'cat_x';
$number_of_items = sizeof( WC()->cart->get_cart() );
if ( $number_of_items > 0 ) {
// Loop through all cart products
foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
$item = $values['data'];
$item_id = $item->id;
// detecting if 'cat_x' item is in cart
if ( has_term( $catx, 'product_cat', $item_id ) ) {
if (!$special)
$special = true;
}
}
// Re-loop through all cart products
foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
$item = $values['data'];
$item_id = $item->id;
if ( $special ) // there is a 'cat_x' item in cart
{
if ( $number_of_items == 1 ) { // only one 'cat_x' item in cart
if ( empty( $notice ) )
$notice = '1';
}
if ( $number_of_items >= 2 ) { // 'cat_x' item + other categories items in cart
// removing other categories items from cart
if ( !has_term( $catx, 'product_cat', $item_id ) ) {
WC()->cart->remove_cart_item( $cart_item_key ); // removing item from cart
if ( empty( $notice ) || $notice == '1' )
$notice = '2';
}
}
} else { // Only other categories items
if ( empty( $notice ) )
$notice = '3';
}
}
// Firing notices
if ( $notice == '1' ) { // message for an 'cat_x' item only (alone)
wc_add_notice( sprintf( '<p class="woocommerce-error">bla bla bla one category X item in the cart</p>' ), 'success' );
} elseif ( $notice == '2' ) { // message for an 'cat_x' item and other ones => removed other ones
wc_add_notice( sprintf( '<p class="woocommerce-error">bla bla bla ther is already category X in the cart => Other category items has been removed</p>' ), 'error' );
} elseif ( $notice == '3' ) { // message for other categories items (if needed)
wc_add_notice( sprintf( '<p class="woocommerce-error">bla bla bla NOT category X in the cart</p>' ), 'success' );
}
}
}
Has the conditional function has_term() works also with arrays of categories, I have tried instead of one category, to set an array of categories in that code. But it’s not working.
However, my needs have changed: I don’t want to let the customer have the possibility to select cart items from different categories. So the cart must always have items from the same product category.
Any help please?
Thanks.
Making a custom function hooked in woocommerce_add_to_cart_validation filter hook is going to do the job in a much more simpler way, without any need to set an array of categories.
So your code will be much more faster and compact. Additionally you can display a custom notice to warn the customer.
This code will avoid adding to cart, if an item of a different category is in cart:
add_filter( 'woocommerce_add_to_cart_validation', 'add_to_cart_validation_callback', 10, 3 );
function add_to_cart_validation_callback( $passed, $product_id, $quantity) {
// HERE set your alert text message
$message = __( 'MY ALERT MESSAGE.', 'woocommerce' );
if( ! WC()->cart->is_empty() ) {
// Get the product category terms for the current product
$terms_slugs = wp_get_post_terms( $product_id, 'product_cat', array('fields' => 'slugs'));
// Loop through cart items
foreach (WC()->cart->get_cart() as $cart_item ){
if( ! has_term( $terms_slugs, 'product_cat', $cart_item['product_id'] )) {
$passed = false;
wc_add_notice( $message, 'error' );
break;
}
}
}
return $passed;
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code is tested and it works
Restricting cart items to be only from different product categories:
Replace in the function the condition:
if( ! has_term( $product_cats, 'product_cat', $cart_item['product_id'] )) {
by
if( has_term( $product_cats, 'product_cat', $cart_item['product_id'] )) {
I just tried and i got a syntax error the array that i fixed this way:
$terms_slugs = wp_get_post_terms($product_id, 'product_cat', array('fields' => 'slugs'));
just a comma after product_cat distraction, but maybe somebody would need it.

Woocommerce - Prevent Adding items from two different categories to cart

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
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>';
}
}
?>
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 );

Categories