Commit 66681345 authored by Reinhold Kainhofer's avatar Reinhold Kainhofer
Browse files

Further work on scoping - basically works, just needs testing; fix warnings

parent 31403f63
......@@ -173,9 +173,9 @@ class plgVmShipmentRules_Shipping_Base extends vmPSPlugin {
$values['virtuemart_shipmentmethod_id'] = $order['details']['BT']->virtuemart_shipmentmethod_id;
$values['shipment_name'] = $this->renderPluginName ($method);
$values['rule_name'] = $method->rule_name;
$values['order_weight'] = $this->getOrderWeight ($cart, $method->weight_unit);
$values['order_articles'] = $this->getOrderArticles ($cart);
$values['order_products'] = $this->getOrderProducts ($cart);
// $values['order_weight'] = $this->getOrderWeight ($cart, $method->weight_unit);
// $values['order_articles'] = $this->getOrderArticles ($cart);
// $values['order_products'] = $this->getOrderProducts ($cart);
$values['shipment_weight_unit'] = $method->weight_unit;
$values['shipment_cost'] = $method->cost;
$values['tax_id'] = $method->tax_id;
......@@ -265,7 +265,9 @@ class plgVmShipmentRules_Shipping_Base extends vmPSPlugin {
}
/** This function evaluates all rules, one after the other until it finds a matching rule that
* defines shipping costs (or uses NoShipping). If a modifier or definition is encountered,
* its effect is stored, but the loop continues */
protected function evaluateMethodRules ($cart, $method, $cart_prices) {
// $method->match will cache the matched rule and the modifiers
if (isset($this->match[$method->virtuemart_shipmentmethod_id])) {
......@@ -274,8 +276,13 @@ class plgVmShipmentRules_Shipping_Base extends vmPSPlugin {
// Evaluate all rules and find the matching ones (including modifiers and definitions!)
$result = array("rule"=>Null, "rule_name"=>"", "modifiers_add"=>array(), "modifiers_multiply"=>array());
$cartvals = $this->getCartValues ($cart, $cart->products, $method, $cart_prices);
// Pass a callback function to matches to obtain the cartvals for a subset of the products
$this_class = $this;
$cartvals_callback = function ($products) use ($this_class, $cart, $method, $cart_prices) {
return $this_class->getCartValues ($cart, $products, $method, NULL);
};
foreach ($this->rules[$method->virtuemart_shipmentmethod_id] as $r) {
if ($r->matches($cartvals)) {
if ($r->matches($cartvals, $cart->products, $cartvals_callback)) {
$rtype = $r->getType();
switch ($rtype) {
case 'shipping':
......@@ -288,7 +295,9 @@ class plgVmShipmentRules_Shipping_Base extends vmPSPlugin {
case 'modifiers_multiply':
$result[$rtype][] = $r;
break;
case 'definition': // A definition has modified the $cartvals, but has no other effects
case 'definition': // A definition updates the $cartvals, but has no other effects
$cartvals[strtolower($r->getRuleName())] = $r->getShippingCosts();
// TODO
break;
default:
$this->printWarning(JText::sprintf('VMSHIPMENT_RULES_UNKNOWN_TYPE', $r->getType(), $r->rulestring));
......@@ -657,18 +666,18 @@ class plgVmShipmentRules_Shipping_Base extends vmPSPlugin {
'zip6'=>substr($zip,0,6),
'city'=>isset($address['city'])?trim($address['city']):'',
);
data['company'] = $address['company'];
data['title'] = $address['title'];
data['first_name'] = $address['first_name'];
data['middle_name'] = $address['middle_name'];
data['last_name'] = $address['last_name'];
data['address1'] = $address['address_1'];
data['address2'] = $address['address_2'];
data['city'] = $address['city'];
data['phone1'] = $address['phone_1'];
data['phone2'] = $address['phone_2'];
data['fax'] = $address['fax'];
data['email'] = $address['email'];
$data['company'] = $address['company'];
$data['title'] = $address['title'];
$data['first_name'] = $address['first_name'];
$data['middle_name'] = $address['middle_name'];
$data['last_name'] = $address['last_name'];
$data['address1'] = $address['address_1'];
$data['address2'] = $address['address_2'];
$data['city'] = $address['city'];
$data['phone1'] = $address['phone_1'];
$data['phone2'] = $address['phone_2'];
$data['fax'] = $address['fax'];
$data['email'] = $address['email'];
return $data;
}
......@@ -885,7 +894,7 @@ function filterProducts($products, $filter_conditions) {
foreach ($products as $p) {
if (!empty($filter_conditions['skus']) && !in_array($p->product_sku, $filter_conditions['skus']))
continue;
if (!empty($filter_conditions['categories']) && count(array_intersect($filter_conditions['categories'], $p->product_categories))==0)
if (!empty($filter_conditions['categories']) && count(array_intersect($filter_conditions['categories'], $p->categories))==0)
continue;
if (!empty($filter_conditions['manufacturers']) && count(array_intersect($filter_conditions['manufacturers'], $p->product_manufacturers))==0)
continue;
......@@ -1115,10 +1124,11 @@ class ShippingRule {
/** Evaluate the given expression $expr only for the products that match the filter given by the scoping
* function and the corresponding conditions */
protected function evaluateScoping($expr, $scoping, $conditionvals, $vals) {
if (count($conditions)<1)
return $this->evaluateTerm($expr, $vals);
protected function evaluateScoping($expr, $scoping, $conditionvals, $vals, $products, $cartvals_callback) {
// JFactory::getApplication()->enqueueMessage("<pre>Scoping, begin, scoping=$scoping, expression=".print_r($expr,1).", conditionvals=".print_r($conditionvals, 1)."</pre>", 'error');
if (count($conditionvals)<1)
return $this->evaluateTerm($expr, $vals, $products, $cartvals_callback);
$filterkeys = array(
"evaluate_for_categories" => 'categories',
"evaluate_for_products" => 'products',
......@@ -1126,15 +1136,17 @@ class ShippingRule {
"evaluate_for_manufacturers" => 'manufacturers'
);
// JFactory::getApplication()->enqueueMessage("<pre>Scoping: condition is ".$filterkeys[$scoping].'='.print_r($conditionvals,1).", Old cartvals are: ".print_r($vals,1)."</pre>", 'error');
$conditions = array();
if (isset($filterkeys[$scoping]))
$conditions[$filterkeys[$scoping]] = $conditionsvals;
$conditions[$filterkeys[$scoping]] = $conditionvals;
// Pass the conditions to the parent plugin class to filter the current list of products:
$products = filterProducts($currentproducts, $conditions);
$vals = $this->plugin->getCartValues ($cart, $products, /* FIXME: method*/ $this->method, $cart_prices);
// FIXME: IMPLEMENT
// TODO
$filteredproducts = filterProducts($products, $conditions);
// We have been handed a callback function to calculate the cartvals for the filtered list of products, so use it:
$filteredvals = $cartvals_callback($filteredproducts);
// JFactory::getApplication()->enqueueMessage("<pre>Scoping: condition is ".print_r($conditions,1).", products filtered: ".count($filteredproducts).", New cartvals are: ".print_r($filteredvals,1)."</pre>", 'error');
return $this->evaluateTerm ($expr, $filteredvals, $filteredproducts, $cartvals_callback);
}
protected function evaluateFunction ($function, $args) {
......@@ -1231,7 +1243,7 @@ class ShippingRule {
}
}
protected function evaluateTerm ($expr, $vals) {
protected function evaluateTerm ($expr, $vals, $products, $cartvals_callback) {
// The scoping functions need to be handled differently, because they first need to adjust the cart variables to the filtered product list
// before evaluating its first argument. So even though parsing the rules handles scoping functions like any other function, their
// evaluation is fundamentally different and is special-cased here:
......@@ -1254,7 +1266,7 @@ class ShippingRule {
$func = array_shift($expr); // The scoping function name
$expression = array_shift($expr); // The expression to be evaluated
$conditions = $expr; // the remaining $expr list now contains the conditions
return $this->evaluateScoping ($expression, $func, $conditions, $vals);
return $this->evaluateScoping ($expression, $func, $conditions, $vals, $products, $cartvals_callback);
} elseif (is_array($expr)) {
// Operator
......@@ -1266,7 +1278,7 @@ class ShippingRule {
$evaluate = false;
}
foreach ($expr as $e) {
$term = $evaluate ? ($this->evaluateTerm($e, $vals)) : $e;
$term = $evaluate ? ($this->evaluateTerm($e, $vals, $products, $cartvals_callback)) : $e;
if ($op == 'COMPARISON') {
// For comparisons, we only evaluate every other term (the operators are NOT evaluated!)
// The data format for comparisons is: array('COMPARISON', $operand1, '<', $operand2, '<=', ....)
......@@ -1329,11 +1341,11 @@ class ShippingRule {
}
}
protected function calculateShipping ($vals) {
return $this->evaluateTerm($this->shipping, $vals);
protected function calculateShipping ($vals, $products, $cartvals_callback) {
return $this->evaluateTerm($this->shipping, $vals, $products, $cartvals_callback);
}
protected function evaluateRule (&$vals) {
protected function evaluateRule (&$vals, $products, $cartvals_callback) {
if ($this->evaluated)
return; // Already evaluated
......@@ -1347,7 +1359,7 @@ class ShippingRule {
foreach ($this->conditions as $c) {
// All conditions have to match!
$ret = $this->evaluateTerm($c, $vals);
$ret = $this->evaluateTerm($c, $vals, $products, $cartvals_callback);
if (is_null($ret) || (!$ret)) {
return;
......@@ -1356,7 +1368,7 @@ class ShippingRule {
// All conditions match
$this->match = True;
// Calculate the value (i.e. shipping cost or modifier)
$this->value = $this->calculateShipping($vals);
$this->value = $this->calculateShipping($vals, $products, $cartvals_callback);
// For definitions add the variable to the vals
if ($this->ruletype=='definition') {
$vals[strtolower($this->name)] = $this->value;
......@@ -1376,8 +1388,8 @@ class ShippingRule {
$this->rulename = $name;
}
function matches(&$vals) {
$this->evaluateRule($vals);
function matches(&$vals, $products, $cartvals_callback) {
$this->evaluateRule($vals, $products, $cartvals_callback);
return $this->match;
}
......
Supports Markdown
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