diff --git a/Makefile b/Makefile index 56fe3dbf1395e241e050cf33ccea6009e30bfc0c..cbbb226bd8cdded5a113ecc5183c5fc1305aa81d 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ BASE=rules_shipping BASE_ADV=rules_shipping_advanced PLUGINTYPE=vmshipment -VERSION=1.0.0 +VERSION=1.1.0 PLUGINFILES=$(BASE).php $(BASE).script.php $(BASE).xml index.html PLUGINFILES_ADV=$(BASE_ADV).php $(BASE).php $(BASE_ADV).script.php $(BASE_ADV).xml index.html diff --git a/language/en-GB/en-GB.plg_vmshipment_rules_shipping.ini b/language/en-GB/en-GB.plg_vmshipment_rules_shipping.ini index 3b1af168c3e11f5f25dc7db58aaa17a3c006c1b4..6547cb73c12f00506c6091eee7a66e564eef80d4 100644 --- a/language/en-GB/en-GB.plg_vmshipment_rules_shipping.ini +++ b/language/en-GB/en-GB.plg_vmshipment_rules_shipping.ini @@ -14,7 +14,7 @@ VMSHIPMENT_RULES_HELP="<div style='background: #DDDDDD; padding:5px; margin:3px; <ul><li>Each line contains one rule consisting of several <b>conditions and assignments in arbitrary order and separated by semicolons</b>. </li> <li>The <b>first matching rule is used</b> to calculate the shipping costs.</li> <li>All rule parts with <b>comparison operators (<, <=, =<, ==, !=, <>, >=, =>, >)</b> are conditions.</li> -<li> Supported <b>variables (case-insensitive)</b>: <b><tt>Amount</tt></b>, <b><tt>Weight</tt></b>, <b><tt>ZIP</tt></b>, <b><tt>Products</tt></b> (number of different products order), <b><tt>Articles</tt></b> (each product counted with its quantity).</li> +<li> Supported <b>variables (case-insensitive)</b>: <b><tt>Amount</tt></b>, <b><tt>Weight</tt></b>, <b><tt>ZIP</tt></b>, <b><tt>Products</tt></b> (number of different products), <b><tt>Articles</tt></b> (counted with quantity), <b><tt>Volume</tt></b> (total volume of the order) and <b><tt>MinVolume</tt>, <tt>MinLength</tt>, <tt>MinWidth</tt>, <tt>MinHeight</tt></b> as well as the same variables with <tt>Max</tt> instead of <tt>Min</tt>.</li> <li>A condition can consist of multiple chained comparisons.</li> <li>All rule parts of the form <b><tt>[VARIABLE]=VALUE</tt> are assignments</b>, with <tt>[VARIABLE]</tt> being one of <b><tt>Name</tt></b> (optional name of the rule, displayed in the cart and invoice), <b><tt>Shipping</tt></b> (shipping cost if the rule matches). The <tt>Shipping=</tt> can be left out. I.e. a rule part consisting only of a numerical value is understood as shipping cost.</li> </ul> @@ -24,7 +24,7 @@ VMSHIPMENT_RULES_HELP_ADV="<div style='background: #DDDDDD; padding:5px; margin: <ul><li>Each line contains one rule consisting of several <b>conditions and assignments in arbitrary order and separated by semicolons</b>. </li> <li>The <b>first matching rule is used</b> to calculate the shipping costs.</li> <li>All rule parts with <b>comparison operators (<, <=, =<, ==, !=, <>, >=, =>, >)</b> are conditions.</li> -<li> Supported <b>variables (case-insensitive)</b>: <b><tt>Amount</tt></b>, <b><tt>Weight</tt></b>, <b><tt>ZIP</tt></b>, <b><tt>Products</tt></b> (number of different products order), <b><tt>Articles</tt></b> (each product counted with its quantity).</li> +<li> Supported <b>variables (case-insensitive)</b>: <b><tt>Amount</tt></b>, <b><tt>Weight</tt></b>, <b><tt>ZIP</tt></b>, <b><tt>Products</tt></b> (number of different products), <b><tt>Articles</tt></b> (counted with quantity), <b><tt>Volume</tt></b> (total volume of the order) and <b><tt>MinVolume</tt>, <tt>MinLength</tt>, <tt>MinWidth</tt>, <tt>MinHeight</tt></b> as well as the same variables with <tt>Max</tt> instead of <tt>Min</tt>.</li> <li>A condition can consist of multiple chained comparisons.</li> <li>All rule parts of the form <b><tt>[VARIABLE]=VALUE</tt> are assignments</b>, with <tt>[VARIABLE]</tt> being one of <b><tt>Name</tt></b> (optional name of the rule, displayed in the cart and invoice), <b><tt>Shipping</tt></b> (shipping cost if the rule matches). The <tt>Shipping=</tt> can be left out. I.e. a rule part consisting only of a numerical value is understood as shipping cost.</li> <li>In the advanced version, all expressions (conditions and shipping costs) may contain <b>arbitrary basic arithmetic expressions (+, -, *, /, %, ^ and parentheses)</b> of the above variables.</li> diff --git a/releases/plg_vmshipment_rules_shipping_advanced_v1.1.0.zip b/releases/plg_vmshipment_rules_shipping_advanced_v1.1.0.zip new file mode 100644 index 0000000000000000000000000000000000000000..71c2698fe8ca2c5d4845c37e5e472481a0c1a01b Binary files /dev/null and b/releases/plg_vmshipment_rules_shipping_advanced_v1.1.0.zip differ diff --git a/releases/plg_vmshipment_rules_shipping_v1.1.0.zip b/releases/plg_vmshipment_rules_shipping_v1.1.0.zip new file mode 100644 index 0000000000000000000000000000000000000000..97ee94ce54995548e32170d87491efefb4ec0be4 Binary files /dev/null and b/releases/plg_vmshipment_rules_shipping_v1.1.0.zip differ diff --git a/rules_shipping.php b/rules_shipping.php index 360c56953af62ce1256b079d9eef67528f94d561..e11f970a1635f5699415791212423832bdff06ef 100644 --- a/rules_shipping.php +++ b/rules_shipping.php @@ -218,14 +218,8 @@ class plgVmShipmentRules_Shipping extends vmPSPlugin { */ function getCosts (VirtueMartCart $cart, $method, $cart_prices) { if (empty($method->rules)) $this->parseMethodRules($method); + $cartvals = $this->getCartValues ($cart, $cart_prices); - $address = (($cart->ST == 0) ? $cart->BT : $cart->ST); - $cartvals = array('weight' => $this->getOrderWeight ($cart, $method->weight_unit), - 'zip' => $address['zip'], - 'articles' => $this->getOrderArticles ($cart), - 'products' => $this->getOrderProducts ($cart), - 'amount' => $cart_prices['salesPrice'], - 'country' => $address['virtuemart_country_id']); foreach ($method->rules as $r) { if ($r->matches($cartvals)) { $method->tax_id = $r->tax_id; @@ -276,6 +270,35 @@ class plgVmShipmentRules_Shipping extends vmPSPlugin { return $articles; } + protected function getOrderDimensions (VirtueMartCart $cart) { + /* Cache the value in a static variable and calculate it only once! */ + static $calculated = 0; + static $dimensions=array( + 'volume' => 0, + 'maxvolume' => 0, 'minvolume' => 9999999999, + 'maxlength' => 0, 'minlength' => 9999999999, + 'maxwidth' => 0, 'minwidth' => 9999999999, + 'maxheight' => 0, 'minheight' => 9999999999, + ); + if ($calculated==0) { + $calculated=1; + foreach ($cart->products as $product) { + $volume = $product->product_length * $product->product_width * $product->product_height; + $dimensions['volume'] += $volume * $product->quantity; + $dimensions['maxvolume'] = max ($dimensions['maxvolume'], $volume); + $dimensions['minvolume'] = min ($dimensions['minvolume'], $volume); + $dimensions['maxlength'] = max ($dimensions['maxlength'], $product->product_length); + $dimensions['minlength'] = min ($dimensions['minlength'], $product->product_length); + $dimensions['maxwidth'] = max ($dimensions['maxwidth'], $product->product_width); + $dimensions['minwidth'] = min ($dimensions['minwidth'], $product->product_width); + $dimensions['maxheight'] = max ($dimensions['maxheight'], $product->product_height); + $dimensions['minheight'] = min ($dimensions['minheight'], $product->product_height); + $articles += $product->quantity; + } + } + return $dimensions; + } + protected function getOrderProducts (VirtueMartCart $cart) { /* Cache the value in a static variable and calculate it only once! */ static $products = 0; @@ -284,18 +307,10 @@ class plgVmShipmentRules_Shipping extends vmPSPlugin { } return $products; } - - - /** - * @param \VirtueMartCart $cart - * @param int $method - * @param array $cart_prices - * @return bool - */ - protected function checkConditions ($cart, $method, $cart_prices) { - if (empty($method->rules)) $this->parseMethodRules($method); - + + protected function getCartValues (VirtueMartCart $cart, $cart_prices) { $orderWeight = $this->getOrderWeight ($cart, $method->weight_unit); + $dimensions = $this->getOrderDimensions ($cart); $address = (($cart->ST == 0) ? $cart->BT : $cart->ST); $products = 0; @@ -304,13 +319,36 @@ class plgVmShipmentRules_Shipping extends vmPSPlugin { $products += 1; $articles += $product->quantity; } - $cartvals = array('weight'=>$orderWeight, 'zip'=>$address['zip'], 'articles'=>$articles, 'products'=>$products, 'amount'=>$cart_prices['salesPrice'], - 'country'=>$address['virtuemart_country_id']); + 'country'=>$address['virtuemart_country_id'], + 'volume' => $dimensions['volume'], + 'maxvolume' => $dimensions['maxvolume'], + 'minvolume' => $dimensions['minvolume'], + 'maxlength' => $dimensions['maxlength'], + 'minlength' => $dimensions['minlength'], + 'maxwidth' => $dimensions['maxwidth'], + 'minwidth' => $dimensions['minwidth'], + 'maxheight' => $dimensions['maxheight'], + 'minheight' => $dimensions['minheight'] + ); + return $cartvals; + } + + + /** + * @param \VirtueMartCart $cart + * @param int $method + * @param array $cart_prices + * @return bool + */ + protected function checkConditions ($cart, $method, $cart_prices) { + if (empty($method->rules)) $this->parseMethodRules($method); + + $cartvals = $this->getCartValues ($cart, $cart_prices); foreach ($method->rules as $r) { if ($r->matches($cartvals)) { $method->matched_rule = $r; @@ -438,8 +476,9 @@ class ShippingRule { var $rulestring = ''; var $countries = array(); var $tax_id = 0; - var $conditions=array(); - var $shipping=0; + var $conditions = array(); + var $shipping = 0; + var $shippingWithTax = 0; var $name = ''; function __construct ($rule, $countries, $tax_id) { @@ -453,6 +492,14 @@ class ShippingRule { $this->parseRule($rule); } + function handleAssignment ($variable, $value, $rulepart) { + switch ($variable) { + case 'shipping': $this->shipping = $this->parseShippingTerm($value); break; + case 'shippingwithtax': $this->shippingWithTax = $this->parseShippingTerm($value); break; + case 'name': $this->name = $value; break; + default: JFactory::getApplication()->enqueueMessage(JText::sprintf('VMSHIPMENT_RULES_UNKNOWN_VARIABLE', $variable, $rulepart), 'error'); + } + } function parseRule($rule) { $ruleparts=explode(';', $rule); $operators = array('<', '<=', '=', '>', '>=', '=>', '=<', '<>', '!=', '=='); @@ -464,11 +511,7 @@ class ShippingRule { if (count($atoms)==1) { $this->shipping = $this->parseShippingTerm($atoms[0]); } elseif ($atoms[1]=='=') { - switch (strtolower($atoms[0])) { - case 'shipping': $this->shipping = $this->parseShippingTerm($atoms[2]); break; - case 'name': $this->name = $atoms[2]; break; - default: JFactory::getApplication()->enqueueMessage(JText::sprintf('VMSHIPMENT_RULES_UNKNOWN_VARIABLE', $atoms[0], $p), 'error'); - } + $this->handleAssignment (strtolower($atoms[0]), $atoms[2], $p); } else { // Conditions, need at least three atoms! while (count($atoms)>1) { diff --git a/rules_shipping.xml b/rules_shipping.xml index 35e14344ae3f42f9ebb626186828788a5111afea..a1805d4165b84d1a1da75fc1ae24db1d575c44bf 100644 --- a/rules_shipping.xml +++ b/rules_shipping.xml @@ -6,7 +6,7 @@ <authorUrl>http://www.kainhofer.com</authorUrl> <copyright>Copyright (C) 2013, Reinhold Kainhofer</copyright> <license>GPL v3+</license> - <version>1.0.0</version> + <version>1.1.0</version> <description>VMSHIPMENT_RULES_DESC</description> <files> <filename plugin="rules_shipping">rules_shipping.php</filename> diff --git a/rules_shipping_advanced.xml b/rules_shipping_advanced.xml index 3718b56354b752e7667a09c81f7bd5eaa64d3e5c..71fe47561f2019c9736cb971e6cdfd253518688e 100644 --- a/rules_shipping_advanced.xml +++ b/rules_shipping_advanced.xml @@ -6,7 +6,7 @@ <authorUrl>http://www.kainhofer.com</authorUrl> <copyright>Copyright (C) 2013, Reinhold Kainhofer</copyright> <license>GPL v3+</license> - <version>1.0.0</version> + <version>1.1.0</version> <description>VMSHIPMENT_RULES_ADV_DESC</description> <files> <filename plugin="rules_shipping_advanced">rules_shipping_advanced.php</filename>