Skip to content
GitLab
About GitLab
GitLab: the DevOps platform
Explore GitLab
Install GitLab
How GitLab compares
Get started
GitLab docs
GitLab Learn
Pricing
Talk to an expert
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Projects
Groups
Snippets
Sign up now
Login
Sign in
Toggle navigation
Menu
Open sidebar
VirtueMart
Shipping by Rules for VirtueMart
Commits
66681345
Commit
66681345
authored
Nov 16, 2014
by
Reinhold Kainhofer
Browse files
Further work on scoping - basically works, just needs testing; fix warnings
parent
31403f63
Changes
1
Hide whitespace changes
Inline
Side-by-side
rules_shipping_base.php
View file @
66681345
...
...
@@ -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
]]
=
$condition
s
vals
;
$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
;
}
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment