diff --git a/Makefile b/Makefile index f11c60075ebbdb4d6a26e43de0651e0cd69ab5e0..f5a38f7d175bd01f46a0e06f83fa2614e5fc9a77 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ BASE=rules_shipping BASE_ADV=rules_shipping_advanced PLUGINTYPE=vmshipment -VERSION=2.1.3 +VERSION=2.2.0 PLUGINFILES=$(BASE).php $(BASE)_base.php $(BASE).script.php $(BASE).xml index.html PLUGINFILES_ADV=$(BASE_ADV).php $(BASE)_base.php $(BASE_ADV).script.php $(BASE_ADV).xml index.html diff --git a/elements/vmlengthunit.php b/elements/vmlengthunit.php new file mode 100644 index 0000000000000000000000000000000000000000..b3186022ce52f315e10ea8618054547da60d5ae9 --- /dev/null +++ b/elements/vmlengthunit.php @@ -0,0 +1,64 @@ +<?php +defined('_JEXEC') or die(); +/** + * + * @package VirtueMart + * @subpackage Plugins - Elements + * @author Valérie Isaksen, Reinhold Kainhofer + * @link http://www.virtuemart.net + * @copyright Copyright (c) 2004 - 2011 VirtueMart Team. All rights reserved. + * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL, see LICENSE.php + * VirtueMart is free software. This version may have been modified pursuant + * to the GNU General Public License, and as distributed it includes or + * is derivative of works licensed under the GNU General Public License or + * other free or open source software licenses. + * @version $Id: $ + */ +/* + * This class is used by VirtueMart Payment or Shipment Plugins + * which uses JParameter + * So It should be an extension of JElement + * Those plugins cannot be configured througth the Plugin Manager anyway. + */ + + +// print "<h3>vmlengthunit.php LOADING</h3>"; + +if (!class_exists('VmConfig')) + require(JPATH_ROOT . DS . 'administrator' . DS . 'components' . DS . 'com_virtuemart' . DS . 'helpers' . DS . 'config.php'); + +if (!class_exists('ShopFunctions')) + require(JPATH_VM_ADMINISTRATOR . DS . 'helpers' . DS . 'shopfunctions.php'); + +class JElementVmLengthUnit extends JElement { + + /** + * Element name + * @access protected + * @var string + */ + var $_name = 'LengthUnit'; + + function fetchElement($nm, $value, &$node, $control_name) { + // For now, this is a modified copy of ShopFunctions::renderLWHUnitList to use JHTML::_ instead of VmHTML + // (which would NOT remove the [ and ] from the ID and thus break the javascript magic!) + if (!class_exists ('VmHTML')) { + require(JPATH_VM_ADMINISTRATOR . DS . 'helpers' . DS . 'html.php'); + } + $name = $control_name . '[' . $nm . ']'; + + $lwh_unit_default = array('M' => JText::_ ('COM_VIRTUEMART_UNIT_NAME_M') + , 'CM' => JText::_ ('COM_VIRTUEMART_UNIT_NAME_CM') + , 'MM' => JText::_ ('COM_VIRTUEMART_UNIT_NAME_MM') + , 'YD' => JText::_ ('COM_VIRTUEMART_UNIT_NAME_YARD') + , 'FT' => JText::_ ('COM_VIRTUEMART_UNIT_NAME_FOOT') + , 'IN' => JText::_ ('COM_VIRTUEMART_UNIT_NAME_INCH') + ); + foreach ($lwh_unit_default as $key => $value) { + $lu_list[] = JHTML::_ ('select.option', $key, $value, $name); + } + $listHTML = JHTML::_ ('Select.genericlist', $lu_list, $name, '', $name, 'text', $selected); + return $listHTML; + } + +} \ No newline at end of file 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 62e7d12bc2ce8e8b380e0dcaf884f5f744e5f3b6..ae6f35a7200531138b1dc0568c0db19588b09535 100644 --- a/language/en-GB/en-GB.plg_vmshipment_rules_shipping.ini +++ b/language/en-GB/en-GB.plg_vmshipment_rules_shipping.ini @@ -13,6 +13,9 @@ VMSHIPMENT_RULES_PLUGIN_ADV="<b>Shipment based on general rules (weight, product VMSHIPMENT_RULES_HELP="<div style='background: #DDDDDD; padding:5px; margin:3px;'><h2>Overview of the Rules Syntax</h2><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), <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 without tax if the rule matches) and <b><tt>ShippingWithTax</tt></b> (shipping cost including taxes if the rule matches). The <tt>Shipping=</tt> can be left out (<tt>ShippingWithTax=</tt> can not be left out). I.e. a rule part consisting only of a numerical value is understood as net shipping cost without tax.</li></ul><p>EXAMPLE: A rule named "Europe" that sets shipping costs of 4.50 for order amounts from 50 to less than 100, and free shipping from 100€ on would be:</p><blockquote><tt>Name=Europe; 50<=Amount<100; Shipping=4.50<br>Name=Free Shipping; 100<= Amount; 0</tt></blockquote></div>" VMSHIPMENT_RULES_HELP_ADV="<div style='background: #DDDDDD; padding:5px; margin:3px;'><h2>Overview of the Rules Syntax</h2><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), <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 without tax if the rule matches) and <b><tt>ShippingWithTax</tt></b> (shipping cost including taxes if the rule matches). The <tt>Shipping=</tt> can be left out (<tt>ShippingWithTax=</tt> can not be left out). I.e. a rule part consisting only of a numerical value is understood as net shipping cost without tax.</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></ul><p>EXAMPLE: A rule named "Europe" that sets shipping costs of 5€ plus 1.50€ per article for order amounts from 50 to less than 100, and free shipping from 100€ on would be:</p><blockquote><tt>Name=Europe; 50<=Amount<100; Shipping=5+1.50*Articles<br>Name=Free Shipping; 100<= Amount; 0</blockquote></div>" +VMSHIPMENT_RULES_LENGTH_UNIT="Length Unit" +VMSHIPMENT_RULES_LENGTH_UNIT_DESC="The length unit, in which the length, width and heights are given, and from which the volume is calculated." + VMSHIPMENT_RULES_COUNTRIES1_LABEL="<b>Rules for country set 1</b>" VMSHIPMENT_RULES_COUNTRIES2_LABEL="<b>Rules for country set 2</b>" VMSHIPMENT_RULES_COUNTRIES3_LABEL="<b>Rules for country set 3</b>" diff --git a/releases/plg_vmshipment_rules_shipping_advanced_v2.2.0.zip b/releases/plg_vmshipment_rules_shipping_advanced_v2.2.0.zip new file mode 100644 index 0000000000000000000000000000000000000000..778fdd8a4396cfc9269debc3b8a7c5b540263f6d Binary files /dev/null and b/releases/plg_vmshipment_rules_shipping_advanced_v2.2.0.zip differ diff --git a/releases/plg_vmshipment_rules_shipping_v2.2.0.zip b/releases/plg_vmshipment_rules_shipping_v2.2.0.zip new file mode 100644 index 0000000000000000000000000000000000000000..063e5a859c48623291dd1bb79b9d9b494c5b896c Binary files /dev/null and b/releases/plg_vmshipment_rules_shipping_v2.2.0.zip differ diff --git a/rules_shipping.xml b/rules_shipping.xml index 811fa857896e2e77c5ed6d63c330fdc385d42f03..562531558ee2d3898803600757a3a152a66b9c41 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>2.1.3</version> + <version>2.2.0</version> <description>VMSHIPMENT_RULES_DESC</description> <files> <filename plugin="rules_shipping">rules_shipping.php</filename> @@ -21,9 +21,12 @@ <scriptfile>rules_shipping.script.php</scriptfile> - <params addpath="/administrator/components/com_virtuemart/elements"/> - <params addpath="/plugins/vmshipment/rules_shipping_advanced/elements/"> + <params addpath="/administrator/components/com_virtuemart/elements" /> + <params addpath="/plugins/vmshipment/rules_shipping/rules_shipping/elements" /> + <params addpath="/plugins/vmshipment/rules_shipping/elements" /> + + <params> <param type="vmjpluginwarning" /> <param type="spacer" default='VMSHIPMENT_RULES_PLUGIN' level="level1" /> <param name="shipment_logos" type="vmfiles" label="VMSHIPMENT_WEIGHT_COUNTRIES_LOGOS" @@ -32,6 +35,7 @@ default="default" hide_default="1" hide_none="1" stripext="0" exclude="^_" /> <param name="weight_unit" type="vmweightunit" size="10" default="" label="VMSHIPMENT_WEIGHT_COUNTRIES_WEIGHT_UNIT" description="VMSHIPMENT_WEIGHT_COUNTRIES_WEIGHT_UNIT_DESC"/> + <param name="length_unit" type="vmlengthunit" size="10" default="" label="VMSHIPMENT_RULES_LENGTH_UNIT" description="VMSHIPMENT_RULES_LENGTH_UNIT_DESC"/> <param type="rklabel" default='VMSHIPMENT_RULES_HELP' /> diff --git a/rules_shipping_advanced.php b/rules_shipping_advanced.php index 6d00afa3bba3156b5cec26b161660d8577498482..14dd0e710ebda21b5e3eb6ee753fffe58db4a962 100644 --- a/rules_shipping_advanced.php +++ b/rules_shipping_advanced.php @@ -48,20 +48,6 @@ class plgVmShipmentRules_Shipping_Advanced extends plgVmShipmentRules_Shipping_B } -// is_comparison: if the expression $o is a (possibly chained) comparison consisting of operators in $ops, -// return the last term of hte comparison; null otherwise -function is_comparison ($o, $ops) { - if (!is_array($o)) - return null; - if (in_array($o[0], $ops)) - return $o[2]; - $o2comp = is_comparison($o[2], $ops); - if (trim($o[0])=='AND' && !is_null (is_comparison($o[1], $ops)) && !is_null($o2comp)) - return $o2comp; - return null; -} - - /** Extend the shipping rules by allowing arbitrary mathematical expressions */ class ShippingRule_Advanced extends ShippingRule { @@ -70,7 +56,7 @@ class ShippingRule_Advanced extends ShippingRule { "*" => 60, "/" => 60, "%" => 60, "+" => 50, "-" => 50, "<" => 40, "<=" => 40, ">" => 40, ">=" => 40, "=>" => 40, "=<" => 40, - "==" => 40, "!=" => 40, "<>" => 40, + "==" => 40, "!=" => 40, "<>" => 40, "~" => 40, "&&" => 21, " AND " => 21, "AND" => 21, " OR " => 20, "OR" => 20, "=" => 10, @@ -86,7 +72,7 @@ class ShippingRule_Advanced extends ShippingRule { $str_re = '/("(?:\\"|[^"])*"|\'(?:\\\'|[^\'])*\')/'; $strings = preg_split($str_re, $expression, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY); // Then split all other parts of the expression at the operators - $op_re = ':\s*( OR |&&| AND |<=|=>|>=|=>|<>|!=|==|<|=|>|\+|-|\*|/|%|\(|\)|\^)\s*:'; + $op_re = ':\s*( OR |&&| AND |<=|=>|>=|=>|<>|!=|==|<|=|>|~|\+|-|\*|/|%|\(|\)|\^)\s*:'; $atoms = array(); foreach ($strings as $s) { if (preg_match($str_re, $s)) { @@ -155,8 +141,9 @@ class ShippingRule_Advanced extends ShippingRule { $atoms = $this->tokenize_expression ($rulepart); // Any of these indicate a comparison and thus a condition: - $comparison_ops = array('<', '<=', '=<', '<>', '!=', '==', '>', '>=', '=>', ' OR ', 'OR', 'AND', ' AND ', '&&'); - $is_comparison = false; + $condition_ops = array('<', '<=', '=<', '<>', '!=', '==', '>', '>=', '=>', '~', ' OR ', 'OR', 'AND', ' AND ', '&&'); + $comparison_ops = array('<', '<=', '=<', '<>', '!=', '==', '>', '>=', '=>', '~'); + $is_condition = false; $is_assignment = false; if (count($atoms)==1) return $atoms[0]; @@ -185,7 +172,7 @@ class ShippingRule_Advanced extends ShippingRule { // For operators, pop operators from the stack until you reach an opening parenthesis, // an operator of lower precedence, or a right associative symbol of equal precedence. $prec = $this->operators[$a]; - $is_comparison |= in_array($a, $comparison_ops); + $is_condition |= in_array($a, $condition_ops); $is_assignment |= ($a == "="); while (count($stack)>0) { // 4a) @@ -243,12 +230,16 @@ class ShippingRule_Advanced extends ShippingRule { } $o2 = array_pop($stack); // 4a) $o1 = array_pop($stack); - // TODO: Special-case chained comparisons: if e is a comparison, and operator(o1) is also a comparison, - // insert AND(o1, e(arg2(o1), o2)) instead of e(o1, o1) - // is_comparison nicely returns the last term of the (possibly chained) comparison, null otherwise - $o1comp = is_comparison($o1, $comparison_ops); - if (in_array ($e, $comparison_ops) && !is_null($o1comp) ) { - $op = array ('AND', $o1, array($e, $o1comp, $o2)); + // Special-case chained comparisons: if e is a comparison, and operator(o1) is also a comparison, + // insert the arguments to the existing comparison instead of creating a new one + if (in_array ($e, $comparison_ops)) { + if ($o1[0]=='comparison') { + $op = $o1; + // Append the new comparison to the existing one + array_push($op, $e, $o2); + } else { + $op = array ('comparison', $o1, $e, $o2); + } } else { $op = array ($e, $o1, $o2); // 4b) } @@ -262,7 +253,7 @@ class ShippingRule_Advanced extends ShippingRule { } $res = array_pop($stack); // 5) - if ($is_comparison) { // Comparisons are conditions + if ($is_condition) { // Comparisons are conditions $this->conditions[] = $res; } elseif ($is_assignment) { diff --git a/rules_shipping_advanced.xml b/rules_shipping_advanced.xml index 49db8619a67946a37d0fb01b6045ac3f1e1e11ac..ca9a10d486e872675039d073a040181ab7b58a89 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>2.1.3</version> + <version>2.2.0</version> <description>VMSHIPMENT_RULES_ADV_DESC</description> <files> <filename plugin="rules_shipping_advanced">rules_shipping_advanced.php</filename> @@ -21,9 +21,11 @@ <scriptfile>rules_shipping_advanced.script.php</scriptfile> - <params addpath="/plugins/vmshipment/rules_shipping_advanced/elements/" /> + <params addpath="/administrator/components/com_virtuemart/elements" /> + <params addpath="/plugins/vmshipment/rules_shipping_advanced/rules_shipping_advanced/elements" /> + <params addpath="/plugins/vmshipment/rules_shipping_advanced/elements" /> - <params addpath="/administrator/components/com_virtuemart/elements"> + <params> <param type="vmjpluginwarning" /> <param type="rklabel" default='VMSHIPMENT_RULES_PLUGIN_ADV' level="level1" /> <param name="shipment_logos" type="vmfiles" label="VMSHIPMENT_WEIGHT_COUNTRIES_LOGOS" @@ -32,6 +34,7 @@ default="default" hide_default="1" hide_none="1" stripext="0" exclude="^_" /> <param name="weight_unit" type="vmweightunit" size="10" default="" label="VMSHIPMENT_WEIGHT_COUNTRIES_WEIGHT_UNIT" description="VMSHIPMENT_WEIGHT_COUNTRIES_WEIGHT_UNIT_DESC"/> + <param name="length_unit" type="vmlengthunit" size="10" default="" label="VMSHIPMENT_RULES_LENGTH_UNIT" description="VMSHIPMENT_RULES_LENGTH_UNIT_DESC"/> <param type="rklabel" default='VMSHIPMENT_RULES_HELP_ADV' /> diff --git a/rules_shipping_base.php b/rules_shipping_base.php index 876aadb661191e96ca7f8f6ca77b7b1e08a22ae7..39c3ef77027ba64c189c3c2959fc4439705cd6fe 100644 --- a/rules_shipping_base.php +++ b/rules_shipping_base.php @@ -322,7 +322,7 @@ class plgVmShipmentRules_Shipping_Base extends vmPSPlugin { return $articles; } - protected function getOrderDimensions (VirtueMartCart $cart) { + protected function getOrderDimensions (VirtueMartCart $cart, $length_dimension) { /* Cache the value in a static variable and calculate it only once! */ static $calculated = 0; static $dimensions=array( @@ -335,22 +335,29 @@ class plgVmShipmentRules_Shipping_Base extends vmPSPlugin { if ($calculated==0) { $calculated=1; foreach ($cart->products as $product) { - $volume = $product->product_length * $product->product_width * $product->product_height; + + $l = ShopFunctions::convertDimensionUnit ($product->product_length, $product->product_lwh_uom, $length_dimension); + $w = ShopFunctions::convertDimensionUnit ($product->product_width, $product->product_lwh_uom, $length_dimension); + $h = ShopFunctions::convertDimensionUnit ($product->product_height, $product->product_lwh_uom, $length_dimension); +// JFactory::getApplication()->enqueueMessage("<pre>Product, returned dimensions: $l x $w x $h, from $product->product_lwh_uom to $length_dimension, ".print_r($product,1)."</pre>", 'error'); + + $volume = $l * $w * $h; $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); - $dimensions['totallength'] += $product->product_length; - $dimensions['totalwidth'] += $product->product_width; - $dimensions['totalheight'] += $product->product_height; - + $dimensions['maxlength'] = max ($dimensions['maxlength'], $l); + $dimensions['minlength'] = min ($dimensions['minlength'], $l); + $dimensions['maxwidth'] = max ($dimensions['maxwidth'], $w); + $dimensions['minwidth'] = min ($dimensions['minwidth'], $w); + $dimensions['maxheight'] = max ($dimensions['maxheight'], $h); + $dimensions['minheight'] = min ($dimensions['minheight'], $h); + $dimensions['totallength'] += $l * $product->quantity; + $dimensions['totalwidth'] += $w * $product->quantity; + $dimensions['totalheight'] += $h * $product->quantity; } } +// JFactory::getApplication()->enqueueMessage("<pre>Dimensions: ".print_r($dimensions,1)."</pre>", 'error'); + return $dimensions; } @@ -377,8 +384,15 @@ class plgVmShipmentRules_Shipping_Base extends vmPSPlugin { $products += 1; $articles += $product->quantity; } + $zip = $address['zip']; $cartvals = array('weight'=>$orderWeight, - 'zip'=>$address['zip'], + 'zip'=>$zip, + 'zip1'=>substr($zip,0,1), + 'zip2'=>substr($zip,0,2), + 'zip3'=>substr($zip,0,3), + 'zip4'=>substr($zip,0,4), + 'zip5'=>substr($zip,0,5), + 'zip6'=>substr($zip,0,6), 'articles'=>$articles, 'products'=>$products, 'amount'=>$cart_prices['salesPrice'], @@ -397,7 +411,7 @@ class plgVmShipmentRules_Shipping_Base extends vmPSPlugin { 'country'=>$address['virtuemart_country_id'], ); - $cartvals = array_merge ($cartvals, $this->getOrderDimensions ($cart)); + $cartvals = array_merge ($cartvals, $this->getOrderDimensions ($cart, $method->length_unit)); // Let child classes update the $cartvals array, or add new variables $this->addCustomCartValues($cart, $cart_prices, $cartvals); return $cartvals; @@ -617,6 +631,42 @@ class ShippingRule { return strtolower($expr); } + function evaluateComparison ($terms, $vals) { + while (count($terms)>2) { + $res = false; + switch ($terms[1]) { + case '<': $res = ($terms[0] < $terms[2]); break; + case '<=': + case '=<': $res = ($terms[0] <= $terms[2]); break; + case '==': $res = ($terms[0] == $terms[2]); break; + case '!=': + case '<>': $res = ($terms[0] != $terms[2]); break; + case '>=': + case '=>': $res = ($terms[0] >= $terms[2]); break; + case '>': $res = ($terms[0] > $terms[2]); break; + case '~': + $l=min(strlen($terms[0]), strlen($terms[2])); + $res = (strncmp ($terms[0], $terms[2], $l) == 0); +JFactory::getApplication()->enqueueMessage("String-comparing $terms[0] and $terms[2] ($l chars), result=$res", 'error'); + break; + default: + JFactory::getApplication()->enqueueMessage(JText::sprintf('VMSHIPMENT_RULES_UNKNOWN_OPERATOR', $terms[1], $this->rulestring), 'error'); + $res = false; + } + + if ($res==false) return false; + array_shift($terms); + array_shift($terms); + } + if (count($terms)>1) { + // We do not have the correct number of terms for chained comparisons, i.e. two terms leftover instead of one! + JFactory::getApplication()->enqueueMessage(JText::sprintf('VMSHIPMENT_RULES_EVALUATE_UNKNOWN_ERROR', $this->rulestring), 'error'); + return false; + } + // All conditions were fulfilled, so we can return true + return true; + } + function evaluateTerm ($expr, $vals) { if (is_null($expr)) { return $expr; @@ -636,8 +686,13 @@ class ShippingRule { // Operator $op = array_shift($expr); $args = array(); + $evaluate = true; foreach ($expr as $e) { - $term = $this->evaluateTerm($e, $vals); + $term = $evaluate ? ($this->evaluateTerm($e, $vals)) : $e; + if ($op == 'comparison') { + // For comparisons, we only evaluate every other term (the operators are NOT evaluated!) + $evaluate = !$evaluate; + } if (is_null($term)) return null; $args[] = $term; } @@ -650,15 +705,19 @@ class ShippingRule { case ' AND ': $res = true; foreach ($args as $a) { $res = ($res && $a); }; break; case 'in': $needle = array_shift($args); $res = in_array($needle, $args); break; - case '<': $res = ($args[0] < $args[1]); break; + case '<': case '<=': - case '=<': $res = ($args[0] <= $args[1]); break; - case '==': $res = ($args[0] == $args[1]); break; + case '=<': + case '==': case '!=': - case '<>': $res = ($args[0] != $args[1]); break; + case '<>': case '>=': - case '=>': $res = ($args[0] >= $args[1]); break; - case '>': $res = ($args[0] > $args[1]); break; + case '=>': + case '>': + case '~': + $res = $this->evaluateComparison(array($args[0], $op, $args[1]), $vals); break; + case 'comparison': + $res = $this->evaluateComparison($args, $vals); break; case "+": $res = ($args[0] + $args[1]); break; case "-": $res = ($args[0] - $args[1]); break; @@ -669,6 +728,8 @@ class ShippingRule { default: $res = false; } + +// JFactory::getApplication()->enqueueMessage("<pre>Result of ".print_r($expr,1)." is $res.</pre>", 'error'); return $res; } else { // Neither string nor numeric, nor operator...