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 = '')


Reply With Quote
