Skip to content

Instantly share code, notes, and snippets.

@espiat
Last active August 22, 2024 16:36
Show Gist options
  • Save espiat/ef8a073cbbb1fa01df73a06d7fde8852 to your computer and use it in GitHub Desktop.
Save espiat/ef8a073cbbb1fa01df73a06d7fde8852 to your computer and use it in GitHub Desktop.
woocommerce only physical or virtual product in cart - with add on plugin "Product Bundles" (bundle is virtual but has physical products)
<?php
/**
* Validate cart items and prevent adding incompatible product types.
*
* @param bool $passed
* @param int $product_id
* @param int $quantity
* @return bool
*/
function filter_wc_add_to_cart_validation( $passed, $product_id, $quantity ) {
$cart = WC()->cart->get_cart();
// If cart is empty, allow adding any product
if ( empty( $cart ) ) {
return $passed;
}
$product = wc_get_product( $product_id );
$cart_content = analyze_cart_content( $cart );
$product_type = get_product_type( $product );
// Check if the new product can be added to the cart
if ( !can_add_to_cart( $product_type, $cart_content ) ) {
wc_add_notice( __( "You can't combine these product types in the cart.", "woocommerce" ), 'error' );
return false;
}
return $passed;
}
add_filter( 'woocommerce_add_to_cart_validation', 'filter_wc_add_to_cart_validation', 10, 3 );
/**
* Check cart items before checkout.
*/
function filter_wc_check_cart_items() {
$cart = WC()->cart->get_cart();
$cart_content = analyze_cart_content( $cart );
if ( $cart_content['has_virtual'] && ( $cart_content['has_physical'] || $cart_content['has_bundle'] ) ) {
wc_add_notice( __( "You can't combine these product types in the cart.", "woocommerce" ), 'error' );
}
}
add_action( 'woocommerce_check_cart_items', 'filter_wc_check_cart_items' );
/**
* Analyze the content of the cart.
*
* @param array $cart
* @return array
*/
function analyze_cart_content( $cart ) {
$content = [
'has_physical' => false,
'has_virtual' => false,
'has_bundle' => false
];
foreach ( $cart as $cart_item ) {
$product_type = get_product_type( $cart_item['data'] );
$content["has_$product_type"] = true;
}
return $content;
}
/**
* Get the product type for our categorization.
*
* @param WC_Product $product
* @return string
*/
function get_product_type( $product ) {
if ( $product->get_type() === 'bundle' ) {
return 'bundle';
} elseif ( $product->is_virtual() ) {
return 'virtual';
} else {
return 'physical';
}
}
/**
* Check if a product can be added to the cart.
*
* @param string $product_type
* @param array $cart_content
* @return bool
*/
function can_add_to_cart( $product_type, $cart_content ) {
// Allow only virtual products (excluding bundles)
$only_virtual = $cart_content['has_virtual'] && !$cart_content['has_physical'] && !$cart_content['has_bundle'];
// Allow bundles and physical products together
$physical_and_bundle = ( $cart_content['has_physical'] || $cart_content['has_bundle'] ) && !$cart_content['has_virtual'];
if ( ( $product_type === 'virtual' && !$only_virtual ) ||
( $product_type === 'bundle' && $cart_content['has_virtual'] ) ||
( $product_type === 'physical' && !$physical_and_bundle ) ) {
return false;
}
return true;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment