Here's a radical experiment.
1. For pattern matching, I wonder if we can skip using the *'s idea and just assume a "prefix". That is, for M***** just list M, and for L4**** just use L4.
2. In any listed postal code, if you add a "!" at the beginning or end of the code, it will exclude that one. eg: M4B1Y! or !M4B1Y would exclude all M4B1Y* codes.
3. I also added stripping of hyphens ... so in theory this can also work for US zip codes where someone wants to add specificity in zip-plus-four format. (The original code trimmed all zips to the "minimum allowed length" in order to do matching, which kills the ability to do pattern-matching and negation.)
One caveat to note: if a postalcode pattern is present in more than one zone, the "last" non-excluded match will be used for calculating rates. (eg: if it matches in zones 1 and 3, then the rates from zone 3 will apply, ignoring its existence in zone 1).
Here's the updated code which does all this.
Code:
$this->dest_zone = false;
$this->default_zone = false;
// $this->dest_zipcode = substr(strtoupper($order->delivery['postcode']), 0, (int)ENTRY_POSTCODE_MIN_LENGTH);
$this->dest_zipcode = strtoupper(str_replace([' ', '-'], '', $order->delivery['postcode']));
for ($i = 1; $i <= $this->num_zones; $i++) {
$current_table = "MODULE_SHIPPING_ZIPSHIP_CODES_$i";
if (defined($current_table)) {
$zipcode_table = constant($current_table);
if ($zipcode_table === '00000') {
$this->default_zone = $i;
} else {
// Read codes from config
$zipcodes = explode(',', str_replace([' ', '-'], '', strtoupper($zipcode_table)));
// sort codes, first by alpha, then by reverse-length so we process longest-first
usort($zipcodes, function($a, $b){
$a = trim($a, '!');
$b = trim($b, '!');
return strcmp($a, $b);
});
usort($zipcodes, function($a, $b){
$a = trim($a, '!');
$b = trim($b, '!');
return (strlen($a) < strlen($b)) ? 1 : -1;
});
// Check for exclusion patterns defined with a starting or ending ! symbol
foreach($zipcodes as $check_against) {
if ($check_against === '!' || strpos($check_against, '!') === false) continue; // if no ! skip checking this iteration
if (strpos($this->dest_zipcode, trim($check_against, '!')) === 0) { // strip ! to do matching
$this->dest_zone = false;
// If exclusion detected, use "continue" to end this foreach and skip the next one as well
continue 2;
}
}
// Pass if the supplied code matches a defined prefix pattern
foreach($zipcodes as $check_against) {
if (strpos($check_against, '!') !== false) continue;
if (strpos($this->dest_zipcode, $check_against) === 0) {
$this->dest_zone = $i;
// If a match is found, end this foreach
break;
}
}
}
}
}
if ($this->dest_zone === false && $this->default_zone === false) {
$this->enabled = false;
}
}
}
}
public function quote($method = '')
Bookmarks