Created
February 15, 2018 17:52
-
-
Save jchrislemmer/31667fb7852d80d87f241cc39a9c0ba8 to your computer and use it in GitHub Desktop.
WooCommerce Distance Rate Shipping - Fix issue of exact address not found
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Shipping method with distance rate. | |
* | |
* @package WC_Distance_Rate | |
*/ | |
if ( ! defined( 'ABSPATH' ) ) { | |
exit; // Exit if accessed directly. | |
} | |
/** | |
* WC_Shipping_Distance_Rate class. | |
* | |
* @extends WC_Shipping_Method | |
*/ | |
if ( ! class_exists( 'WC_Shipping_Distance_Rate' ) ) { | |
/** | |
* Shipping method with distance rate. | |
*/ | |
class WC_Shipping_Distance_Rate extends WC_Shipping_Method { | |
/** | |
* Google Distance Matric API object. | |
* | |
* @var Object | |
*/ | |
protected $api; | |
/** | |
* Notice to show users. | |
* | |
* @var string | |
*/ | |
public $notice = ''; | |
/** | |
* Constructor. | |
* | |
* @param int $instance_id Instance ID. | |
* | |
* @return void | |
*/ | |
public function __construct( $instance_id = 0 ) { | |
$this->id = 'distance_rate'; | |
$this->instance_id = absint( $instance_id ); | |
$this->method_title = __( 'Distance Rate', 'woocommerce-distance-rate-shipping' ); | |
$this->supports = array( | |
'shipping-zones', | |
'instance-settings', | |
'settings', | |
); | |
add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) ); | |
$this->init(); | |
} | |
/** | |
* Check if this shipping method is available or not. | |
* | |
* @param array $package Package to ship. | |
* @return bool | |
*/ | |
public function is_available( $package ) { | |
if ( empty( $package['destination']['country'] ) ) { | |
return false; | |
} | |
return apply_filters( 'woocommerce_shipping_' . $this->id . '_is_available', true, $package ); | |
} | |
/** | |
* Initialize settings | |
* | |
* @version 1.0.5 | |
* @since 1.0.5 | |
* @return bool | |
*/ | |
private function set_settings() { | |
// Define user set variables. | |
$this->title = $this->get_option( 'title', $this->method_title ); | |
$this->origin = $this->get_option( 'origin', '' ); | |
$this->debug = ( 'yes' === $this->get_option( 'debug', 'no' ) ) ? true : false; | |
$this->tax_status = $this->get_option( 'tax_status', 'taxable' ); | |
$this->api_key = $this->get_option( 'api_key', '' ); | |
$this->mode = $this->get_option( 'mode', 'driving' ); | |
$this->avoid = $this->get_option( 'avoid', 'none' ); | |
$this->unit = $this->get_option( 'unit', 'metric' ); | |
$this->show_distance = ( 'yes' === $this->get_option( 'show_distance' ) ); | |
$this->show_duration = ( 'yes' === $this->get_option( 'show_duration' ) ); | |
$this->address_1 = $this->get_option( 'address_1', '' ); | |
$this->address_2 = $this->get_option( 'address_2', '' ); | |
$this->city = $this->get_option( 'city', '' ); | |
$this->postal_code = $this->get_option( 'postal_code', '' ); | |
$this->state_country = $this->get_option( 'state_country', '' ); | |
$this->country = $this->get_option( 'country', '' ); | |
$this->rules = $this->get_option( 'rules', array() ); | |
return true; | |
} | |
/** | |
* Init function. | |
* | |
* @access private | |
* @return void | |
*/ | |
private function init() { | |
// Load the settings. | |
$this->init_form_fields(); | |
$this->set_settings(); | |
add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) ); | |
add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'clear_transients' ) ); | |
} | |
/** | |
* Process settings on save | |
* | |
* @access public | |
* @return void | |
*/ | |
public function process_admin_options() { | |
parent::process_admin_options(); | |
$this->set_settings(); | |
} | |
/** | |
* Define form fields. | |
*/ | |
public function init_form_fields() { | |
$this->instance_form_fields = array( | |
'title' => array( | |
'title' => __( 'Method Title', 'woocommerce-distance-rate-shipping' ), | |
'type' => 'text', | |
'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-distance-rate-shipping' ), | |
'default' => __( 'Distance Rate', 'woocommerce-distance-rate-shipping' ), | |
), | |
'tax_status' => array( | |
'title' => __( 'Tax Status', 'woocommerce-distance-rate-shipping' ), | |
'type' => 'select', | |
'default' => 'taxable', | |
'options' => array( | |
'taxable' => __( 'Taxable', 'woocommerce-distance-rate-shipping' ), | |
'none' => _x( 'None', 'Tax status', 'woocommerce-distance-rate-shipping' ), | |
), | |
), | |
'mode' => array( | |
'title' => __( 'Transportation Mode', 'woocommerce-distance-rate-shipping' ), | |
'type' => 'select', | |
'default' => 'driving', | |
'options' => array( | |
'driving' => __( 'Driving', 'woocommerce-distance-rate-shipping' ), | |
'walking' => __( 'Walking', 'woocommerce-distance-rate-shipping' ), | |
'bicycling' => __( 'Bicycling', 'woocommerce-distance-rate-shipping' ), | |
), | |
), | |
'avoid' => array( | |
'title' => __( 'Avoid', 'woocommerce-distance-rate-shipping' ), | |
'type' => 'select', | |
'default' => 'none', | |
'options' => array( | |
'none' => __( 'None', 'woocommerce-distance-rate-shipping' ), | |
'tolls' => __( 'Tolls', 'woocommerce-distance-rate-shipping' ), | |
'highways' => __( 'Highways', 'woocommerce-distance-rate-shipping' ), | |
'ferries' => __( 'Ferries', 'woocommerce-distance-rate-shipping' ), | |
), | |
), | |
'unit' => array( | |
'title' => __( 'Distance Unit', 'woocommerce-distance-rate-shipping' ), | |
'type' => 'select', | |
'default' => 'metric', | |
'options' => array( | |
'metric' => __( 'Metric', 'woocommerce-distance-rate-shipping' ), | |
'imperial' => __( 'Imperial', 'woocommerce-distance-rate-shipping' ), | |
), | |
), | |
'show_distance' => array( | |
'title' => __( 'Show distance', 'woocommerce-distance-rate-shipping' ), | |
'type' => 'checkbox', | |
'label' => __( 'Show the distance next to the shipping cost for the customer.', 'woocommerce-distance-rate-shipping' ), | |
'default' => 'yes', | |
), | |
'show_duration' => array( | |
'title' => __( 'Show duration', 'woocommerce-distance-rate-shipping' ), | |
'type' => 'checkbox', | |
'label' => __( 'Show the duration next to the shipping cost for the customer.', 'woocommerce-distance-rate-shipping' ), | |
'default' => 'no', | |
), | |
'distance_rate_address' => array( | |
'title' => __( 'Shipping Address', 'woocommerce-distance-rate-shipping' ), | |
'type' => 'title', | |
'description' => __( 'Please enter the address that you are shipping from below to work out the distance of the customer from the shipping location.', 'woocommerce-distance-rate-shipping' ), | |
), | |
'address_1' => array( | |
'title' => __( 'Address 1', 'woocommerce-distance-rate-shipping' ), | |
'type' => 'text', | |
'description' => __( 'First address line of where you are shipping from.', 'woocommerce-distance-rate-shipping' ), | |
), | |
'address_2' => array( | |
'title' => __( 'Address 2', 'woocommerce-distance-rate-shipping' ), | |
'type' => 'text', | |
'description' => __( 'Second address line of where you are shipping from.', 'woocommerce-distance-rate-shipping' ), | |
), | |
'city' => array( | |
'title' => __( 'City', 'woocommerce-distance-rate-shipping' ), | |
'type' => 'text', | |
'description' => __( 'City of where you are shipping from.', 'woocommerce-distance-rate-shipping' ), | |
), | |
'postal_code' => array( | |
'title' => __( 'Zip/Postal Code', 'woocommerce-distance-rate-shipping' ), | |
'type' => 'text', | |
'description' => __( 'Zip or Postal Code of where you are shipping from.', 'woocommerce-distance-rate-shipping' ), | |
), | |
'state_province' => array( | |
'title' => __( 'State/Province', 'woocommerce-distance-rate-shipping' ), | |
'type' => 'text', | |
'description' => __( 'State/Province of where you are shipping from.', 'woocommerce-distance-rate-shipping' ), | |
), | |
'country' => array( | |
'title' => __( 'Country', 'woocommerce-distance-rate-shipping' ), | |
'type' => 'text', | |
'description' => __( 'Country of where you are shipping from.', 'woocommerce-distance-rate-shipping' ), | |
), | |
'distance_rates_map' => array( | |
'type' => 'distance_rates_map', | |
), | |
'rules' => array( | |
'type' => 'distance_rate_rule_table', | |
), | |
); | |
$this->form_fields = array( | |
'api_key' => array( | |
'title' => __( 'API Key', 'woocommerce-distance-rate-shipping' ), | |
'type' => 'text', | |
'description' => __( 'Your <a href="http://docs.woothemes.com/document/woocommerce-distance-rate-shipping/#section-3">Google API Key</a>', 'woocommerce-distance-rate-shipping' ), | |
), | |
'debug' => array( | |
'title' => __( 'Debug Mode', 'woocommerce-distance-rate-shipping' ), | |
'type' => 'checkbox', | |
'label' => __( 'Enable/Disable Debug Mode, display API calls on frontend', 'woocommerce-distance-rate-shipping' ), | |
'default' => 'no', | |
), | |
); | |
} | |
/** | |
* Ouput a google map of the shipping location if set. | |
* | |
* @return string HTML of map. | |
*/ | |
public function generate_distance_rates_map_html() { | |
ob_start(); | |
$address_string = $this->get_shipping_address_string(); | |
if ( ! empty( $address_string ) ) { | |
?> | |
<tr valign="top"> | |
<td colspan="2"> | |
<iframe width="600" height="450" frameborder="0" style="border:0" src="https://www.google.com/maps/embed/v1/place?q=<?php echo urlencode( $this->get_shipping_address_string() ); ?>&key=<?php echo $this->api_key; ?>"></iframe> | |
</td> | |
</tr> | |
<?php | |
} | |
return ob_get_clean(); | |
} | |
/** | |
* Generate the rules table html. | |
* | |
* @return string HTML of rules table. | |
*/ | |
public function generate_distance_rate_rule_table_html() { | |
ob_start(); | |
?> | |
<tr valign="top"> | |
<th scope="row" class="titledesc"><?php _e( 'Distance Rate Rules', 'woocommerce-distance-rate-shipping' ); ?>:</th> | |
<td class="forminp" id="<?php echo $this->id; ?>_rules"> | |
<table class="shippingrows widefat" cellspacing="0"> | |
<thead> | |
<tr> | |
<th class="check-column"><input type="checkbox"></th> | |
<th><?php _e( 'Condition', 'woocommerce-distance-rate-shipping' ); ?> <a class="tips" data-tip="<?php _e( 'On what condition must the rule be applied.', 'woocommerce-distance-rate-shipping' ); ?>">[?]</a></th> | |
<th><?php _e( 'Min', 'woocommerce-distance-rate-shipping' ); ?> <a class="tips" data-tip="<?php _e( 'Minimum condition value, leave blank for no limit. Travel time based in minutes.', 'woocommerce-distance-rate-shipping' ); ?>">[?]</a></th> | |
<th><?php _e( 'Max', 'woocommerce-distance-rate-shipping' ); ?> <a class="tips" data-tip="<?php _e( 'Maximum condition value, leave blank for no limit. Travel time based in minutes.', 'woocommerce-distance-rate-shipping' ); ?>">[?]</a></th> | |
<th><?php _e( 'Fixed Cost', 'woocommerce-distance-rate-shipping' ); ?> <a class="tips" data-tip="<?php _e( 'Fixed cost for rule, exluding tax.', 'woocommerce-distance-rate-shipping' ); ?>">[?]</a></th> | |
<th style="padding-right: 20px;"><?php _e( 'Cost Per Distance / Minute', 'woocommerce-distance-rate-shipping' ); ?> <a class="tips" data-tip="<?php _e( 'Cost per distance unit, or cost per minute for total travel time, excluding tax.', 'woocommerce-distance-rate-shipping' ); ?>">[?]</a></th> | |
<th><?php _e( 'Handling Fee', 'woocommerce-distance-rate-shipping' ); ?> <a class="tips" data-tip="<?php _e( 'Fee excluding tax. Enter an amount, e.g. 2.50, or a percentage, e.g. 5%.', 'woocommerce-distance-rate-shipping' ); ?>">[?]</a></th> | |
<th><?php _e( 'Break', 'woocommerce-distance-rate-shipping' ); ?> <a class="tips" data-tip="<?php _e( 'Check to not continue processing rules below the selected rule.', 'woocommerce-distance-rate-shipping' ); ?>">[?]</a></th> | |
</tr> | |
</thead> | |
<tfoot> | |
<tr> | |
<th colspan="8"><a href="#" class="add button"><?php _e( 'Add Distance Rule', 'woocommerce-distance-rate-shipping' ); ?></a> <a href="#" class="remove button"><?php _e( 'Delete selected rule', 'woocommerce-distance-rate-shipping' ); ?></a></th> | |
</tr> | |
</tfoot> | |
<tbody class="distance_rates"> | |
<?php | |
$i = -1; | |
if ( $this->rules ) { | |
foreach ( $this->rules as $rule ) { | |
$i++; | |
$checked = ''; | |
if ( 'yes' == $rule['break'] ) { | |
$checked = 'checked="checked"'; | |
} | |
echo '<tr class="distance_rule"> | |
<th class="check-column"><input type="checkbox" name="select" /></th> | |
<td><select name="' . $this->id . '_condition[' . $i . ']"> | |
<option value="distance" ' . selected( $rule['condition'], 'distance', false ) . '>' . __( 'Distance', 'woocommerce-distance-rate-shipping' ) . '</option> | |
<option value="time" ' . selected( $rule['condition'], 'time', false ) . '>' . __( 'Total Travel Time', 'woocommerce-distance-rate-shipping' ) . '</option> | |
<option value="weight" ' . selected( $rule['condition'], 'weight', false ) . '>' . __( 'Weight', 'woocommerce-distance-rate-shipping' ) . '</option> | |
<option value="total" ' . selected( $rule['condition'], 'total', false ) . '>' . __( 'Order Total', 'woocommerce-distance-rate-shipping' ) . '</option> | |
<option value="quantity" ' . selected( $rule['condition'], 'quantity', false ) . '>' . __( 'Quantity', 'woocommerce-distance-rate-shipping' ) . '</option> | |
</select></td> | |
<td><input type="text" name="' . $this->id . '_min[' . $i . ']' . '" size="4" class="wc_input_price" value="' . $rule['min'] . '" /></td> | |
<td><input type="text" name="' . $this->id . '_max[' . $i . ']' . '" size="4" class="wc_input_price" value="' . $rule['max'] . '"/></td> | |
<td><input type="text" name="' . $this->id . '_cost[' . $i . ']' . '" value="' . $rule['cost'] . '" placeholder="' . wc_format_localized_price( 0 ) . '" size="4" class="wc_input_price" /></td> | |
<td><input type="text" name="' . $this->id . '_cost_unit[' . $i . ']' . '" value="' . $rule['cost_unit'] . '" placeholder="' . wc_format_localized_price( 0 ) . '" size="4" class="wc_input_price" /></td> | |
<td><input type="text" name="' . $this->id . '_fee[' . $i . ']' . '" value="' . $rule['fee'] . '" placeholder="' . wc_format_localized_price( 0 ) . '" size="4" class="wc_input_price" /></td> | |
<td><input type="checkbox" name="' . $this->id . '_break[' . $i . ']' . '" ' . $checked . ' /></td> | |
</tr>'; | |
} | |
} | |
?> | |
</tbody> | |
</table> | |
<script type="text/javascript"> | |
jQuery(function() { | |
jQuery('#<?php echo $this->id; ?>_rules').on( 'click', 'a.add', function(){ | |
var size = jQuery('#<?php echo $this->id; ?>_rules tbody .distance_rule').size(); | |
jQuery('<tr class="distance_rule">\ | |
<th class="check-column"><input type="checkbox" name="select" /></th>\ | |
<td><select name="<?php echo $this->id; ?>_condition[' + size + ']">\ | |
<option value="distance"><?php esc_html_e( 'Distance', 'woocommerce-distance-rate-shipping' ); ?></option>\ | |
<option value="time"><?php esc_html_e( 'Total Travel Time', 'woocommerce-distance-rate-shipping' ); ?></option>\ | |
<option value="weight"><?php esc_html_e( 'Weight', 'woocommerce-distance-rate-shipping' ); ?></option>\ | |
<option value="total"><?php esc_html_e( 'Order Total', 'woocommerce-distance-rate-shipping' ); ?></option>\ | |
<option value="quantity"><?php esc_html_e( 'Quantity', 'woocommerce-distance-rate-shipping' ); ?></option>\ | |
</select></td>\ | |
<td><input type="text" name="<?php echo $this->id; ?>_min[' + size + ']" size="4" class="wc_input_price" /></td>\ | |
<td><input type="text" name="<?php echo $this->id; ?>_max[' + size + ']" size="4" class="wc_input_price" /></td>\ | |
<td><input type="text" name="<?php echo $this->id; ?>_cost[' + size + ']" placeholder="<?php echo wc_format_localized_price( 0 ); ?>" size="4" class="wc_input_price" /></td>\ | |
<td><input type="text" name="<?php echo $this->id; ?>_cost_unit[' + size + ']" placeholder="<?php echo wc_format_localized_price( 0 ); ?>" size="4" class="wc_input_price" /></td>\ | |
<td><input type="text" name="<?php echo $this->id; ?>_fee[' + size + ']" placeholder="<?php echo wc_format_localized_price( 0 ); ?>" size="4" class="wc_input_price" /></td>\ | |
<td><input type="checkbox" name="<?php echo $this->id; ?>_break[' + size + ']" /></td>\ | |
</tr>').appendTo('#<?php echo $this->id; ?>_rules table tbody'); | |
return false; | |
}); | |
// Remove row | |
jQuery('#<?php echo $this->id; ?>_rules').on( 'click', 'a.remove', function(){ | |
var answer = confirm("<?php _e( 'Delete the selected rule?', 'woocommerce-distance-rate-shipping' ); ?>"); | |
if (answer) { | |
jQuery('#<?php echo $this->id; ?>_rules table tbody tr th.check-column input:checked').each(function(i, el){ | |
jQuery(el).closest('tr').remove(); | |
}); | |
} | |
return false; | |
}); | |
}); | |
</script> | |
</td> | |
</tr> | |
<?php | |
return ob_get_clean(); | |
} | |
/** | |
* Save the rules. | |
* | |
* @param string $key Key. | |
* | |
* @return array | |
*/ | |
public function validate_distance_rate_rule_table_field( $key ) { | |
$rule_condition = array(); | |
$rule_min = array(); | |
$rule_max = array(); | |
$rule_cost = array(); | |
$rule_cost_unit = array(); | |
$rule_fee = array(); | |
$rule_break = array(); | |
$rules = array(); | |
if ( isset( $_POST[ $this->id . '_condition' ] ) ) { | |
$rule_condition = array_map( 'stripslashes', $_POST[ $this->id . '_condition' ] ); | |
} | |
if ( isset( $_POST[ $this->id . '_min' ] ) ) { | |
$rule_min = array_map( 'stripslashes', $_POST[ $this->id . '_min' ] ); | |
} | |
if ( isset( $_POST[ $this->id . '_max' ] ) ) { | |
$rule_max = array_map( 'stripslashes', $_POST[ $this->id . '_max' ] ); | |
} | |
if ( isset( $_POST[ $this->id . '_cost' ] ) ) { | |
$rule_cost = array_map( 'stripslashes', $_POST[ $this->id . '_cost' ] ); | |
} | |
if ( isset( $_POST[ $this->id . '_cost_unit' ] ) ) { | |
$rule_cost_unit = array_map( 'stripslashes', $_POST[ $this->id . '_cost_unit' ] ); | |
} | |
if ( isset( $_POST[ $this->id . '_fee' ] ) ) { | |
$rule_fee = array_map( 'stripslashes', $_POST[ $this->id . '_fee' ] ); | |
} | |
if ( isset( $_POST[ $this->id . '_break' ] ) ) { | |
$rule_break = array_map( 'stripslashes', $_POST[ $this->id . '_break' ] ); | |
} | |
for ( $i = 0; $i <= count( $rule_condition ); $i++ ) { | |
if ( isset( $rule_condition[ $i ] ) ) { | |
$rule_cost[ $i ] = wc_format_decimal( $rule_cost[ $i ] ); | |
$rule_cost_unit[ $i ] = wc_format_decimal( $rule_cost_unit[ $i ] ); | |
if ( ! strstr( $rule_fee[ $i ], '%' ) ) { | |
$rule_fee[ $i ] = wc_format_decimal( $rule_fee[ $i ] ); | |
} else { | |
$rule_fee[ $i ] = wc_clean( $rule_fee[ $i ] ); | |
} | |
if ( ! empty( $rule_min[ $i ] ) ) { | |
// For quantity condition, we disallow floats. | |
if ( 'quantity' === $rule_condition[ $i ] ) { | |
$rule_min[ $i ] = intval( $rule_min[ $i ] ); | |
} else { | |
$rule_min[ $i ] = floatval( $rule_min[ $i ] ); | |
} | |
} | |
if ( ! empty( $rule_break[ $i ] ) ) { | |
$rule_break[ $i ] = 'yes'; | |
} else { | |
$rule_break[ $i ] = 'no'; | |
} | |
if ( ! empty( $rule_max[ $i ] ) ) { | |
// For quantity condition, we disallow floats. | |
if ( 'quantity' === $rule_condition[ $i ] ) { | |
$rule_max[ $i ] = intval( $rule_max[ $i ] ); | |
} else { | |
$rule_max[ $i ] = floatval( $rule_max[ $i ] ); | |
} | |
} | |
// Add to rules array. | |
$rules[] = array( | |
'condition' => $rule_condition[ $i ], | |
'min' => $rule_min[ $i ], | |
'max' => $rule_max[ $i ], | |
'cost' => $rule_cost[ $i ], | |
'cost_unit' => $rule_cost_unit[ $i ], | |
'fee' => $rule_fee[ $i ], | |
'break' => $rule_break[ $i ], | |
); | |
} | |
} | |
return $rules; | |
} | |
/** | |
* Shows notices when shipping is not available. | |
* | |
* @access public | |
* @since 3.1.3 | |
* @version 3.1.3 | |
* | |
* @param string $notice Notice message. | |
* @param bool $cart_checkout Determine if we need to show in both cart and checkout pages. | |
*/ | |
public function show_notice( $notice = '', $cart_checkout = true ) { | |
$this->notice = $notice; | |
add_filter( 'woocommerce_no_shipping_available_html', array( $this, 'get_notice' ) ); | |
if ( $cart_checkout ) { | |
add_filter( 'woocommerce_cart_no_shipping_available_html', array( $this, 'get_notice' ) ); | |
} | |
} | |
/** | |
* Gets the currently set notice. | |
* | |
* @access public | |
* @since 3.1.3 | |
* @version 3.1.3 | |
* @return string Notice. | |
*/ | |
public function get_notice() { | |
return $this->notice; | |
} | |
/** | |
* Calculate shipping based on rules. | |
* | |
* @since 1.0.0 | |
* @version 1.0.7 | |
* | |
* @param array $package Package to ship. | |
* @return array | |
*/ | |
public function calculate_shipping( $package = array() ) { | |
$this->rates = array(); | |
// Make sure the customer address is not only the country code | |
// as this means the customer has not yet entered an address. | |
if ( 2 === strlen( $this->get_customer_address_string( $package ) ) ) { | |
return; | |
} | |
// Get region based on customer address (GB uses CCTLD). | |
$region = empty( $package['destination']['country'] ) ? '' : strtolower( $package['destination']['country'] ); | |
if ( 'gb' === $region ) { | |
$region = 'uk'; | |
} | |
$distance = $this->get_api()->get_distance( $this->get_shipping_address_string(), $this->get_customer_address_string( $package ), false, $this->mode, $this->avoid, $this->unit, $region ); | |
// Check if a valid response was received. | |
if ( ! isset( $distance->rows[0] ) || 'OK' !== $distance->rows[0]->elements[0]->status ) { | |
// If the address is nout found, then the new call will be done, else, the normal call will be done. | |
unset($package['destination']['address'] ); | |
unset($package['destination']['address_2'] ); | |
unset($this->address_1); | |
unset($this->address_2 ); | |
// Added this for the new API call. | |
$distance = $this->get_api()->get_distance( $this->get_shipping_address_string(), $this->get_customer_address_string( $package ), false, $this->mode, $this->avoid, $this->unit, $region ); | |
if ( ! isset( $distance->rows[0] ) || 'OK' !== $distance->rows[0]->elements[0]->status ) { | |
return; | |
} | |
} | |
$label_suffix = array(); | |
// Maybe display distance next to the cost. | |
if ( $this->show_distance && is_object( $distance ) ) { | |
$label_suffix[] = $distance->rows[0]->elements[0]->distance->text; | |
} | |
// Maybe display duration next to the cost. | |
if ( $this->show_duration && is_object( $distance ) ) { | |
$label_suffix[] = $distance->rows[0]->elements[0]->duration->text; | |
} | |
$label_suffix = ! empty( $label_suffix ) | |
? sprintf( ' (%s)', implode( '; ', $label_suffix ) ) | |
: ''; | |
$label_suffix = apply_filters( 'woocommerce_distance_rate_shipping_label_suffix', $label_suffix, $distance, $package ); | |
$travel_time_minutes = round( $distance->rows[0]->elements[0]->duration->value / 60 ); | |
$rounding_precision = apply_filters( 'woocommerce_distance_rate_shipping_distance_rounding_precision', 1 ); | |
$distance_value = $distance->rows[0]->elements[0]->distance->value; | |
if ( 'imperial' === $this->unit ) { | |
$distance = round( $distance_value * 0.000621371192, $rounding_precision ); | |
} else { | |
$distance = round( $distance_value / 1000, $rounding_precision ); | |
} | |
/** | |
* Filter the distance received by the api before the shipping rules are checked | |
* | |
* @param stdClass $distance | |
* @param integer $distance_value | |
* @param string $unit | |
*/ | |
$distance = apply_filters( 'woocommerce_distance_rate_shipping_calculated_distance', $distance, $distance_value, $this->unit ); | |
$rule_found = false; | |
$shipping_total = 0; | |
foreach ( $this->rules as $rule ) { | |
switch ( $rule['condition'] ) { | |
case 'distance': | |
$rule_cost = $this->distance_shipping( $rule, $distance, $package ); | |
if ( ! is_null( $rule_cost ) ) { | |
$rule_found = true; | |
$shipping_total += $rule_cost; | |
} else { | |
$this->show_notice( __( 'Sorry, that shipping location is beyond our shipping radius.', 'woocommerce-distance-rate-shipping' ) ); | |
} | |
break; | |
case 'time': | |
$rule_cost = $this->time_shipping( $rule, $travel_time_minutes, $package ); | |
if ( ! is_null( $rule_cost ) ) { | |
$rule_found = true; | |
$shipping_total += $rule_cost; | |
} else { | |
$this->show_notice( __( 'Sorry, that shipping location is beyond our shipping travel time.', 'woocommerce-distance-rate-shipping' ) ); | |
} | |
break; | |
case 'weight': | |
$rule_cost = $this->weight_shipping( $rule, $distance, $package ); | |
if ( ! is_null( $rule_cost ) ) { | |
$rule_found = true; | |
$shipping_total += $rule_cost; | |
} else { | |
$this->show_notice( __( 'Sorry, the total weight of your chosen items is beyond what we can ship.', 'woocommerce-distance-rate-shipping' ) ); | |
} | |
break; | |
case 'total': | |
$rule_cost = $this->order_total_shipping( $rule, $distance, $package ); | |
if ( ! is_null( $rule_cost ) ) { | |
$rule_found = true; | |
$shipping_total += $rule_cost; | |
} else { | |
$this->show_notice( __( 'Sorry, the total order cost is beyond what we can ship.', 'woocommerce-distance-rate-shipping' ) ); | |
} | |
break; | |
case 'quantity': | |
$rule_cost = $this->quantity_shipping( $rule, $distance, $package ); | |
if ( ! is_null( $rule_cost ) ) { | |
$rule_found = true; | |
$shipping_total += $rule_cost; | |
} else { | |
$this->show_notice( __( 'Sorry, the total quantity of items is beyond what we can ship.', 'woocommerce-distance-rate-shipping' ) ); | |
} | |
break; | |
} | |
// Skip other rules if break. | |
if ( 'yes' === $rule['break'] && $rule_found ) { | |
break; | |
} | |
} | |
if ( $rule_found ) { | |
$args = array( | |
'id' => $this->get_rate_id(), | |
'label' => $this->title . $label_suffix, | |
'cost' => $shipping_total, | |
); | |
$this->add_rate( $args ); | |
} | |
} | |
/** | |
* Calculate shipping based on distance. | |
* | |
* @since 1.0.0 | |
* @version 1.0.8 | |
* | |
* @param array $rule Rule. | |
* @param int $distance Distance. | |
* @param object $package Package to ship. | |
* @return int | |
*/ | |
public function distance_shipping( $rule, $distance, $package ) { | |
$min_match = false; | |
$max_match = false; | |
$rule_cost = null; | |
if ( empty( $rule['min'] ) || $distance >= $rule['min'] ) { | |
$min_match = true; | |
} | |
if ( empty( $rule['max'] ) || $distance <= $rule['max'] ) { | |
$max_match = true; | |
} | |
if ( $min_match && $max_match ) { | |
$rule_cost = 0; | |
if ( ! empty( $rule['cost_unit'] ) ) { | |
$rule_cost = $rule['cost_unit'] * $distance; | |
} | |
if ( ! empty( $rule['cost'] ) ) { | |
$rule_cost += $rule['cost']; | |
} | |
if ( ! empty( $rule['fee'] ) ) { | |
$rule_cost += $this->get_fee( $rule['fee'], $package['contents_cost'] ); | |
} | |
} | |
/** | |
* Filter the rule cost for distance shipping. | |
* | |
* @since 1.0.8 | |
* @version 1.0.8 | |
* | |
* @param float $rule_cost Calculated cost. | |
* @param array $rule Rule in DRS' row. | |
* @param float $distance Distance. | |
* @param array $package Package to ship. | |
*/ | |
return apply_filters( | |
'woocommerce_distance_rate_shipping_rule_cost_distance_shipping', | |
$rule_cost, | |
$rule, | |
$distance, | |
$package | |
); | |
} | |
/** | |
* Calculate shipping based on total travel time. | |
* | |
* @since 1.0.0 | |
* @version 1.0.8 | |
* | |
* @param array $rule Rule. | |
* @param int $travel_time_minutes Travel time in minutes. | |
* @param object $package Package to ship. | |
* @return int | |
*/ | |
public function time_shipping( $rule, $travel_time_minutes, $package ) { | |
$min_match = false; | |
$max_match = false; | |
$rule_cost = null; | |
if ( empty( $rule['min'] ) || $travel_time_minutes >= $rule['min'] ) { | |
$min_match = true; | |
} | |
if ( empty( $rule['max'] ) || $travel_time_minutes <= $rule['max'] ) { | |
$max_match = true; | |
} | |
if ( $min_match && $max_match ) { | |
$rule_cost = 0; | |
if ( ! empty( $rule['cost_unit'] ) ) { | |
$rule_cost = $rule['cost_unit'] * $travel_time_minutes; | |
} | |
if ( ! empty( $rule['cost'] ) ) { | |
$rule_cost += $rule['cost']; | |
} | |
if ( ! empty( $rule['fee'] ) ) { | |
$rule_cost += $this->get_fee( $rule['fee'], $package['contents_cost'] ); | |
} | |
} | |
/** | |
* Filter the rule cost for time shipping. | |
* | |
* @since 1.0.8 | |
* @version 1.0.8 | |
* | |
* @param float $rule_cost Calculated cost. | |
* @param array $rule Rule in DRS' row. | |
* @param int $travel_time_minutes Travel time in minutes. | |
* @param array $package Package to ship. | |
*/ | |
return apply_filters( | |
'woocommerce_distance_rate_shipping_rule_cost_time_shipping', | |
$rule_cost, | |
$rule, | |
$travel_time_minutes, | |
$package | |
); | |
} | |
/** | |
* Calculate shipping based on weight. | |
* | |
* @since 1.0.0 | |
* @version 1.0.8 | |
* | |
* @param array $rule Rule. | |
* @param int $distance Distance. | |
* @param object $package Package to ship. | |
* @return int | |
*/ | |
public function weight_shipping( $rule, $distance, $package ) { | |
$min_match = false; | |
$max_match = false; | |
$rule_cost = null; | |
$total_weight = WC()->cart->cart_contents_weight; | |
if ( isset( $total_weight ) && $total_weight > 0 ) { | |
if ( empty( $rule['min'] ) || $total_weight >= $rule['min'] ) { | |
$min_match = true; | |
} | |
if ( empty( $rule['max'] ) || $total_weight <= $rule['max'] ) { | |
$max_match = true; | |
} | |
if ( $min_match && $max_match ) { | |
$rule_cost = 0; | |
if ( ! empty( $rule['cost_unit'] ) ) { | |
$rule_cost = $rule['cost_unit'] * $distance; | |
} | |
if ( ! empty( $rule['cost'] ) ) { | |
$rule_cost += $rule['cost']; | |
} | |
if ( ! empty( $rule['fee'] ) ) { | |
$rule_cost += $this->get_fee( $rule['fee'], $package['contents_cost'] ); | |
} | |
} | |
} | |
/** | |
* Filter the rule cost for distance shipping. | |
* | |
* @since 1.0.8 | |
* @version 1.0.8 | |
* | |
* @param float $rule_cost Calculated cost. | |
* @param array $rule Rule in DRS' row. | |
* @param float $distance Distance. | |
* @param array $package Package to ship. | |
*/ | |
return apply_filters( | |
'woocommerce_distance_rate_shipping_rule_cost_weight_shipping', | |
$rule_cost, | |
$rule, | |
$distance, | |
$package | |
); | |
} | |
/** | |
* Calculate shipping based on order total. | |
* | |
* @since 1.0.0 | |
* @version 1.0.8 | |
* | |
* @param array $rule Rule. | |
* @param int $distance Distance. | |
* @param object $package Package to ship. | |
* @return int | |
*/ | |
public function order_total_shipping( $rule, $distance, $package ) { | |
$min_match = false; | |
$max_match = false; | |
$rule_cost = null; | |
$order_total = $package['contents_cost']; | |
if ( isset( $order_total ) && $order_total > 0 ) { | |
if ( empty( $rule['min'] ) || $order_total >= $rule['min'] ) { | |
$min_match = true; | |
} | |
if ( empty( $rule['max'] ) || $order_total <= $rule['max'] ) { | |
$max_match = true; | |
} | |
if ( $min_match && $max_match ) { | |
$rule_cost = 0; | |
if ( ! empty( $rule['cost_unit'] ) ) { | |
$rule_cost = $rule['cost_unit'] * $distance; | |
} | |
if ( ! empty( $rule['cost'] ) ) { | |
$rule_cost += $rule['cost']; | |
} | |
if ( ! empty( $rule['fee'] ) ) { | |
$rule_cost += $this->get_fee( $rule['fee'], $package['contents_cost'] ); | |
} | |
} | |
} | |
/** | |
* Filter the rule cost for distance shipping. | |
* | |
* @since 1.0.8 | |
* @version 1.0.8 | |
* | |
* @param float $rule_cost Calculated cost. | |
* @param array $rule Rule in DRS' row. | |
* @param float $distance Distance. | |
* @param array $package Package to ship. | |
*/ | |
return apply_filters( | |
'woocommerce_distance_rate_shipping_rule_cost_order_total_shipping', | |
$rule_cost, | |
$rule, | |
$distance, | |
$package | |
); | |
} | |
/** | |
* Calculate shipping based on quantity. | |
* | |
* @since 1.0.0 | |
* @version 1.0.8 | |
* | |
* @param array $rule Rule. | |
* @param int $distance Distance. | |
* @param object $package Package to ship. | |
* @return int | |
*/ | |
public function quantity_shipping( $rule, $distance, $package ) { | |
$min_match = false; | |
$max_match = false; | |
$rule_cost = null; | |
$content_count = WC()->cart->get_cart_contents_count(); | |
if ( isset( $content_count ) && $content_count > 0 ) { | |
if ( empty( $rule['min'] ) || $content_count >= $rule['min'] ) { | |
$min_match = true; | |
} | |
if ( empty( $rule['max'] ) || $content_count <= $rule['max'] ) { | |
$max_match = true; | |
} | |
if ( $min_match && $max_match ) { | |
$rule_cost = 0; | |
if ( ! empty( $rule['cost_unit'] ) ) { | |
$rule_cost = $rule['cost_unit'] * $distance; | |
} | |
if ( ! empty( $rule['cost'] ) ) { | |
$rule_cost += $rule['cost']; | |
} | |
if ( ! empty( $rule['fee'] ) ) { | |
$rule_cost += $this->get_fee( $rule['fee'], $package['contents_cost'] ); | |
} | |
} | |
} | |
/** | |
* Filter the rule cost for distance shipping. | |
* | |
* @since 1.0.8 | |
* @version 1.0.8 | |
* | |
* @param float $rule_cost Calculated cost. | |
* @param array $rule Rule in DRS' row. | |
* @param float $distance Distance. | |
* @param array $package Package to ship. | |
*/ | |
return apply_filters( | |
'woocommerce_distance_rate_shipping_rule_cost_quantity_shipping', | |
$rule_cost, | |
$rule, | |
$distance, | |
$package | |
); | |
} | |
/** | |
* Build customer address string from package. | |
* | |
* @param array $package Package to ship. | |
* @return string | |
*/ | |
public function get_customer_address_string( $package ) { | |
$address = array(); | |
// Cart page only has country, state and zipcodes. | |
if ( isset( $package['destination']['postcode'] ) && ! empty( $package['destination']['postcode'] ) ) { | |
$address[] = $package['destination']['postcode']; | |
} | |
if ( isset( $package['destination']['state'] ) && ! empty( $package['destination']['state'] ) ) { | |
$state = $package['destination']['state']; | |
$country = $package['destination']['country']; | |
// Convert state code to full name if available | |
if ( isset( WC()->countries->states[ $country ], WC()->countries->states[ $country ][ $state ] ) ) { | |
$state = WC()->countries->states[ $country ][ $state ]; | |
$country = WC()->countries->countries[ $country ]; | |
} | |
$address[] = $state; | |
} | |
if ( isset( $package['destination']['country'] ) && ! empty( $package['destination']['country'] ) ) { | |
$country = $package['destination']['country']; | |
// Convert country code to full name if available | |
if ( isset( WC()->countries->countries[ $country ] ) ) { | |
$country = WC()->countries->countries[ $country ]; | |
} | |
$address[] = $country; | |
} | |
if ( is_checkout() ) { | |
if ( isset( $package['destination']['address'] ) && ! empty( $package['destination']['address'] ) ) { | |
$address[] = $package['destination']['address']; | |
} | |
if ( isset( $package['destination']['address_2'] ) && ! empty( $package['destination']['address_2'] ) ) { | |
$address[] = $package['destination']['address_2']; | |
} | |
if ( isset( $package['destination']['city'] ) && ! empty( $package['destination']['city'] ) ) { | |
$address[] = $package['destination']['city']; | |
} | |
} | |
return implode( ', ', $address ); | |
} | |
/** | |
* Get the shipping from address as string. | |
* | |
* @return string | |
*/ | |
public function get_shipping_address_string() { | |
$address = array(); | |
if ( isset( $this->address_1 ) && ! empty( $this->address_1 ) ) { | |
$address[] = $this->address_1; | |
} | |
if ( isset( $this->address_2 ) && ! empty( $this->address_2 ) ) { | |
$address[] = $this->address_2; | |
} | |
if ( isset( $this->city ) && ! empty( $this->city ) ) { | |
$address[] = $this->city; | |
} | |
if ( isset( $this->postal_code ) && ! empty( $this->postal_code ) ) { | |
$address[] = $this->postal_code; | |
} | |
if ( isset( $this->state_province ) && ! empty( $this->state_province ) ) { | |
$address[] = $this->state_province; | |
} | |
if ( isset( $this->country ) && ! empty( $this->country ) ) { | |
$address[] = $this->country; | |
} | |
return implode( ', ', $address ); | |
} | |
/** | |
* Return the API object. | |
* | |
* @return object WC_Google_Distance_Matrix_API | |
*/ | |
public function get_api() { | |
if ( is_object( $this->api ) ) { | |
return $this->api; | |
} | |
require 'class-wc-google-distance-matrix-api.php'; | |
$api_key = $this->api_key; | |
$debug = $this->debug; | |
return $this->api = new WC_Google_Distance_Matrix_API( $api_key, $debug ); | |
} | |
/** | |
* Clear transients. | |
* | |
* @access public | |
* @return void | |
*/ | |
public function clear_transients() { | |
global $wpdb; | |
$wpdb->query( "DELETE FROM `$wpdb->options` WHERE `option_name` LIKE ('_transient_distance_rate_%') OR `option_name` LIKE ('_transient_timeout_distance_rate_%')" ); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script type="text/javascript"> | |
/*** CHECKOUT SHIPPING ***/ | |
/* The Javascript I have included in my theme. What it will do is calculate the shortest distance form the client and hide the other options on the checkout and cart pages. */ | |
/* I've also added some text to show my clients how long delivery will take. */ | |
/* Depending on the distance calucation, I select the closest option to my client. */ | |
function selectClosest() { | |
if (jQuery("#shipping_method li").length == 0) return; | |
var distance = new Array(); | |
var count = 0; | |
jQuery.each(jQuery("#shipping_method li"), function () { | |
var km = jQuery(this).text().split(" (")[1].split(" km")[0]; | |
var id = jQuery(this).find('input').attr('id'); | |
if (jQuery(this).text().indexOf(':') === -1) { | |
jQuery(this).find("label").html("<span>"+jQuery(this).text() + ": Free Shipping </span><span class='expectDelivery'>Expect Delivery within: 3-5 Working Days</span>"); | |
} | |
else if (jQuery(this).text().indexOf('R250') !== -1) | |
{ | |
jQuery(this).find("label").html("<span>"+jQuery(this).text() + " </span><span class='expectDelivery'>Expect Delivery within: 5-7 Working Days</span>"); | |
} | |
else if (jQuery(this).text().indexOf('R500') !== -1) | |
{ | |
jQuery(this).find("label").html("<span>"+jQuery(this).text() + " </span><span class='expectDelivery'>Expect Delivery within: 7-10 Working Days</span>"); | |
} | |
distance.push([parseFloat(km.replace(",", "")), id]); | |
count++; | |
}); | |
distance = distance.sort(function (a, b) { | |
return a[0] - b[0]; | |
}); | |
if (jQuery("#" + distance[0][1])) { | |
jQuery("#" + distance[0][1]).attr('checked', 'checked'); | |
jQuery.each(jQuery("#shipping_method li"), function () { | |
jQuery(this).hide(); | |
}); | |
jQuery("#" + distance[0][1]).parent().show(); | |
} | |
} | |
if (window.location.href.indexOf("checkout.html") > -1 || window.location.href.indexOf("cart.html") > -1) { | |
// selectClosest(); | |
jQuery('#billing_postcode').on('input', function (e) { | |
selectClosest(); | |
}); | |
jQuery('#billing_city').on('input', function (e) { | |
selectClosest(); | |
}); | |
jQuery('#billing_address_1').on('input', function (e) { | |
selectClosest(); | |
}); | |
jQuery(document).ajaxComplete(function () { | |
selectClosest(); | |
}); | |
} | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment