Search code examples
phpwordpresswoocommercehook-woocommercecart

Allow only one downloadable product in WooCommerce cart


Here is the code that prevent to have more than one downloadable product in the cart:

add_filter( 'woocommerce_add_to_cart_validation', 'only_one_product_type_allowed', 10, 3 );
function only_one_product_type_allowed( $passed, $product_id, $quantity ) {

  $product = wc_get_product( $product_id );
  $product_type = $product->get_type();
  $product_downloadable = $product->is_downloadable();

  foreach ( WC()->cart->get_cart() as $cart_item ) {

    if ( $product_type == $cart_item['data']->get_type() && $product_downloadable == $cart_item['data']->is_downloadable() && ! $product->is_virtual() ) {

      wc_add_notice( __( "NOTICE ON CART PAGE.", "woocommerce" ), 'error' );

      return false;
    }
  }

  return $passed;
  
}

Now , it is not allowing more than one downloadable products in single cart which is OK. But it is not allowing more than one regular items in cart too. it is throwing same notice. can anyone help with fix.


Solution

  • To allow only one downloadable product in cart, allowing other products kind, try to use the following instead:

    add_filter( 'woocommerce_add_to_cart_validation', 'only_one_downloadable_product_allowed', 10, 4 );
    function only_one_downloadable_product_allowed( $passed, $product_id, $quantity, $variation_id = null ) {
        // Get the current product object
        $product  = wc_get_product( $variation_id > 0 ? $variation_id : $product_id );
    
        // Initializing downloadable product count
        $count_dl = $product->is_downloadable() ? 1 : 0; 
    
        // Loop through cart items
        foreach ( WC()->cart->get_cart() as $item ) {
            // Check for downloadable products in cart
            if ( $item['data']->is_downloadable() ) {
                $count_dl++;
            }
        }
    
        if ( $count_dl > 1 ) {
            wc_add_notice( __( "Only one downloadable product is allowed at the time.", "woocommerce" ), 'error' );
            $passed = false;
        }
        return $passed;
    }
    

    Code goes in functions.php file of your child theme (or in a plugin). It should work.