Describe the bug
When there is only 1 Shipping Method available in the initial package, WooCommerce core doesn't display any radio buttons. Instead, it adds a hidden input element: https://github.com/woocommerce/woocommerce/blob/6ab6788c7547bf76f8e5a6e6948dd4fd93e5d2f3/plugins/woocommerce/templates/cart/cart-shipping.php#L38 and then runs the woocommerce_after_shipping_rate
action. The hidden input element is necessary for the chosen_shipping_methods
session key to be set correctly.
In WooCommerce Subscriptions, there are two cases in which there could be only 1 Shipping Method for the recurring package:
- when there is only 1 Shipping Method available for the matched zone (this is similar to the check WooCommerce core makes in the initial package) and;
- when the recurring package rates match the initial package rates (in other words, when the initial and recurring package have the same contents).
In both cases:
- the Shipping Methods radio buttons must be hidden,
- the hidden input element should be added and;
- the
woocommerce_after_shipping_rate
action should run.
This happens, though, only when there is 1 Shipping Method available for the matched zone and not when the recurring package rates match the initial package rates -- even though in the latter case only 1 Shipping Method is displayed as well.
The reason why this happens is that in this validation: https://github.com/Automattic/woocommerce-subscriptions-core/blob/trunk/includes/wcs-cart-functions.php#L108 the code only checks how many Shipping Methods are available for the matched zone and not if the recurring package rates match the initial package rates.
Therefore, when the recurring package rates match the initial package rates and one Shipping Method is displayed:
- the hidden input element is not added (and so, this Shipping Method is not set as the chosen shipping method for the recurring package in the session) and;
- the
woocommerce_after_shipping_rate
action does not run (and therefore, any code that hooks into this action doesn't run either).
To resolve this, it is necessary to make sure that this code: https://github.com/Automattic/woocommerce-subscriptions-core/blob/trunk/includes/wcs-cart-functions.php#L109-L110 always runs when this validation: https://github.com/Automattic/woocommerce-subscriptions-core/blob/trunk/includes/wcs-cart-functions.php#L90 passes.
To Reproduce
- Make sure that you have at least 2 Shipping Methods available in your store.
- Add a Simple Subscription Product to the cart.
- Ensure that the Shipping Method radio buttons are hidden in the recurring package and that the Shipping Method selected in the initial package applies to the recurring package as well.
- Install a snippet that uses the
woocommerce_after_shipping_rate
actiond (a) or a snippet that prints the chosen shipping methods per package (b):
(a)
add_action( 'woocommerce_after_shipping_rate', 'print_random_message' );
function print_random_message() {
echo "Hello World!";
}
(b)
add_action( 'woocommerce_after_checkout_form', 'print_chosen_shipping_methods' );
function print_chosen_shipping_methods() {
$chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
error_log( print_r( $chosen_methods, 1 ) );
}
- If you used (a), does the custom message show up for the Shipping Method in the recurring package? If you used (b), is the chosen method for the recurring package passed to the session?
Expected behavior
The expected behavior is that the woocommerce_after_shipping_rate
action should run after each Shipping Method regardless of how many Shipping Methods are available in the package or whether the package is a recurring one. Moreover, the hidden input element should show up when there is only 1 Shipping Method in the recurring package in order for this method to be set as the chosen one in the session.
Actual behavior
When the recurring package rates match the initial package rates, only one Shipping Method is displayed in the recurring package and the woocommerce_after_shipping_rate
action does not run. Moreover, this Shipping Method is not set as the chosen one in the session.
Product impact
This issue affects all code that uses the woocommerce_after_shipping_rate
action and expects that this action runs after all Shipping Methods. For example, Conditional Shipping and Payments conditionally adds notices next to each restricted Shipping Method -- these notices cannot be shown in Shipping Methods in the recurring cart since this action is missing.
Moreover, it affects all code that works based on the chosen shipping methods (WC()->session->get( 'chosen_shipping_methods
) as the chosen shipping method for the recurring package is not set.
PR incoming.