diff --git a/rules_shipping_advanced.php b/rules_shipping_advanced.php index df476b0db79f08958a0f307ac90a4f9e59fbe02e..a40fde60e7aa8cffad06d419a23c557fc8aff1e9 100644 --- a/rules_shipping_advanced.php +++ b/rules_shipping_advanced.php @@ -109,23 +109,13 @@ class ShippingRule_Advanced extends ShippingRule { } function tokenize_expression ($expression) { - // First, extract all strings, delimited by ": - $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 -// TODO 1: This fails for expressions like "(1>0) OR zip in array(1,4,1080)" -// TODO 2: Better handle the spaces around in-line text operators! -// (state2 in array("TX", "WS", "MS")) OR zip in array(1,4,1080) - $op_re = ':\s*( OR |&&| AND | in |<=|=>|>=|=>|<>|!=|==|<|=|>|~|\+|-|\*|/|%|\(|\)|\^|,)\s*:'; - $atoms = array(); - foreach ($strings as $s) { - if (preg_match($str_re, $s)) { - $atoms[] = $s; - } else { - $newatoms = preg_split($op_re, $s, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY); - $atoms = array_merge ($atoms, $newatoms); - } - } + // First, extract all strings, delimited by quotes, then all text operators + // (OR, AND, in; but make sure we don't capture parts of words, so we need to + // use lookbehind/lookahead patterns to exclude OR following another letter + // or followed by another letter) and then all arithmetic operators + $re = '/\s*("[^"]*"|\'[^\']*\'|(?<![A-Za-z0-9])(?:OR|AND|IN|or|and|in)(?![A-Za-z0-9])|&&|<=|=>|>=|=>|<>|!=|==|<|=|>|~|\+|-|\*|\/|%|\(|\)|\^|,)\s*/'; + $atoms = preg_split($re, $expression, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY); + // JFactory::getApplication()->enqueueMessage("TOKENIZING '$expression' returns: <pre>".print_r($atoms,1)."</pre>", 'error'); return $atoms; } @@ -186,7 +176,7 @@ class ShippingRule_Advanced extends ShippingRule { $unary_ops = array("-" => ".-", "+" => ".+"); // Any of these indicate a comparison and thus a condition: - $condition_ops = array('<', '<=', '=<', '<>', '!=', '==', '>', '>=', '=>', '~', ' OR ', 'OR', 'AND', ' AND ', '&&', 'in', ' in '); + $condition_ops = array('<', '<=', '=<', '<>', '!=', '==', '>', '>=', '=>', '~', 'OR', 'AND', 'AND', '&&', 'in'); $comparison_ops = array('<', '<=', '=<', '<>', '!=', '==', '>', '>=', '=>', '~'); $is_condition = false; $is_assignment = false; diff --git a/rules_shipping_base.php b/rules_shipping_base.php index 258aae363c44434923951b0cd8e27d3151462b96..10878aaee5da1282b00948018f4f57527432f349 100644 --- a/rules_shipping_base.php +++ b/rules_shipping_base.php @@ -416,7 +416,10 @@ class plgVmShipmentRules_Shipping_Base extends vmPSPlugin { } function getOrderCountryState (VirtueMartCart $cart, $address) { - $data = array (); + $data = array ( + 'countryid' => 0, 'country' => '', 'country2' => '', 'country3' => '', + 'stateid' => 0, 'state' => '', 'state2' => '', 'state3' => '', + ); $countriesModel = VmModel::getModel('country'); if (isset($address['virtuemart_country_id'])) { @@ -761,6 +764,7 @@ class ShippingRule { switch ($func) { case "max": return max($args); break; case "min": return min($args); break; + case "list": case "array": return $args; break; } // No known function matches => print an error, return 0 @@ -806,13 +810,10 @@ class ShippingRule { $res = false; switch ($op) { // Logical operators: - case 'OR': - case ' OR ': foreach ($args as $a) { $res = ($res || $a); }; break; + case 'OR': foreach ($args as $a) { $res = ($res || $a); }; break; case '&&': - case 'AND': - case ' AND ': $res = true; foreach ($args as $a) { $res = ($res && $a); }; break; - case 'in': - case ' in ': $res = in_array($args[0], $args[1]); break; + case 'AND': $res = true; foreach ($args as $a) { $res = ($res && $a); }; break; + case 'in': $res = in_array($args[0], $args[1]); break; // Comparisons: case '<': @@ -868,6 +869,8 @@ class ShippingRule { foreach ($this->conditions as $c) { // All conditions have to match! $ret = $this->evaluateTerm($c, $vals); + // JFactory::getApplication()->enqueueMessage("Evaluating term <pre>".print_r($c,1)."</pre> returns $ret", 'error'); + if (is_null($ret) || (!$ret)) { return false; }