1
votes

I've had a user from here help me and assist in getting my code fixed correctly to function correctly and while the above does work for everything with custom field of 90 days to hide all shipping and display only "Free Shipping" if available. However, my client also set free shipping to be shown only on certain amount.

I'm wondering if I can add the following;

Here's the original code I am using:

add_filter( 'woocommerce_package_rates', 'show_only_free_shipping_for_autodelivery', 100, 2 );
function show_only_free_shipping_for_autodelivery ( $rates, $package ) {
    // Loop through cart items
    foreach( $package['contents'] as $cart_item ){
        if( $cart_item['data']->get_meta('auto_delivery_default') == '90 Days' ) {
            $found = true;
            break; // Stop the loop
        }
    }

    if( ! ( isset($found) && $found ) )
        return $rates; // Exit

    $free = array();
    foreach ( $rates as $rate_id => $rate ) {
        if ( 'free_shipping' === $rate->method_id ) {
            $free[ $rate_id ] = $rate;
            break;
        }
    }
    return ! empty( $free ) ? $free : $rates;
}

I'm trying to force Free Shipping overwriting the minimum amount for free shipping, while still hiding all shipping options based on the meta value for the meta key 'auto_delivery_default'.


Edit:

Finally I have discovered that it is custom cart item data:
The targeted key is delivery_options for a value of 3 months.

1

1 Answers

2
votes

Update 2:

The following code will force "Free shipping" method when a cart item with a custom data delivery_options has a value of 3 months:

// Conditionally hide others shipping methods when free shipping is available
add_filter( 'woocommerce_package_rates', 'show_only_free_shipping_for_autodelivery', 100, 2 );
function show_only_free_shipping_for_autodelivery ( $rates, $package ) {
    // Loop through cart items
    foreach( $package['contents'] as $cart_item ){
        if( isset($cart_item['delivery_options']) && $cart_item['delivery_options'] == '3 months' ) {
            $found = true;
            break; // Stop the loop
        }
    }

    if( ! ( isset($found) && $found ) )
        return $rates; // Exit

    $free = array();
    foreach ( $rates as $rate_id => $rate ) {
        if ( 'free_shipping' === $rate->method_id ) {
            $free[ $rate_id ] = $rate;
            break;
        }
    }
    return ! empty( $free ) ? $free : $rates;
}


// Force free shipping for a specific custom field value
add_filter( 'woocommerce_shipping_free_shipping_is_available', 'filter_free_shipping_is_available', 20, 3 );
function filter_free_shipping_is_available ( $is_available, $package, $free_shipping ) {
    // Loop through cart items
    foreach( $package['contents'] as $cart_item ){
        if( isset($cart_item['delivery_options']) && $cart_item['delivery_options'] == '3 months' ) {
            $is_available = true;
            break; // Stop the loop
        }
    }

    return $is_available;
}

Code goes in function.php file of your active child theme (or active theme). Tested and works.

Refreshing shipping caches temporarily is needed, enabling the "Debug mode" in Woocommerce global shipping settings under "Shipping options" tab.
Once tested and working, just disable it and everything will still work.