From 1baf2b0a01591e9720e4c8763b447dae5fbea171 Mon Sep 17 00:00:00 2001 From: vendidero Date: Fri, 25 Oct 2024 13:29:33 +0200 Subject: [PATCH] By default, do not override shipping package total data within global cart data as this tweak (for improved bundle compatibility) does not work with plugins (e.g. subscriptions) that do add additional carts with separate totals. --- src/ShippingMethod/MethodHelper.php | 46 ++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/src/ShippingMethod/MethodHelper.php b/src/ShippingMethod/MethodHelper.php index 2b591a41..5fd6bc14 100644 --- a/src/ShippingMethod/MethodHelper.php +++ b/src/ShippingMethod/MethodHelper.php @@ -2,6 +2,7 @@ namespace Vendidero\Germanized\Shipments\ShippingMethod; +use Vendidero\Germanized\Shipments\Compatibility\Bundles; use Vendidero\Germanized\Shipments\Package; use Vendidero\Germanized\Shipments\Packing\CartItem; use Vendidero\Germanized\Shipments\Packing\ItemList; @@ -30,9 +31,26 @@ public static function init() { add_filter( 'woocommerce_generate_shipping_provider_method_tabs_close_html', array( __CLASS__, 'render_method_tab_content_close' ), 10, 4 ); add_filter( 'woocommerce_generate_shipping_provider_method_configuration_sets_html', array( __CLASS__, 'render_method_configuration_sets' ), 10 ); - add_filter( 'woocommerce_cart_shipping_packages', array( __CLASS__, 'register_cart_items_to_pack' ) ); add_filter( 'woocommerce_shipping_methods', array( __CLASS__, 'register_shipping_methods' ) ); add_filter( 'woocommerce_hidden_order_itemmeta', array( __CLASS__, 'set_shipping_order_meta_hidden' ) ); + + add_filter( 'woocommerce_cart_shipping_packages', array( __CLASS__, 'register_cart_items_to_pack' ) ); + + add_action( + 'woocommerce_before_calculate_totals1', + function ( $cart ) { + remove_filter( 'woocommerce_cart_shipping_packages', array( __CLASS__, 'register_cart_items_to_pack' ) ); + + add_filter( + 'woocommerce_cart_shipping_packages', + function ( $package ) use ( $cart ) { + $package = self::register_cart_items_to_pack( $package, $cart ); + + return $package; + } + ); + } + ); } public static function set_shipping_order_meta_hidden( $meta ) { @@ -67,6 +85,8 @@ public static function register_cart_items_to_pack( $cart_contents ) { return $cart_contents; } + $cart = WC()->cart; + foreach ( $cart_contents as $index => $content ) { $package_data = array( 'total' => 0.0, @@ -129,20 +149,24 @@ public static function register_cart_items_to_pack( $cart_contents ) { do_action( 'woocommerce_gzd_shipments_after_prepare_cart_contents' ); /** - * In case prices have already been calculated, use the official - * Woo API for better compatibility with extensions, e.g. Bundles. + * In case prices have already been calculated, maybe prefer the official + * Woo API for improved compatibility with extensions, e.g. unassembled, individually priced bundled items. + * + * This may cause problems with plugins that add additional carts and calculate shipping (e.g. Subscriptions) based on these separate carts + * as Woo does not pass the current $cart object to the filter used here. Within the shipping package data there is unfortunately + * no item total amount (incl taxes) available. */ - if ( 0 !== WC()->cart->get_subtotal() ) { - $total = (float) WC()->cart->get_cart_contents_total(); - $subtotal = (float) WC()->cart->get_subtotal(); + if ( 0 !== $cart_contents[ $index ]['cart_subtotal'] && apply_filters( 'woocommerce_gzd_shipments_prefer_cart_totals_over_cart_item_totals', false, $cart_contents ) ) { + $total = (float) $cart->get_cart_contents_total(); - if ( wc()->cart->display_prices_including_tax() ) { - $total += (float) WC()->cart->get_cart_contents_tax(); - $subtotal += (float) WC()->cart->get_subtotal_tax(); + if ( $cart->display_prices_including_tax() ) { + $total += (float) $cart->get_cart_contents_tax(); + } else { + $total = (float) $cart_contents[ $index ]['contents_cost']; // this is excl tax } - $package_data['total'] = NumberUtil::round_to_precision( $total ); - $package_data['subtotal'] = NumberUtil::round_to_precision( $subtotal ); + $package_data['total'] = NumberUtil::round_to_precision( $total ); // item total after discounts + $package_data['subtotal'] = NumberUtil::round_to_precision( (float) $cart_contents[ $index ]['cart_subtotal'] ); // item total before discounts } $cart_contents[ $index ]['package_data'] = $package_data;