Rajout de doctrine/orm
[zf2.biz/galerie.git] / vendor / doctrine / common / lib / Doctrine / Common / Collections / Expr / ClosureExpressionVisitor.php
1 <?php
2 /*
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.
14  *
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>.
18  */
19
20 namespace Doctrine\Common\Collections\Expr;
21
22 /**
23  * Walks an expression graph and turns it into a PHP closure.
24  *
25  * This closure can be used with {@Collection#filter()} and is used internally
26  * by {@ArrayCollection#select()}.
27  *
28  * @author Benjamin Eberlei <kontakt@beberlei.de>
29  * @since 2.3
30  */
31 class ClosureExpressionVisitor extends ExpressionVisitor
32 {
33     /**
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).
36      *
37      * is*() is not supported.
38      *
39      * @return mixed
40      */
41     static public function getObjectFieldValue($object, $field)
42     {
43         $accessor = "get" . $field;
44
45         if (method_exists($object, $accessor) || method_exists($object, '__call')) {
46             return $object->$accessor();
47         }
48
49         if ($object instanceof \ArrayAccess) {
50             return $object[$field];
51         }
52
53         return $object->$field;
54     }
55
56     /**
57      * Helper for sorting arrays of objects based on multiple fields +
58      * orientations.
59      *
60      * @param string $name
61      * @param int $orientation
62      * @param Closure $next
63      * @return Closure
64      */
65     static public function sortByField($name, $orientation = 1, \Closure $next = null)
66     {
67         if (!$next) {
68             $next = function() {
69                 return 0;
70             };
71         }
72
73         return function ($a, $b) use ($name, $next, $orientation) {
74             $aValue = ClosureExpressionVisitor::getObjectFieldValue($a, $name);
75             $bValue = ClosureExpressionVisitor::getObjectFieldValue($b, $name);
76
77             if ($aValue === $bValue) {
78                 return $next($a, $b);
79             }
80
81             return (($aValue > $bValue) ? 1 : -1) * $orientation;
82         };
83     }
84
85     /**
86      * {@inheritDoc}
87      */
88     public function walkComparison(Comparison $comparison)
89     {
90         $field = $comparison->getField();
91         $value = $comparison->getValue()->getValue(); // shortcut for walkValue()
92
93         switch ($comparison->getOperator()) {
94             case Comparison::EQ:
95             case Comparison::IS:
96                 return function ($object) use ($field, $value) {
97                     return ClosureExpressionVisitor::getObjectFieldValue($object, $field) === $value;
98                 };
99
100             case Comparison::NEQ:
101                 return function ($object) use ($field, $value) {
102                     return ClosureExpressionVisitor::getObjectFieldValue($object, $field) !== $value;
103                 };
104
105             case Comparison::LT:
106                 return function ($object) use ($field, $value) {
107                     return ClosureExpressionVisitor::getObjectFieldValue($object, $field) < $value;
108                 };
109
110             case Comparison::LTE:
111                 return function ($object) use ($field, $value) {
112                     return ClosureExpressionVisitor::getObjectFieldValue($object, $field) <= $value;
113                 };
114
115             case Comparison::GT:
116                 return function ($object) use ($field, $value) {
117                     return ClosureExpressionVisitor::getObjectFieldValue($object, $field) > $value;
118                 };
119
120             case Comparison::GTE:
121                 return function ($object) use ($field, $value) {
122                     return ClosureExpressionVisitor::getObjectFieldValue($object, $field) >= $value;
123                 };
124
125             case Comparison::IN:
126                 return function ($object) use ($field, $value) {
127                     return in_array(ClosureExpressionVisitor::getObjectFieldValue($object, $field), $value);
128                 };
129
130             case Comparison::NIN:
131                 return function ($object) use ($field, $value) {
132                     return ! in_array(ClosureExpressionVisitor::getObjectFieldValue($object, $field), $value);
133                 };
134
135             default:
136                 throw new \RuntimeException("Unknown comparison operator: " . $comparison->getOperator());
137         }
138     }
139
140     /**
141      * {@inheritDoc}
142      */
143     public function walkValue(Value $value)
144     {
145         return $value->getValue();
146     }
147
148     /**
149      * {@inheritDoc}
150      */
151     public function walkCompositeExpression(CompositeExpression $expr)
152     {
153         $expressionList = array();
154
155         foreach ($expr->getExpressionList() as $child) {
156             $expressionList[] = $this->dispatch($child);
157         }
158
159         switch($expr->getType()) {
160             case CompositeExpression::TYPE_AND:
161                 return $this->andExpressions($expressionList);
162
163             case CompositeExpression::TYPE_OR:
164                 return $this->orExpressions($expressionList);
165
166             default:
167                 throw new \RuntimeException("Unknown composite " . $expr->getType());
168         }
169     }
170
171     private function andExpressions($expressions)
172     {
173         return function ($object) use ($expressions) {
174             foreach ($expressions as $expression) {
175                 if ( ! $expression($object)) {
176                     return false;
177                 }
178             }
179             return true;
180         };
181     }
182
183     private function orExpressions($expressions)
184     {
185         return function ($object) use ($expressions) {
186             foreach ($expressions as $expression) {
187                 if ($expression($object)) {
188                     return true;
189                 }
190             }
191             return false;
192         };
193     }
194 }
195