Source of file ShippingCalculator.php
Size: 8,194 Bytes - Last Modified: 2021-12-24T05:16:24+00:00
/var/www/docs.ssmods.com/process/src/code/tools/ShippingCalculator.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305 | <?php /** * Shipping calculator is a basic helper class that can be used to query * the shipping table. * * At the moment we only output shipping areas based on weight/cost/ * items and location. Buit this can now be expanded more easily if * needed. * * @author ilateral (info@ilateral.co.uk) * @package checkout */ class ShippingCalculator extends Object { /** * 2 character country code * * @var string */ private $country_code; public function setCountryCode($value) { $this->country_code = $value; return $this; } public function getCountryCode() { return $this->country_code; } /** * Zip/postal code for the search * * @var string */ private $zipcode; public function setZipCode($value) { $this->zipcode = $value; return $this; } public function getZipCode() { return $this->zipcode; } /** * The total cost we will be checking the cart against * * @var Float */ private $cost = 0.0; public function setCost($value) { $this->cost = $value; return $this; } public function getCost() { return $this->cost; } /** * The total weight to check against * * @var Float */ private $weight = 0; public function setWeight($value) { $this->weight = $value; return $this; } public function getWeight() { return $this->weight; } /** * The total numbers of items to check against * * @var Float */ private $items = 0; public function setItems($value) { $this->items = $value; return $this; } public function getItems() { return $this->items; } /** * The total numbers of items to check against * * @var Float */ private $include_wildcards = true; public function setWildcards($value) { $this->include_wildcards = $value; return $this; } public function getWildcards() { return $this->include_wildcards; } /** * Simple constructor that sets the country code and zip. If no * country is set, this class attempts to autodetect. * * @param country_code 2 character country code * @param zipcode string of the zipo/postal code */ public function __construct($zipcode, $country_code = null) { if ($country_code) { $this->country_code = $country_code; } else { $locale = new Zend_Locale(); $locale->setLocale($this->locale()); $this->country_code = $locale->getRegion(); } if ($zipcode) { $this->zipcode = $zipcode; } } /** * Get the locale of the Member, or if we're not logged in or don't have a locale, use the default one * @return string */ protected function locale() { if (($member = Member::currentUser()) && $member->Locale) { return $member->Locale; } return i18n::get_locale(); } /** * Find relevent postage rates, based on supplied: * - Country * - Zip/postal code * - Weight * - Cost * - Number of Items * * This is returned as an ArrayList that can be looped through. * * @return ArrayList */ public function getPostageAreas() { $return = ArrayList::create(); $config = SiteConfig::current_site_config(); $cart = ShoppingCart::get(); $discount = $cart->getDiscount(); $filter_zipcode = strtolower(substr($this->zipcode, 0, 2)); if ($this->include_wildcards) { $filter = array( "Country:PartialMatch" => array($this->country_code, "*"), "ZipCode:PartialMatch" => array($filter_zipcode, "*") ); } else { $filter = array( "Country:PartialMatch" => $this->country_code, "ZipCode:PartialMatch" => $filter_zipcode ); } // Find any postage areas that match our filter $postage_areas = $config ->PostageAreas() ->filter($filter); // Check if any discounts are set with free postage // This is a little hacky at the moment, need to find a nicer // way to add free shipping. if ($discount && $discount->Type == "Free Shipping" && ((strpos($discount->Country, $this->country_code) !== false) || $discount->Country == "*")) { $postage = Checkout::CreateFreePostageObject(); $return->add($postage); } // Make sure we don't effect any associations foreach ($postage_areas as $item) { $return->add($item); } // Before doing anything else, remove any wildcards (if needed) $exact_country = false; // Find any countries that are exactly matched foreach ($return as $location) { if ($location->Country != "*") { $exact_country = true; } } // If exactly matched, remove any wildcards foreach ($return as $location) { if ($exact_country && $location->Country == "*" && $location->ID != -1) { $return->remove($location); } } // As above, we need to check for wildcards, this time for Zip Codes $exact_zip = false; // Find any zipcodes that are exactly matched foreach ($return as $location) { if ($location->ZipCode != "*") { $exact_zip = true; } } // If exactly matched, remove any wildcards foreach ($return as $location) { if ($exact_zip && $location->ZipCode == "*" && $location->ID != -1) { $return->remove($location); } } // Now we have a list of locations, start checking for additional // rules an remove if not applicable. $total_cost = $this->cost; $total_weight = $this->weight; $total_items = $this->items; $max_cost = 0; $max_weight = 0; $max_items = 0; // First loop through and find items that are invalid foreach ($return as $location) { if ($location->Calculation == "Price" && ($total_cost < $location->Unit)) { $return->remove($location); } if ($location->Calculation == "Weight" && ($total_weight < $location->Unit)) { $return->remove($location); } if ($location->Calculation == "Items" && ($total_items < $location->Unit)) { $return->remove($location); } } // Now find max values based on units foreach ($return as $location) { if ($location->Calculation == "Price" && ($location->Unit > $max_cost)) { $max_cost = $location->Unit; } if ($location->Calculation == "Weight" && ($location->Unit > $max_weight)) { $max_weight = $location->Unit; } if ($location->Calculation == "Items" && ($location->Unit > $max_items)) { $max_items = $location->Unit; } } // Now loop through again and calculate which brackets each // Location fits in foreach ($return as $location) { if ($location->Calculation == "Price" && ($location->Unit < $max_cost)) { $return->remove($location); } if ($location->Calculation == "Weight" && ($location->Unit < $max_weight)) { $return->remove($location); } if ($location->Calculation == "Items" && ($location->Unit < $max_items)) { $return->remove($location); } } return $return; } } |