http://phing.info/

Source Code Coverage

Designed for use with PHPUnit2, Xdebug and Phing.

Methods: 20 LOC: 399 Statements: 103

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


Report generated at 2008-01-20T12:13:39-05:00