From d10987d8139b26ed682e222b8683c16503fc74c2 Mon Sep 17 00:00:00 2001 From: Manos Psychogyiopoulos Date: Thu, 25 Jan 2018 16:40:31 +0200 Subject: [PATCH] Match saved (canonical) rate IDs against chosen rates Generates canonical rate IDs (`method_id:instance_id`) from package rates and order shipping line items. Requires https://github.com/woocommerce/woocommerce/pull/18483 --- .../gateways/cod/class-wc-gateway-cod.php | 67 +++++++++++++++++-- 1 file changed, 61 insertions(+), 6 deletions(-) diff --git a/includes/gateways/cod/class-wc-gateway-cod.php b/includes/gateways/cod/class-wc-gateway-cod.php index b4cf078fd97..542a7e2220e 100644 --- a/includes/gateways/cod/class-wc-gateway-cod.php +++ b/includes/gateways/cod/class-wc-gateway-cod.php @@ -182,15 +182,16 @@ class WC_Gateway_COD extends WC_Payment_Gateway { // Only apply if all packages are being shipped via chosen method, or order is virtual. if ( ! empty( $this->enable_for_methods ) && $needs_shipping ) { - $chosen_shipping_methods = array(); - if ( is_object( $order ) ) { - $chosen_shipping_methods = array_unique( array_map( 'wc_get_string_before_colon', $order->get_shipping_methods() ) ); - } elseif ( $chosen_shipping_methods_session = WC()->session->get( 'chosen_shipping_methods' ) ) { - $chosen_shipping_methods = array_unique( array_map( 'wc_get_string_before_colon', $chosen_shipping_methods_session ) ); + $canonical_rate_ids = array(); + + if ( is_object( $order ) && ( $order_shipping_items = $order->get_shipping_methods() ) ) { + $canonical_rate_ids = $this->get_canonical_order_shipping_item_rate_ids( $order_shipping_items ); + } elseif ( $chosen_package_rate_ids = WC()->session->get( 'chosen_shipping_methods' ) ) { + $canonical_rate_ids = $this->get_canonical_package_rate_ids( $chosen_package_rate_ids ); } - if ( 0 < count( array_diff( $chosen_shipping_methods, $this->enable_for_methods ) ) ) { + if ( ! sizeof( $this->get_matching_rates( $canonical_rate_ids ) ) ) { return false; } } @@ -198,6 +199,60 @@ class WC_Gateway_COD extends WC_Payment_Gateway { return parent::is_available(); } + /** + * Converts the chosen rate IDs generated by Shipping Methods to a canonical 'method_id:instance_id' format. + * + * @since 3.4.0 + * + * @param array $order_shipping_items Array of WC_Order_Item_Shipping objects. + * @return array $canonical_rate_ids Rate IDs in a canonical format. + */ + private function get_canonical_order_shipping_item_rate_ids( $order_shipping_items ) { + + $canonical_rate_ids = array(); + + foreach ( $order_shipping_items as $order_shipping_item ) { + $canonical_rate_ids[] = $order_shipping_item->get_method_id() . ':' . $order_shipping_item->get_instance_id(); + } + + return $canonical_rate_ids; + } + + /** + * Converts the chosen rate IDs generated by Shipping Methods to a canonical 'method_id:instance_id' format. + * + * @since 3.4.0 + * + * @param array $rate_ids Rate IDs as generated by shipping methods. Can be anything if a shipping method doesn't honor WC conventions. + * @return array $canonical_rate_ids Rate IDs in a canonical format. + */ + private function get_canonical_package_rate_ids( $chosen_package_rate_ids ) { + + $shipping_packages = WC()->shipping->get_packages(); + $canonical_rate_ids = array(); + + foreach ( $chosen_package_rate_ids as $package_key => $chosen_package_rate_id ) { + if ( ! empty( $shipping_packages[ $package_key ][ 'rates' ][ $chosen_package_rate_id ] ) ) { + $chosen_rate = $shipping_packages[ $package_key ][ 'rates' ][ $chosen_package_rate_id ]; + $canonical_rate_ids[] = $chosen_rate->get_method_id() . ':' . $chosen_rate->get_instance_id(); + } + } + + return $canonical_rate_ids; + } + + /** + * Indicates whether a rate exists in an array of canonically-formatted rate IDs that activates this gateway. + * + * @since 3.4.0 + * + * @param array $rate_ids + * @return boolean + */ + private function get_matching_rates( $rate_ids ) { + // First, match entries in 'method_id:instance_id' format. Then, match entries in 'method_id' format by stripping off the instance ID from the candidates. + return array_unique( array_merge( array_intersect( $this->enable_for_methods, $rate_ids ), array_intersect( $this->enable_for_methods, array_unique( array_map( 'wc_get_string_before_colon', $rate_ids ) ) ) ) ); + } /** * Process the payment and return the result.