http://phing.info/

Source Code Coverage

Designed for use with PHPUnit2, Xdebug and Phing.

Methods: 18 LOC: 644 Statements: 319

Source file Statements Methods Total coverage
Parser.php 95.6% 100.0% 95.8%
   
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_Orm
17
 * @copyright Copyright (c) 2007 Irrational Logic (http://devweblog.org)
18
 * @license   http://www.opensource.org/licenses/bsd-license.php New BSD License
19
 * @version   $Id: Parser.php 74 2007-08-19 15:49:31Z doublecompile $
20
 */
21
/**
22
 * @see Xyster_String
23
 */
24 1
require_once 'Xyster/String.php';
25
/**
26
 * A data entity: the basic data unit of the ORM package
27
 *
28
 * @category  XysterColumn
29
 * @package   Xyster_Orm
30
 * @copyright Copyright (c) 2007 Irrational Logic (http://devweblog.org)
31
 * @license   http://www.opensource.org/licenses/bsd-license.php New BSD License
32
 */
33
class Xyster_Orm_Query_Parser
34
{
35
    /**
36
     * The mapper factory
37
     *
38
     * @var Xyster_Orm_Mapper_Factory_Interface
39
     */
40
    protected $_mapFactory;
41
42
    /**
43
     * A cache for runtime evaluations
44
     *
45
     * @var unknown_type
46
     */
47
    static protected $_runtime = array();
48
49
    /**
50
     * Creates a new query parser
51
     *
52
     * @param Xyster_Orm_Mapper_Factory_Interface $mapFactory
53
     */
54
    public function __construct( Xyster_Orm_Mapper_Factory_Interface $mapFactory )
55
    {
56 92
        $this->_mapFactory = $mapFactory;
57
    }
58
59
    /**
60
     * Asserts a field's presence in a class' members
61
     *
62
     * @param string $field
63
     * @param string $className
64
     * @throws Xyster_Orm_Query_Parser_Exception
65
     */
66
    public function assertValidFieldForClass( $field, $className )
67
    {
68 32
        require_once 'Xyster/Orm/Relation.php';
69 32
        require_once 'Xyster/Orm/Entity/Meta.php';
70
71 32
        require_once 'Xyster/Orm/Loader.php';
72 32
        Xyster_Orm_Loader::loadEntityClass($className);
73 32
        $map = $this->_mapFactory->get($className);
74 32
        $meta = $map->getEntityMeta();
75
76 32
        $field = ( $field instanceof Xyster_Data_Field ) ?
77 32
            trim($field->getName()) : trim($field);
78
79 32
        require_once 'Xyster/Data/Field/Aggregate.php';
80 32
        $matches = Xyster_Data_Field_Aggregate::match($field);
81 32
        if ( count($matches) ) {
82 1
            $field = trim($matches["field"]);
83 1
        }
84
85 32
        $calls = Xyster_String::smartSplit("->", $field);
86
        /*
87
            for composite references (i.e.  supervisor->name )
88
            - check each column exists in its container
89
        */
90 32
        if ( count($calls) > 1 ) {
91
92 7
            $container = $className;
93 7
            $currentMeta = $meta;
94 7
            foreach( $calls as $k=>$v ) {
95 7
                $this->assertValidFieldForClass($v, $container);
96 7
                if ( $meta->isRelation($v) ) {
97 7
                    $details = $meta->getRelation($v);
98 7
                    if ( !$details->isCollection() ) {
99 7
                        $container = $details->getTo();
100 7
                        $currentMeta = $this->_mapFactory->get($container)->getEntityMeta();
101 7
                    } else {
102 1
                        break;
103
                    }
104 7
                } else {
105 7
                    break;
106
                }
107 7
            }
108
109 7
        } else {
110
111
            /*
112
                for method calls
113
                - check method exists in class
114
                - check any method parameters that may themselves be members
115
            */
116 32
            if ( preg_match("/^(?P<name>[a-z0-9_]+)(?P<meth>\((?P<args>[\w\W]*)\))$/i", $field, $matches) ) {
117 16
                if ( $className != "" && !in_array($matches['name'], $meta->getMembers()) ) {
118 1
                    require_once 'Xyster/Orm/Query/Parser/Exception.php';
119 1
                    throw new Xyster_Orm_Query_Parser_Exception($matches['name'] . ' is not a member of the ' . $className . ' class' );
120 0
                }
121 16
                $args = array();
122 16
                if ( strlen(trim($matches['args'])) ) {
123 9
                    foreach( Xyster_String::smartSplit(",", $matches['args']) as $v ) {
124 9
                        $v = trim($v);
125 9
                        $args[] = ( $this->isValidField($v) ) ?
126 1
                            $this->assertValidFieldForClass($v, $className) : $v;
127 9
                    }
128 9
                }
129
            /*
130
                for properties and relationships
131
                - check column exists in class
132
            */
133 32
            } else if ( $className != "" && !in_array($field, $meta->getMembers()) ) {
134 1
                require_once 'Xyster/Orm/Query/Parser/Exception.php';
135 1
                throw new Xyster_Orm_Query_Parser_Exception($field . ' is not a member of the ' . $className . ' class');
136 0
            }
137
        }
138
    }
139
140
    /**
141
     * Checks if a literal is a method call
142
     *
143
     * @param string $field
144
     * @return bool
145
     */
146
    public function isMethodCall( $field )
147
    {
148 15
        return (bool) preg_match("/^[a-z_][a-z0-9_]*\([\w\W]*\)$/i", $field);
149
    }
150
151
    /**
152
     * Verifies if a {@link Xyster_Data_Criterion} or {@link Xyster_Data_Field} is runtime
153
     *
154
     * @param object $object
155
     * @param string $class
156
     * @return bool
157
     */
158
    public function isRuntime( $object, $class )
159
    {
160 33
        if ( $object instanceof Xyster_Data_Criterion ) {
161
162 20
            foreach( Xyster_Data_Criterion::getFields($object) as $v ) {
163 20
                if ($this->isRuntime($v, $class)) {
164 12
                    return true;
165 0
                }
166 16
            }
167 16
            return false;
168
169 33
        } else if ( $object instanceof Xyster_Data_Field ) {
170
171 32
            $name = $object->getName();
172 32
            if ( !isset(self::$_runtime[$class][$name])) {
173 14
                self::$_runtime[$class][$name] = $this->_isRuntime($name,$class);
174 14
            }
175 32
            return self::$_runtime[$class][$name];
176
177 13
        } else if ( $object instanceof Xyster_Data_Sort ) {
178
179 12
            return $this->isRuntime($object->getField(), $class);
180
181 0
        }
182
183 1
        require_once 'Xyster/Orm/Query/Parser/Exception.php';
184 1
        throw new Xyster_Orm_Query_Parser_Exception('Unexpected type: ' . gettype($object));
185
    }
186
187
    /**
188
     * Checks a reference for syntactical correctness
189
     *
190
     * @param string $field
191
     * @return boolean
192
     */
193
    public function isValidField( $field )
194
    {
195 16
        $field = trim($field);
196
197 16
        $ok = true;
198 16
        if ( !preg_match("/^[a-z][a-z0-9_]*(->[a-z0-9_]+(\([\s]*\))?)*$/i", $field) ) {
199 16
            $mcs = Xyster_String::smartSplit("->", $field);
200 16
            foreach( $mcs as $mc ) {
201 16
                $matches = array();
202 16
                $match = preg_match( "/^[a-z][a-z0-9_]*(\((?P<params>[\w\W]*)\))?$/i", $mc, $matches );
203 16
                if ( ( $match && array_key_exists("params", $matches) && strlen(trim($matches['params']))
204 16
                && !$this->_checkMethodParameters($matches['params']) ) || !$match ) {
205 16
                    $ok = false;
206 16
                    break;
207 0
                }
208 1
            }
209 16
        }
210 16
        return $ok;
211
    }
212
213
    /**
214
     * Parse a statement into a Xyster_Data_Criterion
215
     *
216
     * @param string $statement
217
     * @return Xyster_Data_Criterion
218
     */
219
    public function parseCriterion( $statement )
220
    {
221 50
        require_once 'Xyster/Data/Junction.php';
222
223 50
        $crit = null;
224 50
        $statement = trim($statement);
225
226 50
        $groups = Xyster_String::matchGroups($statement);
227 50
        if ( count($groups) == 1 && strlen($groups[0]) == strlen($statement) ) {
228 31
            $statement = trim(substr($statement,1,-1));
229 31
        }
230
231 50
        $crits = Xyster_String::smartSplit(" AND ", $statement, true);
232
        // in case it split the and of a "BETWEEN x AND y"
233 50
        if ( count($crits) == 2 && $this->_checkLiteral($crits[1]) ) {
234 1
            $crits = array($statement);
235 1
        }
236
237 50
        if ( count($crits) < 2 ) {
238
239 50
            $subcrits = Xyster_String::smartSplit(" OR ", $statement, true);
240 50
            if ( count($subcrits) < 2 ) {
241 50
                $groups = Xyster_String::matchGroups(trim($subcrits[0]));
242 50
                $crit = ( count($groups) > 0 && strlen($groups[0]) ) ?
243 2
                    $this->parseCriterion($subcrits[0]) :
244 50
                    $this->parseExpression($subcrits[0]);
245 50
            } else {
246 2
                $criteria = array_map(array($this, 'parseCriterion'), $subcrits);
247 2
                $crit = Xyster_Data_Criterion::fromArray('OR', $criteria);
248
            }
249
250 50
        } else {
251
252 5
            $crit = Xyster_Data_Junction::all( $this->parseCriterion($crits[0]),
253 5
                $this->parseCriterion($crits[1]) );
254
255 5
            if ( count($crits) > 2 ) {
256 1
                for ( $i=2; $i<count($crits); $i++ ) {
257 1
                    $crit->add( $this->parseCriterion( $crits[$i] ) );
258 1
                }
259 1
            }
260
        }
261
262 50
        return $crit;
263
    }
264
265
    /**
266
     * Parse string statement as Expression
267
     *
268
     * @param string $statement
269
     * @return Xyster_Data_Expression
270
     * @throws Xyster_Orm_Query_Parser_Exception if the expression syntax is incorrect
271
     */
272
    public function parseExpression( $statement )
273
    {
274 55
        require_once 'Xyster/Data/Expression.php';
275
276
        // remove whitespace characters we don't like
277 55
        $statement = Xyster_String::smartSplit(" ", preg_replace("/[\t\n\r]+/", " ", trim($statement)));
278
279 55
        $exp = array();
280 55
        foreach( $statement as $v ) {
281 55
            if( $v != "" ) {
282 55
                $exp[] = $v;
283 55
            }
284 55
        }
285
286 55
        $leftlit = $this->parseField($exp[0]);
287
288 55
        array_shift($exp);
289 55
        $upper0 = strtoupper($exp[0]);
290 55
        $upper1 = strtoupper($exp[1]);
291
292 55
        if ( $upper0 == "NOT" || ( $upper0 == "IS" && $upper1 == "NOT" ) ) {
293 2
            $operator = $upper0 . " " . $upper1;
294 2
            array_shift($exp);
295 2
        } else {
296 54
            $operator = $upper0;
297
        }
298
299 55
        if ( !Xyster_Data_Expression::isOperator($operator) ) {
300 1
            require_once 'Xyster/Orm/Query/Parser/Exception.php';
301 1
            throw new Xyster_Orm_Query_Parser_Exception('Invalid expression operator: ' . $operator);
302 0
        }
303
304 54
        array_shift($exp);
305
306 54
        if ( ( $operator == "BETWEEN" || $operator == "NOT BETWEEN" ) && count($exp) != 3 ) {
307 1
            require_once 'Xyster/Orm/Query/Parser/Exception.php';
308 1
            throw new Xyster_Orm_Query_Parser_Exception('Invalid literal: ' . implode(" ",$exp));
309 0
        }
310
311 53
        if ( $operator == "IN" || $operator == "NOT IN" ) {
312 2
            $rightlit = trim(implode(" ",$exp));
313 2
            $matches = array();
314 2
            if ( !preg_match('/^\([\s]*(?P<choices>.*)[\s]*\)$/',$rightlit,$matches) ) {
315 1
                require_once 'Xyster/Orm/Query/Parser/Exception.php';
316 1
                throw new Xyster_Orm_Query_Parser_Exception('Invalid literal: ' . $rightlit);
317 0
            }
318
            else {
319 1
                $inChoices = Xyster_String::smartSplit(',',$matches['choices']);
320 1
                foreach( $inChoices as $k=>$choice ) {
321 1
                    $choice = trim($choice);
322 1
                    $this->_assertLiteral($choice);
323 1
                    if ( preg_match('/^"[^"]*"$/i',$choice) )
324 1
                        $inChoices[$k] = substr($choice,1,-1);
325 1
                }
326 1
                $rightlit = $inChoices;
327
            }
328 1
        } else {
329 51
            $rightlit = ( $operator == "BETWEEN" || $operator == "NOT BETWEEN" ) ?
330 51
                array( $exp[0], $exp[2] ) : $exp[0];
331 51
            $this->_assertLiteral($rightlit);
332
        }
333
334 51
        if ( !is_array($rightlit) && preg_match('/^"[^"]*"$/i',$rightlit) ) {
335 7
            $rightlit = substr($rightlit,1,-1);
336 7
        }
337
338 51
        $args = array( $leftlit );
339 51
        if ( in_array($operator, array("=","<>",">",">=","<","<=","LIKE","NOT LIKE",'IN','NOT IN')) ) {
340 51
            $args[] = $rightlit;
341 51
        } else if ( $operator == "BETWEEN" || $operator == "NOT BETWEEN" ) {
342 1
            $args[] = $rightlit[0];
343 1
            $args[] = $rightlit[1];
344 1
        }
345
346 51
        return call_user_func_array(array("Xyster_Data_Expression",
347 51
            Xyster_Data_Expression::getMethodName($operator)), $args);
348
    }
349
350
    /**
351
     * Parse a string as Field
352
     *
353
     * @param string $name
354
     * @return Xyster_Data_Field
355
     */
356
    public function parseField( $name )
357
    {
358 58
        $name = trim($name);
359
360 58
        require_once 'Xyster/Data/Field/Aggregate.php';
361 58
        $match = Xyster_Data_Field_Aggregate::match($name);
362
363 58
        if ( $match ) {
364 3
            require_once 'Xyster/Enum.php';
365 3
            $function = Xyster_Enum::valueOf('Xyster_Data_Aggregate', strtoupper($match['function']));
366 3
            $field = Xyster_Data_Field::aggregate($function, trim($match['field']));
367 3
        } else {
368 57
            $field = Xyster_Data_Field::named($name);
369
        }
370
371 58
        return $field;
372
    }
373
374
    /**
375
     * Parse a string as Field with alias
376
     *
377
     * @param string $name
378
     * @return Xyster_Data_Field
379
     */
380
    public function parseFieldAlias( $statement )
381
    {
382 3
        $statement = trim($statement);
383 3
        $matches = array();
384 3
        $alias = $statement;
385 3
        $pattern = '/[\s]+(AS[\s]+(?P<aliasA>[a-z0-9_]+)|"(?P<aliasQ>[a-z0-9_]+)")/i';
386
387 3
        if (preg_match($pattern, $statement, $matches)) {
388 2
            if (!empty($matches['aliasA']) || !empty($matches['aliasQ'])) {
389 2
                $alias = (!empty($matches['aliasA'])) ?
390 2
                    $matches['aliasA'] : $matches['aliasQ'];
391 2
            }
392 2
            $statement = str_replace($matches[0], "", $statement);
393 2
        }
394
395 3
        $field = $this->parseField($statement);
396 3
        $field->setAlias($alias);
397 3
        return $field;
398
    }
399
400
    /**
401
     * Parses string statement as Xyster_Orm_Query
402
     *
403
     * @param Xyster_Orm_Query $query
404
     * @param string $statement
405
     */
406
    public function parseQuery( Xyster_Orm_Query $query, $statement )
407
    {
408 2
        $expecting = array('where','order');
409
410 2
        $parts = $this->_baseParseQuery($query, $statement, $expecting);
411 2
        if ( !empty($parts['where']) ) {
412 2
            $query->where($this->parseCriterion($parts['where']));
413 2
        }
414 2
        if ( !empty($parts['order']) ) {
415 1
            $this->_parseClause($query, 'order', $parts['order']);
416 1
        }
417
    }
418
419
    /**
420
     * Parses string statement as Xyster_Orm_Query_Report
421
     *
422
     * @param Xyster_Orm_Query_Report $query
423
     * @param string $statement
424
     */
425
    public function parseReportQuery( Xyster_Orm_Query_Report $query, $statement )
426
    {
427 2
        $expecting = array('select','where','group','having','order');
428
429 2
        $parts = $this->_baseParseQuery($query,$statement,$expecting);
430 2
        if ( empty($parts['select']) ) {
431 1
            require_once 'Xyster/Orm/Query/Parser/Exception.php';
432 1
            throw new Xyster_Orm_Query_Parser_Exception('Invalid statement: ' . $statement);
433 0
        }
434
435 2
        $matches = array();
436 2
        if (preg_match('/^distinct[[:space:]]+/i', $parts['select'], $matches)) {
437 1
            $query->distinct(true);
438 1
            $parts['select'] = str_replace($matches[0], '', $parts['select']);
439 1
        }
440
441 2
        $this->_parseClause($query, 'select', $parts['select']);
442 2
        if ( !empty($parts['where']) ) {
443 2
            $query->where($this->parseCriterion($parts['where']));
444 2
        }
445 2
        if ( !empty($parts['order']) ) {
446 1
            $this->_parseClause($query, 'order', $parts['order']);
447 1
        }
448 2
        if ( !empty($parts['group']) ) {
449 1
            $this->_parseClause($query, 'group', $parts['group']);
450 1
        }
451 2
        if ( !empty($parts['having']) ) {
452 1
            $query->having($this->parseCriterion($parts['having']));
453 1
        }
454
    }
455
456
    /**
457
     * Parse string statement as a {@link Xyster_Data_Sort}
458
     *
459
     * @param string $statement
460
     * @return Xyster_Data_Sort
461
     * @throws Xyster_Orm_Query_Parser_Exception  if the statement syntax is invalid
462
     */
463
    public function parseSort( $statement )
464
    {
465 3
        $statement = trim($statement);
466 3
        $matches = array();
467 3
        $dir = 'ASC';
468
469 3
        if ( preg_match('/\s+(?P<dir>ASC|DESC)$/i', $statement, $matches) ) {
470 3
            $dir = $matches["dir"];
471 3
            $statement = trim(str_replace($matches[0], "", $statement));
472 3
        }
473
474 3
        $field = $this->parseField($statement);
475 3
        return (!strcasecmp($dir, 'DESC')) ? $field->desc() : $field->asc();
476
    }
477
478
    /**
479
     * Asserts a literal for syntactical correctness
480
     *
481
     * @param string $lit
482
     * @throws Xyster_Orm_Query_Parser_Exception if the syntax is incorrect
483
     */
484
    protected function _assertLiteral( $lit )
485
    {
486 52
        if ( is_array($lit) ) {
487 1
            foreach( $lit as $v ) {
488 1
                $this->_assertLiteral($v);
489 1
            }
490 52
        } else if ( !$this->_checkLiteral($lit) ) {
491 1
            require_once 'Xyster/Orm/Query/Parser/Exception.php';
492 1
            throw new Xyster_Orm_Query_Parser_Exception('Invalid literal: ' . $lit);
493 0
        }
494
    }
495
496
    /**
497
     * Removes the limit and offset clause from a statement
498
     *
499
     * @param Xyster_Orm_Query $query  The query into which the parts are set
500
     * @param string $statement  The statement to parse
501
     * @param array $expecting
502
     * @return array  The statement split by parts
503
     */
504
    protected function _baseParseQuery( Xyster_Orm_Query $query, $statement, array $expecting )
505
    {
506 3
        $matches = array();
507 3
        if ( preg_match('/[\s]*LIMIT (?P<limit>[\d]+)( OFFSET (?P<offset>[\d]+))?$/i',$statement,$matches) ) {
508 2
            $statement = str_replace($matches[0], '', $statement);
509 2
        }
510 3
        $limit = ( isset($matches['limit']) ) ? $matches['limit'] : 0;
511 3
        $offset = ( isset($matches['offset']) ) ? $matches['offset'] : 0;
512 3
        if ( $limit ) {
513 2
            $query->limit($limit,$offset);
514 2
        }
515
516 3
        $parts = array();
517 3
        $part = '';
518 3
        $split = Xyster_String::smartSplit(' ', trim($statement));
519
520 3
        foreach( $split as $v ) {
521 3
            if ( in_array($part, array('order','group')) && !strcasecmp($v, 'by') ) {
522 2
                continue;
523 0
            }
524 3
            foreach( $expecting as $epart ) {
525 3
                if ( !strcasecmp($v, $epart) ) {
526 3
                    $part = strtolower($v);
527 3
                }
528 3
            }
529 3
            if ( !in_array(strtolower($v), $expecting) ) {
530 3
                if ( !isset($parts[$part]) ) {
531 3
                    $parts[$part] = "";
532 3
                }
533 3
                $parts[$part] .= $v . " ";
534 3
            }
535 3
        }
536
537 3
        return $parts;
538
    }
539
540
    /**
541
     * Checks a literal for syntactical correctness
542
     *
543
     * @param string $lit
544
     * @return boolean
545
     */
546
    protected function _checkLiteral( $lit )
547
    {
548
        return (
549
            // either a string or a number or the word "null"
550 53
            preg_match("/^(\"[^\"]*\"|[\d]+(.[\d]+)?|null)$/i", trim($lit))
551
            //  a string with escapes in it
552 7
            || preg_match('/^"[^"\\\\]*(\\\\.[^"\\\\]*)*"$/', trim($lit))
553
            // check to see if it's a field
554 7
            || $this->isValidField($lit)
555 53
        );
556
    }
557
558
    /**
559
     * Checks method parameters for syntactical correctness
560
     *
561
     * @param array $params
562
     * @return boolean
563
     */
564
    protected function _checkMethodParameters( $params )
565
    {
566 1
        $ps = Xyster_String::smartSplit(",", trim($params));
567 1
        $ok = true;
568 1
        foreach( $ps as $p ) {
569 1
            if ( !$this->_checkLiteral($p) ) {
570 1
                $ok = false;
571 1
                break;
572 0
            }
573 1
        }
574 1
        return $ok;
575
    }
576
577
    /**
578
     * Checks to see if a column can only be evaluated at runtime
579
     *
580
     * @param string $field
581
     * @param string $className
582
     * @return boolean
583
     */
584
    protected function _isRuntime( $field, $className )
585
    {
586 14
        require_once 'Xyster/Orm/Loader.php';
587 14
        Xyster_Orm_Loader::loadEntityClass($className);
588 14
        $meta = $this->_mapFactory->get($className)->getEntityMeta();
589
590 14
        $calls = Xyster_String::smartSplit('->',trim($field));
591
592 14
        if ( count($calls) == 1 ) {
593
594
            // the call isn't composite - could be a member or a relation
595 14
            return ( $this->isMethodCall($calls[0]) ) ? true :
596 8
                ( !in_array($field, $meta->getFieldNames())
597 14
                    && !$meta->isRelation($field) );
598
599 0
        } else {
600
601
            // the call is composite - loop through to see if we can figure
602
            // out the type bindings
603 3
            $container = $className;
604 3
            $currentMeta = $meta;
605 3
            foreach( $calls as $call ) {
606 3
                if ( $this->isMethodCall($call) ) {
607 1
                    return true;
608 0
                } else {
609 3
                    $isRel = $currentMeta->isRelation($call);
610 3
                    if ( !in_array($call, array_keys($currentMeta->getFields()))
611 3
                        && !$isRel ) {
612 1
                        return true;
613 3
                    } else if ( $isRel ) {
614 3
                        $container = $currentMeta->getRelation($call)->getTo();
615 3
                        $currentMeta = $this->_mapFactory->get($container)->getEntityMeta();
616 3
                    }
617
                }
618 3
            }
619 3
            return false;
620
621
        }
622
    }
623
624
    /**
625
     * Parses a string statement clause into its corresponding parts
626
     *
627
     * @param Xyster_Orm_Query $query The query into which the parts will be set
628
     * @param string $type  The type of clause (either select, group, or order)
629
     * @param string $statement  The actual clause to parse
630
     */
631
    protected function _parseClause( Xyster_Orm_Query $query, $type, $statement )
632
    {
633
        $call = array(
634 3
                'select'=>array($this, 'parseFieldAlias'),
635 3
                'order'=>array($this, 'parseSort'),
636 3
                'group'=>array('Xyster_Data_Field', 'group')
637 3
            );
638 3
        $method = array('select'=>'field', 'order'=>'order', 'group'=>'group');
639
640 3
        foreach( Xyster_String::smartSplit(",", $statement) as $item ) {
641 3
            $query->{$method[$type]}( call_user_func($call[$type], $item) );
642 3
        }
643
    }
644
}


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