You can use the woocommerce_available_shipping_methods
filter to do that. NB: if you have Role Based Shipping plugin you might find that it removes the Free Shipping option under some circumstances; this code puts it back if shopper has a coupon for Free Shipping.
/**
* if Free Shipping method is available, reduce to just Free Shipping
* @param array $available_methods
* @return array
*/
add_filter('woocommerce_available_shipping_methods', function($available_methods) {
global $woocommerce;
// check for coupon with Free Shipping
if (wpse_114581_has_coupon_free_shipping()) {
// ensure that Free Shipping is in the list of available methods (again -- Role Based Methods may strip Free Shipping for Guests)
if (!isset($available_methods['free_shipping'])) {
$available_methods['free_shipping'] = new WC_Shipping_Rate('free_shipping', 'Free Shipping', 0, array(), '');
}
}
// if both Free Shipping and another method, reduce to just free shipping
if (isset($available_methods['free_shipping']) && count($available_methods) > 1) {
$available_methods = array('free_shipping' => $available_methods['free_shipping']);
// change title on Free Shipping method
$available_methods['free_shipping']->method_title="flat rate shipping (free!)";
}
return $available_methods;
});
/**
* check for coupon with free shipping
* @return bool
*/
function wpse_114581_has_coupon_free_shipping() {
global $woocommerce;
foreach ($woocommerce->cart->applied_coupons as $code) {
$coupon = new WC_Coupon($code);
if ($coupon->is_valid() === true) {
if ($coupon->enable_free_shipping()) {
return true;
}
}
}
return false;
}