http://phing.info/

Source Code Coverage

Designed for use with PHPUnit2, Xdebug and Phing.

Methods: 20 LOC: 404 Statements: 103

Source file Statements Methods Total coverage
Expression.php 100.0% 100.0% 100.0%
 
1
<?php
2
/**
3
 * Xyster Framework
4
 *
5
 * LICENSE
6
 *
7
 * This source file is subject to the new BSD license that is bundled
8
 * with this package in the file LICENSE.txt.
9
 * It is also available through the world-wide-web at this URL:
10
 * http://www.opensource.org/licenses/bsd-license.php
11
 * If you did not receive a copy of the license and are unable to
12
 * obtain it through the world-wide-web, please send an email
13
 * to xyster@devweblog.org so we can send you a copy immediately.
14
 *
15
 * @category  Xyster
16
 * @package   Xyster_Data
17
 * @copyright Copyright (c) 2007 Irrational Logic (http://devweblog.org)
18
 * @license   http://www.opensource.org/licenses/bsd-license.php New BSD License
19
 */
20
/**
21
 * Xyster_Data_Criterion
22
 */
23 1
require_once 'Xyster/Data/Criterion.php';
24
/**
25
 * An expression is a boolean evaluation comparing a column against a value
26
 *
27
 * @category  Xyster
28
 * @package   Xyster_Data
29
 * @copyright Copyright (c) 2007 Irrational Logic (http://devweblog.org)
30
 * @license   http://www.opensource.org/licenses/bsd-license.php New BSD License
31
 */
32
class Xyster_Data_Expression extends Xyster_Data_Criterion
33
{
34
    /**
35
     * Internal list of valid expression operators
36
     *
37
     * @var array
38
     */
39
    static private $_operators = array(
40
        "eq" => "=",
41
        "neq" => "<>",
42
        "lt" => "<",
43
        "gt" => ">",
44
        "gte" => ">=",
45
        "lte" => "<=",
46
        "like" => "LIKE",
47
        "notLike" => "NOT LIKE",
48
        "between" => "BETWEEN",
49
        "notBetween" => "NOT BETWEEN",
50
        "in" => "IN",
51
        "notIn" => "NOT IN"
52
    );
53
54
    /**
55
     * The left value, always a field
56
     *
57
     * @var Xyster_Data_Field
58
     */
59
    protected $_left;
60
    /**
61
     * The operator
62
     *
63
     * @var string
64
     */
65
    protected $_operator;
66
    /**
67
     * The right value, could be a scalar or a {@link Xyster_Data_Field}
68
     *
69
     * @var mixed
70
     */
71
    protected $_right;
72
73
    /**
74
     * Creates a new expression
75
     *
76
     * @param Xyster_Data_Field|string $field
77
     * @param string $operator
78
     * @param mixed $value
79
     */
80
    protected function __construct( $field, $operator, $value )
81
    {
82 131
        if (! $field instanceof Xyster_Data_Field) {
83 93
            require_once 'Xyster/Data/Field.php';
84 93
            $field = Xyster_Data_Field::named($field);
85 93
        }
86 131
        $this->_left = $field;
87 131
        $this->_operator = $operator;
88 131
        if ( $value == "NULL" ) {
89 11
            $value = null;
90 11
        }
91 131
        $this->_right = $value;
92
    }
93
94
    /**
95
     * Gets the field
96
     *
97
     * @return Xyster_Data_Field
98
     */
99
    public function getLeft()
100
    {
101 56
        return $this->_left;
102
    }
103
104
    /**
105
     * Gets the operator
106
     *
107
     * @return string
108
     */
109
    public function getOperator()
110
    {
111 44
        return $this->_operator;
112
    }
113
114
    /**
115
     * Gets the value
116
     *
117
     * @return mixed
118
     */
119
    public function getRight()
120
    {
121 44
        return $this->_right;
122
    }
123
124
    /**
125
     * Returns the syntax for this Expression
126
     *
127
     * @magic
128
     * @return string
129
     */
130
    public function __toString()
131
    {
132 19
        $string = "";
133 19
        $val = $this->_right;
134 19
        if ( $val == "NULL" || $val === null ) {
135 1
            $string .= 'NULL';
136 19
        } else if ( is_array($val) && strpos($this->_operator,'BETWEEN') !== false ) {
137 2
            $string .= ( preg_match("/^[0-9.]+$/",$val[0]) ) ?
138 2
                $val[0] : "'".str_replace("'","''",$val[0])."'";
139 2
            $string .= ' AND ';
140 2
            $string .= ( preg_match("/^[0-9.]+$/",$val[1]) ) ?
141 2
                $val[1] : "'".str_replace("'","''",$val[1])."'";
142 19
        } else if ( is_array($val)
143 19
            && $this->_operator == "IN" || $this->_operator == "NOT IN" ) {
144 2
            $quoted = array();
145 2
            foreach( $val as $v ) {
146 2
                $quoted[] = ( preg_match("/^[0-9.]+$/",$v) ) ?
147 2
                    $v : "'".str_replace("'","''",$v)."'";
148 2
            }
149 2
            $string .= '('. implode(',',$quoted) . ')';
150 19
        } else if ( $val instanceof Xyster_Data_Field ) {
151 1
            $string .= (string)$val;
152 18
        } else if ( !is_numeric($val) ) {
153 8
            $string .= "'".str_replace("'","''",$val)."'";
154 8
        } else {
155 12
            $string .= $val;
156
        }
157 19
        return (string)$this->_left . " " . $this->_operator . " " . $string;
158
    }
159
160
    /**
161
     * Evaluates the Expression for a given array or object
162
     *
163
     * @param mixed $object
164
     * @return boolean
165
     */
166
    public function evaluate( $object )
167
    {
168 52
        $value = $this->_left->evaluate($object);
169 52
        $value2 = ( $this->_right instanceof Xyster_Data_Field ) ?
170 52
            $this->_right->evaluate($object) : $this->_right;
171
172 52
        $bool = false;
173 52
        $eval = "\$bool = (bool)( \$value %s \$value2 );";
174 52
        switch( $this->_operator ) {
175 52
            case "=":
176 38
                eval(sprintf($eval,'=='));
177 38
                break;
178
179 21
            case "<>":
180 4
                eval(sprintf($eval,'!='));
181 4
                break;
182
183 18
            case "LIKE":
184 18
            case "NOT LIKE":
185 3
                $lookend = ( substr($value2,0,1) == '%' );
186 3
                $lookbeg = ( substr($value2,-1,1) == '%' );
187 3
                $lookin = ( $lookbeg && $lookend );
188 3
                if ( $lookin ) {
189 3
                    $bool = strpos($value,substr($value2,1,strlen($value2)-2)) > -1;
190 3
                } else if ( $lookbeg ) {
191 2
                    $bool = ( substr($value2,0,-1) == substr($value,0,strlen($value2)-1) );
192 2
                } else if ( $lookend ) {
193 2
                    $match = substr($value2,1);
194 2
                    $bool = ( $match == substr($value,-strlen($match)) );
195 2
                }
196 3
                if ( $this->_operator == "NOT LIKE" ) {
197 1
                    $bool = !$bool;
198 1
                }
199 3
                break;
200
201 16
            case "IN":
202 1
                $bool = ( in_array($value,$value2) );
203 1
                break;
204
205 15
            case "NOT IN":
206 1
                $bool = ( !in_array($value,$value2) );
207 1
                break;
208
209 14
            case "BETWEEN":
210 1
                $bool = ( $value >= $value2[0] ) && ( $value <= $value2[1] );
211 1
                break;
212
213 13
            case "NOT BETWEEN":
214 1
                $bool = ( $value < $value2[0] ) || ( $value > $value2[1] );
215 1
                break;
216
217 12
            case ">":
218 12
            case "<":
219 12
            case ">=":
220 12
            case "<=":
221 12
            default:
222 12
                eval(sprintf($eval, $this->_operator));
223 12
        }
224 52
        return $bool;
225
    }
226
227
    /**
228
     * Tests whether the string passed is a valid Expression operator
229
     *
230
     * @param string $operator
231
     * @return boolean
232
     */
233
    static public function isOperator( $operator )
234
    {
235 56
        return in_array($operator,self::$_operators);
236
    }
237
238
    /**
239
     * Returns the name of the static method to call for the operator passed
240
     *
241
     * @param string $operator
242
     * @return string
243
     */
244
    static public function getMethodName( $operator )
245
    {
246 52
        return array_search($operator,self::$_operators);
247
    }
248
249
    /**
250
     * Equal To Xyster_Data_Expression ( field = 'value' )
251
     *
252
     * For $value to reference another field, pass a {@link Xyster_Data_Field} object
253
     *
254
     * @param string $field
255
     * @param string $value
256
     * @return Xyster_Data_Expression
257
     */
258
    static public function eq( $field, $value )
259
    {
260 81
        return new Xyster_Data_Expression($field, self::$_operators[__FUNCTION__], $value);
261
    }
262
263
    /**
264
     * Not Equal To Xyster_Data_Expression ( field <> 'value' )
265
     *
266
     * For $value to reference another field, pass a {@link Xyster_Data_Field} object
267
268
     * @param string $field
269
     * @param string $value
270
     * @return Xyster_Data_Expression
271
     */
272
    static public function neq( $field, $value )
273
    {
274 50
        return new Xyster_Data_Expression($field, self::$_operators[__FUNCTION__], $value);
275
    }
276
277
    /**
278
     * Less Than Xyster_Data_Expression ( field < 3 )
279
     *
280
     * For $value to reference another field, pass a {@link Xyster_Data_Field} object
281
     *
282
     * @param string $field
283
     * @param string $value
284
     * @return Xyster_Data_Expression
285
     */
286
    static public function lt( $field, $value )
287
    {
288 4
        return new Xyster_Data_Expression($field, self::$_operators[__FUNCTION__], $value);
289
    }
290
291
    /**
292
     * Less Than or Equal To Xyster_Data_Expression ( field <= 3 )
293
     *
294
     * @param string $field
295
     * @param string $value
296
     * @return Xyster_Data_Expression
297
     */
298
    static public function lte( $field, $value )
299
    {
300 2
        return new Xyster_Data_Expression($field, self::$_operators[__FUNCTION__], $value);
301
    }
302
303
    /**
304
     * Greater Than Xyster_Data_Expression ( field > 2 )
305
     *
306
     * For $value to reference another field, pass a {@link Xyster_Data_Field} object
307
     *
308
     * @param string $field
309
     * @param string $value
310
     * @return Xyster_Data_Expression
311
     */
312
    static public function gt( $field, $value )
313
    {
314 20
        return new Xyster_Data_Expression($field, self::$_operators[__FUNCTION__], $value);
315
    }
316
317
    /**
318
     * Greater Than or Equal To Xyster_Data_Expression ( field >= 2 )
319
     *
320
     * For $value to reference another field, pass a {@link Xyster_Data_Field} object
321
     *
322
     * @param string $field
323
     * @param string $value
324
     * @return Xyster_Data_Expression
325
     */
326
    static public function gte( $field, $value )
327
    {
328 2
        return new Xyster_Data_Expression($field, self::$_operators[__FUNCTION__], $value);
329
    }
330
331
    /**
332
     * LIKE Xyster_Data_Expression ( field LIKE '%value' )
333
     *
334
     * @param string $field
335
     * @param string $value
336
     * @return Xyster_Data_Expression
337
     */
338
    static public function like( $field, $value )
339
    {
340 9
        return new Xyster_Data_Expression($field, self::$_operators[__FUNCTION__], $value);
341
    }
342
343
    /**
344
     * NOT LIKE Xyster_Data_Expression ( field NOT LIKE '%value' )
345
     *
346
     * @param string $field
347
     * @param string $value
348
     * @return Xyster_Data_Expression
349
     */
350
    static public function notLike( $field, $value )
351
    {
352 6
        return new Xyster_Data_Expression($field, self::$_operators[__FUNCTION__], $value);
353
    }
354
355
    /**
356
     * BETWEEN Xyster_Data_Expression ( field BETWEEN 'value' AND 'value' )
357
     *
358
     * @param string $field
359
     * @param string $start
360
     * @param string $end
361
     * @return Xyster_Data_Expression
362
     */
363
    static public function between( $field, $start, $end )
364
    {
365 5
        return new Xyster_Data_Expression($field, self::$_operators[__FUNCTION__], array($start, $end));
366
    }
367
368
    /**
369
     * Equal To Xyster_Data_Expression ( field NOT BETWEEN 'value' AND 'value' )
370
     *
371
     * @param string $field
372
     * @param string $start
373
     * @param string $end
374
     * @return Xyster_Data_Expression
375
     */
376
    static public function notBetween( $field, $start, $end )
377
    {
378 2
        return new Xyster_Data_Expression($field, self::$_operators[__FUNCTION__], array($start, $end));
379
    }
380
381
    /**
382
     * In expression ( field IN ( 1,1,2,3,5,8,13,21,'fibonacci','sequence' ) )
383
     *
384
     * @param string $field
385
     * @param array $choices
386
     * @return Xyster_Data_Expression
387
     */
388
    static public function in( $field, array $choices )
389
    {
390 4
        return new Xyster_Data_Expression($field, self::$_operators[__FUNCTION__], $choices);
391
    }
392
393
    /**
394
     * Not in expression ( field NOT IN ( 1,1,2,3,5,8,13,21,'fibonacci','sequence' ) )
395
     *
396
     * @param string $field
397
     * @param array $choices
398
     * @return Xyster_Data_Expression
399
     */
400
    static public function notIn( $field, array $choices )
401
    {
402 3
        return new Xyster_Data_Expression($field, self::$_operators[__FUNCTION__], $choices);
403
    }
404
}


Report generated at 2007-10-08T19:32:24-05:00