phpwordpresswoocommercecartuser-roles

Hide "ship to a different address" in Woocommerce based on user roles and specific products in cart


I'm trying to hide the "ship to a different address" on WooCommerce checkout page for 2 user roles, if their cart contains any of the specified product ID's.

My code is working for a single product ID:

/** Shipping Address */
function filter_woocommerce_cart_needs_shipping_address( $needs_shipping ) {    
    // The targeted products & roles
    $targeted_variation_id = 414;
    $targeted_user_role = 'team';
    $targeted_user_role2 = 'team2';
    // Flag
    $found = false;

    // Loop through cart items
      foreach ( WC()->cart->get_cart() as $cart_item ) {
        if ( in_array( $targeted_variation_id, array( $cart_item['product_id'], $cart_item['variation_id'] ) ) ) {
            $found = true;
            break;
        }
    }
    
     // True & user Role is
        if ( $found && current_user_can( $targeted_user_role )) {
        $needs_shipping = false;
    }
     // True & only 1 item in cart
        if ( $found && current_user_can( $targeted_user_role2 )) {
        $needs_shipping = false;
    }   
       
    return $needs_shipping;
}
add_filter( 'woocommerce_cart_needs_shipping_address', 'filter_woocommerce_cart_needs_shipping_address', 10, 1 );

But then when I try to create an array of multiple IDs, I can't achieve the desired result, this is my attempt:

**Multiple Variants**
/** Shipping Address */
function filter_woocommerce_cart_needs_shipping_address( $needs_shipping ) {    
    // The targeted products & roles
    $targeted_variation_id = array(414,617);
    $targeted_user_role = 'team';
    $targeted_user_role2 = 'team2';
    // Flag
    $found = false;

    // Loop through cart items
      foreach ( WC()->cart->get_cart() as $cart_item ) {
        if ( in_array( $targeted_variation_id, array( $cart_item['product_id'], $cart_item['variation_id'] ) ) ) {
            $found = true;
            break;
        }
    }
    
     // True & user Role is
        if ( $found && current_user_can( $targeted_user_role )) {
        $needs_shipping = false;
    }
     // True & only 1 item in cart
        if ( $found && current_user_can( $targeted_user_role2 )) {
        $needs_shipping = false;
    }   
       
    return $needs_shipping;
}
add_filter( 'woocommerce_cart_needs_shipping_address', 'filter_woocommerce_cart_needs_shipping_address', 10, 1 );

Anyone able to help figure out how to get it to work with multiple ID's and not just one?


Solution

  • The mistakes in your code is in the following line:

    if ( in_array( $targeted_variation_id, array( $cart_item['product_id'], $cart_item['variation_id'] ) ) )
    

    $targeted_variation_id has been changed to an array, while the searched value must be a string when using in_array()

    It also seems more logical to check the user role first, before iterate all cart items

    So you get:

    function filter_woocommerce_cart_needs_shipping_address( $needs_shipping ) {
        // Retrieve the current user object
        $user = wp_get_current_user();
    
        // Add your user roles, several can be entered, separated by a comma
        $user_roles = array( 'team1', 'team2', 'administrator' );
    
        // Targeted product IDs, several can be entered, separated by a comma
        $targeted_product_ids = array( 30, 813, 414, 617 );
    
        // User role is found
        if ( array_intersect( $user_roles, (array) $user->roles ) ) {
            // Loop through cart contents
            foreach ( WC()->cart->get_cart_contents() as $cart_item ) {
                // Get product ID
                $product_id = $cart_item['variation_id'] > 0 ? $cart_item['variation_id'] : $cart_item['product_id'];
                
                // Checks if a value exists in an array
                if ( in_array( $product_id, $targeted_product_ids ) ) {
                    $needs_shipping = false;
                    break;
                }
            }
        }
    
        return $needs_shipping;
    }
    add_filter( 'woocommerce_cart_needs_shipping_address', 'filter_woocommerce_cart_needs_shipping_address', 10, 1 );