Force local pickupのWooCommerce2.6対応 その2
前回の後、管理画面でzone毎の配送オプション設定をしたそうで、そしたらまたうまく動かなくなったらしいので調査。
どうやらzone設定とpickup-onlyの要素はデフォルトだとzoneで設定した配送方法の方が勝る様ですが、先方はpickup-onlyの方を強くしたいとのこと。
更にzone = LOCALShippingOK の場合で合計金額が一定金額を超える場合は、pickup-onlyでも配送料無料で配送も有効にしたいとのこと。
pickup-onlyがonlyじゃ無くなってますなってツッコミはともかくとして、調べてみました。
今回はここを参考にしてfunctions.phpを変更する事で対応しました。
https://wordpress.org/support/topic/how-to-set-certain-items-for-local-pickup-only/
<?php /** * This function loops over cart items, and moves any item with shipping class 'special-class' into a new package. * The new package in this example only takes flat rate shipping. */ function split_special_shipping_class_items( $packages ) { $found_item = false; $special_class = 'pickup-only'; $new_package = current( $packages ); $new_package['contents'] = array(); $new_package['contents_cost'] = 0; $new_package['applied_coupons'] = array(); $new_package['ship_via'] = array( 'click-and-pick_shipping_method' ); $new_package['name'] = 'Shipping'; $has_free_shipping = false; foreach ( WC()->cart->get_cart() as $item_key => $item ) { // Is the product in the special class? if ( $item['data']->needs_shipping() && $special_class === $item['data']->get_shipping_class() ) { $found_item = true; $new_package['contents'][ $item_key ] = $item; $new_package['contents_cost'] += $item['line_total']; // Remove from original package $packages[0]['contents_cost'] = $packages[0]['contents_cost'] - $item['line_total']; unset( $packages[0]['contents'][ $item_key ] ); // If there are no items left in the previous package, remove it completely. if ( empty( $packages[0]['contents'] ) ) { unset( $packages[0] ); } } } $ship_methods = WC()->shipping->get_shipping_methods(); $zone_criteria['destination']['country'] = WC()->customer->get_country(); $zone_criteria['destination']['state'] = WC()->customer->get_state(); $zone_criteria['destination']['postcode'] = WC()->customer->get_postcode(); $shipping_zone = WC_Shipping_Zones::get_zone_matching_package($zone_criteria); if (array_key_exists('free_shipping', $ship_methods) && strpos($shipping_zone->get_zone_name(),'LOCALShippingOK') !== false ) { $has_free_shipping = true; } if ( $found_item ) { foreach ( WC()->cart->get_cart() as $item_key => $item ) { $new_package['contents'][ $item_key ] = $item; $new_package['contents_cost'] += $item['line_total']; // Remove from original package $packages[0]['contents_cost'] = $packages[0]['contents_cost'] - $item['line_total']; unset( $packages[0]['contents'][ $item_key ] ); // If there are no items left in the previous package, remove it completely. if ( empty( $packages[0]['contents'] ) ) { unset( $packages[0] ); } } if ( $has_free_shipping ) { $new_package['ship_via'] = array('free_shipping', 'click-and-pick_shipping_method' ); } $packages[] = $new_package; } return $packages; } // Hook into shipping packages filter add_filter( 'woocommerce_cart_shipping_packages', 'split_special_shipping_class_items' ); function rename_custom_package( $package_name, $i, $package ) { if ( ! empty( $package['name'] ) ) { $package_name = $package['name']; } return $package_name; } // output the new package name add_filter( 'woocommerce_shipping_package_name', 'rename_custom_package', 10, 3 );
カート内でpickup-onlyを探すループと、配送方法再設定のループがある感じですね。
WC_Shipping_Zones::get_zone_matching_package用にわざわざ$zone_criteriaをセットせずともWC()->shippingから取れそうでしたが、
このメソッド実行時に取ろうとするとプログラムがコケるので、わざわざセットしてあります。
全体的にあまり美しくなくてモヤモヤするのですが、すでにサービスインしていて急ぎだってんで、「動くが正義」でやってみました。