3
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
15
* This software consists of voluntary contributions made by many individuals
16
* and is licensed under the MIT license. For more information, see
17
* <http://www.doctrine-project.org>.
20
namespace Doctrine\Common\Collections\Expr;
23
* Walks an expression graph and turns it into a PHP closure.
25
* This closure can be used with {@Collection#filter()} and is used internally
26
* by {@ArrayCollection#select()}.
28
* @author Benjamin Eberlei <kontakt@beberlei.de>
31
class ClosureExpressionVisitor extends ExpressionVisitor
34
* Access the field of a given object. This field has to be public directly
35
* or indirectly (through an accessor get* or a magic method, __get, __call).
37
* is*() is not supported.
41
static public function getObjectFieldValue($object, $field)
43
$accessor = "get" . $field;
45
if (method_exists($object, $accessor) || method_exists($object, '__call')) {
46
return $object->$accessor();
49
if ($object instanceof \ArrayAccess) {
50
return $object[$field];
53
return $object->$field;
57
* Helper for sorting arrays of objects based on multiple fields +
61
* @param int $orientation
62
* @param Closure $next
65
static public function sortByField($name, $orientation = 1, \Closure $next = null)
73
return function ($a, $b) use ($name, $next, $orientation) {
74
$aValue = ClosureExpressionVisitor::getObjectFieldValue($a, $name);
75
$bValue = ClosureExpressionVisitor::getObjectFieldValue($b, $name);
77
if ($aValue === $bValue) {
81
return (($aValue > $bValue) ? 1 : -1) * $orientation;
88
public function walkComparison(Comparison $comparison)
90
$field = $comparison->getField();
91
$value = $comparison->getValue()->getValue(); // shortcut for walkValue()
93
switch ($comparison->getOperator()) {
96
return function ($object) use ($field, $value) {
97
return ClosureExpressionVisitor::getObjectFieldValue($object, $field) === $value;
100
case Comparison::NEQ:
101
return function ($object) use ($field, $value) {
102
return ClosureExpressionVisitor::getObjectFieldValue($object, $field) !== $value;
106
return function ($object) use ($field, $value) {
107
return ClosureExpressionVisitor::getObjectFieldValue($object, $field) < $value;
110
case Comparison::LTE:
111
return function ($object) use ($field, $value) {
112
return ClosureExpressionVisitor::getObjectFieldValue($object, $field) <= $value;
116
return function ($object) use ($field, $value) {
117
return ClosureExpressionVisitor::getObjectFieldValue($object, $field) > $value;
120
case Comparison::GTE:
121
return function ($object) use ($field, $value) {
122
return ClosureExpressionVisitor::getObjectFieldValue($object, $field) >= $value;
126
return function ($object) use ($field, $value) {
127
return in_array(ClosureExpressionVisitor::getObjectFieldValue($object, $field), $value);
130
case Comparison::NIN:
131
return function ($object) use ($field, $value) {
132
return ! in_array(ClosureExpressionVisitor::getObjectFieldValue($object, $field), $value);
136
throw new \RuntimeException("Unknown comparison operator: " . $comparison->getOperator());
143
public function walkValue(Value $value)
145
return $value->getValue();
151
public function walkCompositeExpression(CompositeExpression $expr)
153
$expressionList = array();
155
foreach ($expr->getExpressionList() as $child) {
156
$expressionList[] = $this->dispatch($child);
159
switch($expr->getType()) {
160
case CompositeExpression::TYPE_AND:
161
return $this->andExpressions($expressionList);
163
case CompositeExpression::TYPE_OR:
164
return $this->orExpressions($expressionList);
167
throw new \RuntimeException("Unknown composite " . $expr->getType());
171
private function andExpressions($expressions)
173
return function ($object) use ($expressions) {
174
foreach ($expressions as $expression) {
175
if ( ! $expression($object)) {
183
private function orExpressions($expressions)
185
return function ($object) use ($expressions) {
186
foreach ($expressions as $expression) {
187
if ($expression($object)) {