Skip to content
This repository
JustinSainton JustinSainton
file 380 lines (302 sloc) 13.275 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380
<?php
/**
* WP e-Commerce Australia Post shipping module - http://auspost.com.au
*
*/
class australiapost {
var $internal_name, $name;

/**
* List of Valid Australia Post services
*
* @var Array
*/
var $services = array();

/**
* Shipping module settings
*
* @var Array
*/
var $settings;

var $base_country;
var $base_zipcode;

/**
* Constructor
*/
function australiapost () {
$this->internal_name = "australiapost";
$this->name = __( 'Australia Post', 'wpsc' );
$this->is_external = true;
$this->requires_weight = true;
$this->needs_zipcode = true;
$this->debug = false; // change to true to log (to the PHP error log) the API URLs and responses for each active service

// Initialise the list of available postage services

// DOMESTIC (Australia only)
$this->services['STANDARD'] = __('Standard Parcel Post', 'wpsc');
$this->services['EXPRESS'] = __('Express Post', 'wpsc');

// INTERNATIONAL
$this->services['AIR'] = __('Air Mail', 'wpsc');
$this->services['SEA'] = __('Sea Mail', 'wpsc');
$this->services['ECI_M'] = __('Express Courier International', 'wpsc'); // Express Courier International Merchandise
$this->services['EPI'] = __('Express Post International', 'wpsc');

// Attempt to load the existing settings
$this->settings = get_option("wpsc_australiapost_settings");

$this->base_country = get_option('base_country');
$this->base_zipcode = get_option('base_zipcode');

if (!$this->settings) {
// Initialise the settings
$this->settings = array();
foreach ($this->services as $code => $value) {
$this->settings['services'][$code] = true;
}
update_option('wpsc_australiapost_settings', $this->settings);
}

return true;
}

function getId() {
}

function setId($id) {
}

function getName() {
return $this->name;
}

function getInternalName() {
return $this->internal_name;
}

function getForm() {
$output = '';
// Only for Australian merchants
if ($this->base_country != 'AU') {
return "<tr><td colspan='2'>" . __('This shipping module only works if the base country in settings, region is set to Australia.', 'wpsc') . "</td></tr>";
}

// Base postcode must be set
if (strlen($this->base_zipcode) != 4) {
return "<tr><td colspan='2'>" .__('You must set your base postcode above before this shipping module will work.', 'wpsc') . "</td></tr>";
}

$output .= "<tr><td>" . __('Select the Australia Post services that you want to offer during checkout:', 'wpsc') . "</td></tr>";
$output .= "<tr><td>";
foreach ($this->services as $code => $value) {
$checked = $this->settings['services'][$code] ? "checked='checked'" : '';
$output .= "<label style=\"margin-left: 50px;\">";
$output .= "<input type='checkbox' {$checked} name='wpsc_australiapost_settings[services][{$code}]'/> ";
$output .= $this->services[$code];
$output .= "</label><br />";
}
$output .= "<input type='hidden' name='{$this->internal_name}_updateoptions' value='true'>";
$output .= "</td></tr>";
$output .= "<tr><td><h4>" . __('Notes:', 'wpsc') . "</h4>";
$output .= __('1. The actual services quoted to the customer during checkout will depend on the destination country. Not all methods are available to all destinations.', 'wpsc') . "<br />";
$output .= __('2. Each product must have a valid weight configured. When editing a product, use the weight field.', 'wpsc') . "<br />";
$output .= __('3. To ensure accurate quotes, each product must valid dimensions configured. When editing a product, use the height, width and length fields.', 'wpsc') . "<br />";
$output .= __('4. The combined dimensions are estimated by calculating the volume of each item, and then calculating the cubed root of the overall order volume which becomes width, length and height.', 'wpsc') . "<br />";
$output .= __('5. If no product dimensions are defined, then default package dimensions of 100mm x 100mm x 100mm will be used.', 'wpsc') . "<br />";
$output .= "</tr></td>";
return $output;
}

function submit_form() {
$this->settings['services'] = array();

// Only continue if this module's options were updated
if ( !isset($_POST["{$this->internal_name}_updateoptions"]) || !$_POST["{$this->internal_name}_updateoptions"] ) return;

if (isset($_POST['wpsc_australiapost_settings'])) {
if (isset($_POST['wpsc_australiapost_settings']['services'])) {
foreach ($this->services as $code => $name) {
$this->settings['services'][$code] = isset($_POST['wpsc_australiapost_settings']['services'][$code]) ? true : false;
}
}
}

update_option('wpsc_australiapost_settings', $this->settings);
return true;
}

function getQuote() {
global $wpdb, $wpsc_cart;

if ($this->base_country != 'AU' || strlen($this->base_zipcode) != 4 || !count($wpsc_cart->cart_items)) return;

$dest = wpsc_get_customer_meta( 'shipping_country' );

$destzipcode = (string) wpsc_get_customer_meta( 'shipping_zip' );
if( isset($_POST['zipcode'] ) ) {
$destzipcode = $_POST['zipcode'];
wpsc_update_customer_meta( 'shipping_zip', $destzipcode );
}

if ($dest == 'AU' && strlen($destzipcode) != 4) {
// Invalid Australian Post Code entered, so just return an empty set of quotes instead of wasting time contactin the Aus Post API
return array();
}

/*
3 possible scenarios:

1.
Cart consists of only item(s) that have "disregard shipping" ticked.

In this case, WPEC doesn't mention shipping at all during checkout, and this shipping module probably won't be executed at all.

Just in case it does get queried, we should still query the Australia Post API for valid shipping estimates,
and then override the quoted price(s) to $0.00 so the customer is able to get free shipping.


2.
Cart consists of only item(s) where "disregard shipping" isn't ticked (ie. all item(s) attract shipping charges).

In this case, we should query the Australia Post API as per normal.


3.
Cart consists of one or more "disregard shipping" product(s), and one or more other products that attract shipping charges.

In this case, we should query the Aus Post API, only taking into account the product(s) that attract shipping charges.
Products with "disregard shipping" ticked shouldn't have their weight or dimensions included in the quote.
*/


// Obtain the total combined weight for all items(s) in the cart (excluding items that have the "Disregard Shipping for this product" option ticked)
// Weight is in grams
$weight = wpsc_convert_weight($wpsc_cart->calculate_total_weight(true), 'pound', 'gram');

// Calculate the total cart dimensions by adding the volume of each product then calculating the cubed root
$volume = 0;

// Total number of item(s) in the cart
$numItems = count($wpsc_cart->cart_items);

if ($numItems == 0) {
// The customer's cart is empty. This probably shouldn't occur, but just in case!
return array();
}

// Total number of item(s) that don't attract shipping charges.
$numItemsWithDisregardShippingTicked = 0;

foreach($wpsc_cart->cart_items as $cart_item) {

if ( !$cart_item->uses_shipping ) {
// The "Disregard Shipping for this product" option is ticked for this item.
// Don't include it in the shipping quote.
$numItemsWithDisregardShippingTicked++;
continue;
}

// If we are here then this item attracts shipping charges.

$meta = get_product_meta($cart_item->product_id,'product_metadata',true);
$meta = $meta['dimensions'];

if ($meta && is_array($meta)) {
$productVolume = 1;
foreach (array('width','height','length') as $dimension) {
// default dimension to 100mm
if ( empty( $meta[$dimension] ) ) {
$meta[$dimension] = 100;
$meta["{$dimension}_unit"] = 'mm';
}
switch ($meta["{$dimension}_unit"]) {
// we need the units in mm
case 'cm':
// convert from cm to mm
$meta[$dimension] *= 10;
break;
case 'meter':
// convert from m to mm
$meta[$dimension] *= 1000;
break;
case 'in':
// convert from in to mm
$meta[$dimension] *= 25.4;
break;
}

$productVolume *= $meta[$dimension];
}

$volume += floatval($productVolume) * $cart_item->quantity;
}
}

// If there's only one item in the cart, its dimensions will be used
// But if there are multiple items, cubic root of total volume will be used instead
if ( $wpsc_cart->get_total_shipping_quantity() == 1 ) {
$height = $meta['height'];
$width = $meta['width'];
$length = $meta['length'];
} else {
// Calculate the cubic root of the total volume, rounding up
$cuberoot = ceil(pow($volume, 1 / 3));

if ($cuberoot > 0)
$height = $width = $length = $cuberoot;
}

// As per http://auspost.com.au/personal/parcel-dimensions.html: if the parcel is box-shaped, both its length and width must be at least 15cm.
if ($length < 150) $length = 150;
if ($width < 150) $width = 150;

// By default we should use Australia Post's quoted rate(s)
$shippingPriceNeedsToBeZero = false;

if ($numItemsWithDisregardShippingTicked == $numItems) {
// The cart consists of entirely "disregard shipping" products, so the shipping quote(s) should be $0.00
// Set the weight to 1 gram so that we can obtain valid Australia Post quotes (which we will then ignore the quoted price of)
$weight = 1;
$shippingPriceNeedsToBeZero = true;
}

// API Documentation: http://drc.edeliver.com.au/
$url = "http://drc.edeliver.com.au/ratecalc.asp";

$params = array(
'Pickup_Postcode' => $this->base_zipcode
, 'Destination_Postcode' => $destzipcode
, 'Quantity' => 1
, 'Weight' => $weight
, 'Height' => $height
, 'Width' => $width
, 'Length' => $length
, 'Country' => $dest
);

// URL encode the parameters to prevent issues where postcodes contain spaces (eg London postcodes)
$params = array_map('urlencode', $params);

$url = add_query_arg($params, $url);

$log = '';
$methods = array();
foreach ($this->services as $code => $service) {
if (!$this->settings['services'][$code]) continue;

$fullURL = add_query_arg('Service_Type', $code, $url);

// This cache key should be unique for a cart with these contents and destination
// Needs to be less than 45 characters (as per http://core.trac.wordpress.org/ticket/15058)
$cacheKey = 'wpec_apq_' . md5($fullURL);

// See if this Australia Post quote is cached
$cachedResult = get_transient($cacheKey);

if ( false === $cachedResult ) {

// Quote isn't cached -> query the Australia Post API and then cache the result for 10 minutes

$response = wp_remote_get($fullURL);

// Silently ignore any API server errors
if ( is_wp_error($response) || $response['response']['code'] != '200' || empty($response['body']) ) continue;

if ($this->debug) {
$log .=" {$fullURL}\n " . $response['body'] . "\n";
}

$lines = explode("\n", $response['body']);

foreach($lines as $line) {
if ( empty( $line ) )
continue;
list($key, $value) = explode('=', $line);
$key = trim($key);
$value = trim($value);
switch ($key) {
case 'charge':
if ($shippingPriceNeedsToBeZero) {
// All shipping prices quoted should be zero
$methods[$code]['charge'] = 0.00;
$log .=" NB: the price for the above quote has been overridden to $0.00\n\n";
} else {
// Use the Australia Post quoted price
$methods[$code]['charge'] = floatval($value);
}
break;
case 'days':
$methods[$code]['days'] = floatval($value);
break;
case 'err_msg':
$methods[$code]['err_msg'] = trim($value);
break;
}
}
$methods[$code]['name'] = $this->services[$code];

// Cache this quote for 10 minutes
set_transient($cacheKey, $methods[$code], 600);

} else {
// This quote is cached so use that result instead
$methods[$code] = $cachedResult;
}
}
if ( $this->debug && strlen($log) )
error_log( 'WP e-Commerce Australia Post shipping quotes for ' . home_url() . ":\n----------\n$log----------" );

// Allow another WordPress plugin to override the quoted method(s)/amount(s)

$methods = apply_filters('wpsc_australia_post_methods', $methods, $this->base_zipcode, $destzipcode, $dest, $weight);

$quotedMethods = array();

foreach ($methods as $code => $data) {
// Only include methods with an OK response
if ($data['err_msg'] != 'OK') continue;

if ($data['days']) {
// If the estimated number of days is specified, so include it in the quote
$text = sprintf(_n('%1$s (estimated delivery time: %2$d business day)', '%1$s (estimated delivery time: %2$d business days)', $data['days'], 'wpsc'), $data['name'], $data['days']);
} else {
// No time estimate
$text = $data['name'];
}
$quotedMethods[$text] = $data['charge'];
}
return $quotedMethods;
}

function get_item_shipping() {
}
}
$australiapost = new australiapost();
$wpsc_shipping_modules[$australiapost->getInternalName()] = $australiapost;
?>
Something went wrong with that request. Please try again.