Commit 3fb3ca68 authored by Reinhold Kainhofer's avatar Reinhold Kainhofer
Browse files

V5.99.1: Some more library refactoring, merging in changed from the WC...

V5.99.1: Some more library refactoring, merging in changed from the WC shipping by rules plugin (getCosts returns array with further information, possibly multiple rates, etc.)
parent 507d206a
......@@ -2,7 +2,7 @@ BASE=rules_shipping
BASE_ADV=rules_shipping_advanced
PLUGINTYPE=vmshipment
ZIPBASE=opentools_vm
VERSION=5.99
VERSION=5.99.1
PLUGINFILES=$(BASE).php $(BASE)_base.php $(BASE)_framework_joomla.php $(BASE).script.php $(BASE).xml index.html
PLUGINFILES_ADV=$(BASE_ADV).php $(BASE)_base.php $(BASE)_framework_joomla.php $(BASE_ADV).script.php $(BASE_ADV).xml index.html
......
<?php
defined ('_JEXEC') or die('Restricted access');
if ( !defined( 'ABSPATH' ) && !defined('_JEXEC') ) {
die( 'Direct Access to ' . basename( __FILE__ ) . ' is not allowed.' );
}
/**
* Shipping By Rules Framework for general, rules-based shipments, like regular postal services with complex shipping cost structures
......@@ -217,6 +219,27 @@ class RulesShippingFramework {
'maxquantity' => 0,
);
}
protected function getDateTimeVariables($cart, $products, $method) {
$utime = microtime(true);
$milliseconds = (int)(1000*($utime - (int)$utime));
$millisecondsstring = sprintf('%03d', $milliseconds);
return array(
'year' => date("Y", $utime),
'year2' => date("y", $utime),
'month' => date("m", $utime),
'day' => date("d", $utime),
'weekday' => date("N", $utime),
'hour' => date("H", $utime),
'hour12' => date("h", $utime),
'ampm' => date("a", $utime),
'minute' => date("i", $utime),
'second' => date("s", $utime),
'decisecond' => $millisecondsstring[0],
'centisecond' => substr($millisecondsstring, 0, 2),
'millisecond' => $millisecondsstring,
);
}
protected function getOrderDimensions ($cart, $products, $method) {
return array();
......@@ -237,6 +260,46 @@ class RulesShippingFramework {
protected function getOrderPrices ($cart, $products, $method) {
return array();
}
/**
* Extract information about non-numerical zip codes (UK and Canada) from the postal code
*/
protected function getAddressZIP ($zip) {
$values = array();
// Postal code Check for UK postal codes: Use regexp to determine if ZIP structure matches and also to extract the parts.
// Also handle UK overseas areas/islands that use four-letter outward codes rather than "A{1,2}0{1,2}A{0,1} 0AA"
$zip=strtoupper($zip);
if (isset($zip) and preg_match('/^\s*(([A-Z]{1,2})(\d{1,2})([A-Z]?)|[A-Z]{4}|GIR)\s*(\d[A-Z]{2})\s*$/', $zip, $match)) {
$values['uk_outward'] = $match[1];
$values['uk_area'] = $match[2];
$values['uk_district'] = $match[3];
$values['uk_subdistrict'] = $match[4];
$values['uk_inward'] = $match[5];
} else {
$values['uk_outward'] = NULL;
$values['uk_area'] = NULL;
$values['uk_district'] = NULL;
$values['uk_subdistrict'] = NULL;
$values['uk_inward'] = NULL;
}
// Postal code Check for Canadian postal codes: Use regexp to determine if ZIP structure matches and also to extract the parts.
if (isset($zip) and preg_match('/^\s*(([A-Za-z])(\d)([A-Za-z]))\s*(\d[A-Za-z]\d)\s*$/', $zip, $match)) {
$values['canada_fsa'] = $match[1];
$values['canada_area'] = $match[2];
$values['canada_urban'] = $match[3];
$values['canada_subarea'] = $match[4];
$values['canada_ldu'] = $match[5];
} else {
$values['canada_fsa'] = NULL;
$values['canada_area'] = NULL;
$values['canada_urban'] = NULL;
$values['canada_subarea'] = NULL;
$values['canada_ldu'] = NULL;
}
// print("<pre>values: ".print_r($values,1)."</pre>");
return $values;
}
/** Allow child classes to add additional variables for the rules or modify existing one
*/
......@@ -250,6 +313,7 @@ class RulesShippingFramework {
public function getCartValues ($cart, $products, $method) {
$cartvals = array_merge (
$this->getDateTimeVariables($cart, $products, $method),
$this->getOrderCounts($cart, $products, $method),
// Add the prices, optionally calculated from the products subset of the cart
$this->getOrderPrices ($cart, $products, $method),
......@@ -296,31 +360,33 @@ class RulesShippingFramework {
$cartvals_callback = function ($products) use ($this_class, $cart, $method) {
return $this_class->getCartValues ($cart, $products, $method, NULL);
};
foreach ($this->rules[$id] as $r) {
if ($r->matches($cartvals, $cart->products, $cartvals_callback)) {
$rtype = $r->getType();
switch ($rtype) {
case 'shipping':
case 'shippingwithtax':
case 'noshipping':
$result["rule"] = $r;
$result["rule_name"] = $r->getRuleName();
break;
case 'modifiers_add':
case 'modifiers_multiply':
$result[$rtype][] = $r;
break;
case 'definition': // A definition updates the $cartvals, but has no other effects
$cartvals[strtolower($r->getRuleName())] = $r->getValue();
break;
default:
$this->warning('OTSHIPMENT_RULES_UNKNOWN_TYPE', $r->getType(), $r->rulestring);
break;
if (isset($this->rules[$id])) {
foreach ($this->rules[$id] as $r) {
if ($r->matches($cartvals, $this->getCartProducts($cart, $method), $cartvals_callback)) {
$rtype = $r->getType();
switch ($rtype) {
case 'shipping':
case 'shippingwithtax':
case 'noshipping':
$result["rule"] = $r;
$result["rule_name"] = $r->getRuleName();
break;
case 'modifiers_add':
case 'modifiers_multiply':
$result[$rtype][] = $r;
break;
case 'definition': // A definition updates the $cartvals, but has no other effects
$cartvals[strtolower($r->getRuleName())] = $r->getValue();
break;
default:
$this->warning('OTSHIPMENT_RULES_UNKNOWN_TYPE', $r->getType(), $r->rulestring);
break;
}
}
if (!is_null($result["rule"])) {
$this->match[$id] = $result;
return $result; // <- This also breaks out of the foreach loop!
}
}
if (!is_null($result["rule"])) {
$this->match[$id] = $result;
return $result; // <- This also breaks out of the foreach loop!
}
}
}
......@@ -329,6 +395,18 @@ class RulesShippingFramework {
return NULL;
}
protected function handleNoShipping($match, $method) {
if ($match['rule']->isNoShipping()) {
if (!empty($match["rule_name"]))
$this->warning('OTSHIPMENT_RULES_NOSHIPPING_MESSAGE', $match["rule_name"]);
$name = $this->getMethodName($method);
$this->debug('checkConditions '.$name.' indicates NoShipping for this method, specified by rule "'.$match["rule_name"].'" ('.$match['rule']->rulestring.').');
return true;
} else {
return false;
}
}
/**
* @param $cart
* @param int $method
......@@ -339,19 +417,16 @@ class RulesShippingFramework {
$name = $this->getMethodName($method);
if (!isset($this->rules[$id]))
$this->parseMethodRules($method);
// TODO: This needs to be redone sooner or later!
$match = $this->evaluateMethodRules ($cart, $method);
if ($match && !is_null ($match['rule'])) {
$this->setMethodCosts($method, $match, null);
// If NoShipping is set, this method should NOT offer any shipping at all, so return FALSE, otherwise TRUE
// If the rule has a name, print it as warning (otherwise don't print anything)
if ($match['rule']->isNoShipping()) {
if (!empty($match["rule_name"]))
$this->warning('OTSHIPMENT_RULES_NOSHIPPING_MESSAGE', $match["rule_name"]);
$this->debug('checkConditions '.$name.' indicates NoShipping for this method, specified by rule "'.$match["rule_name"].'" ('.$match['rule']->rulestring.').');
if ($this->handleNoShipping($match, $method)) {
return FALSE;
} else {
return TRUE;
}
return TRUE;
}
$this->debug('checkConditions '.$name.' does not fulfill all conditions, no rule matches');
return FALSE;
......@@ -370,11 +445,16 @@ class RulesShippingFramework {
* @return int
*/
function getCosts ($cart, $method) {
$results = array();
$id = $this->getMethodId($method);
if (!isset($this->rules[$id]))
$this->parseMethodRules($method);
$match = $this->evaluateMethodRules ($cart, $method);
if ($match) {
if ($this->handleNoShipping($match, $method)) {
return $results;
}
$r = $match["rule"];
$this->debug('Rule ' . $match["rule_name"] . ' ('.$r->rulestring.') matched.');
......@@ -390,11 +470,20 @@ class RulesShippingFramework {
}
$this->setMethodCosts($method, $match, $cost);
return $cost;
$res = array(
'method' => $id,
'name' => $this->getMethodName($method),
// 'rulesetname'=>$match['ruleset_name'],
'rulename' => $match["rule_name"],
'cost' => $cost,
);
$results[] = $res;
}
$this->debug('getCosts '.$this->getMethodName($method).' does not return shipping costs');
return 0;
if (empty($results)) {
$this->debug('getCosts '.$this->getMethodName($method).' does not return shipping costs');
}
return $results;
}
public function getRuleName($methodid) {
......@@ -676,6 +765,7 @@ class ShippingRule {
if (count($conditionvals)<1)
return $this->evaluateTerm($expr, $vals, $products, $cartvals_callback);
// TODO: Make this more general!
$filterkeys = array(
"evaluate_for_categories" => 'categories',
"evaluate_for_products" => 'skus',
......
......@@ -6,7 +6,7 @@
<authorUrl>http://www.open-tools.net</authorUrl>
<copyright>Copyright (C) 2013-2014, Reinhold Kainhofer</copyright>
<license>GPL v3+</license>
<version>5.99</version>
<version>5.99.1</version>
<description>OTSHIPMENT_RULES_DESC</description>
<files>
<filename plugin="rules_shipping">rules_shipping.php</filename>
......
......@@ -6,7 +6,7 @@
<authorUrl>http://www.open-tools.net</authorUrl>
<copyright>Copyright (C) 2013-2014, Reinhold Kainhofer</copyright>
<license>GPL v3+</license>
<version>5.99</version>
<version>5.99.1</version>
<description>OTSHIPMENT_RULES_ADV_DESC</description>
<files>
<filename plugin="rules_shipping_advanced">rules_shipping_advanced.php</filename>
......
......@@ -120,7 +120,10 @@ class plgVmShipmentRules_Shipping_Base extends vmPSPlugin {
// We need to call getCosts, because in J3 $method->rule_name and $method->cost as set in getCosts is no longer preserved.
// Instead, we simply call getCosts again, which as a side-effect sets all those members of $method.
$costs = $this->helper->getCosts($cart,$method);
$rulename = $this->helper->getRuleName($method->virtuemart_shipmentmethod_id);
if (empty($costs))
return FALSE;
$rulename = $costs[0]['rulename'];
// $rulename = $this->helper->getRuleName($method->virtuemart_shipmentmethod_id);
$variables = $this->helper->getRuleVariables($method->virtuemart_shipmentmethod_id);
$values['virtuemart_order_id'] = $order['details']['BT']->virtuemart_order_id;
$values['order_number'] = $order['details']['BT']->order_number;
......@@ -138,7 +141,12 @@ class plgVmShipmentRules_Shipping_Base extends vmPSPlugin {
return TRUE;
}
function getCosts (VirtueMartCart $cart, $method, $cart_prices) {
return $this->helper->getCosts($cart, $method, $cart_prices);
$costs = $this->helper->getCosts($cart, $method, $cart_prices);
if (empty($costs)) {
return false;
} else {
return $costs[0]['cost'];
}
}
protected function checkConditions ($cart, $method, $cart_prices) {
return $this->helper->checkConditions($cart, $method, $cart_prices);
......
......@@ -102,10 +102,11 @@ class RulesShippingFrameworkJoomla extends RulesShippingFramework {
$counts = array(
'articles' => 0,
'products' => count($products),
'quantity' => 0,
'minquantity' => 9999999999,
'maxquantity' => 0,
);
foreach ($products as $product) {
$counts['articles'] += $product->quantity;
$counts['maxquantity'] = max ($counts['maxquantity'], $product->quantity);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment