Last active
August 22, 2024 16:36
-
-
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)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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