http://phing.info/

Source Code Coverage

Designed for use with PHPUnit2, Xdebug and Phing.

Methods: 16 LOC: 307 Statements: 67

Source file Statements Methods Total coverage
Query.php 97.0% 100.0% 97.6%
   
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_Orm
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
 * @version   $Id: Query.php 202 2008-01-20 16:20:09Z doublecompile $
15
 */
16
/**
17
 * @see Xyster_Orm_Query_Parser
18
 */
19 1
require_once 'Xyster/Orm/Query/Parser.php';
20
/**
21
 * A query object
22
 *
23
 * @category  Xyster
24
 * @package   Xyster_Orm
25
 * @copyright Copyright (c) 2007-2008 Irrational Logic (http://irrationallogic.net)
26
 * @license   http://www.opensource.org/licenses/bsd-license.php New BSD License
27
 */
28
class Xyster_Orm_Query
29
{
30
    const WHERE = 'where';
31
    const ORDER = 'order';
32
    const LIMIT = 'limit';
33
    const OFFSET = 'offset';
34
35
    /**
36
     * The entity being queried
37
     *
38
     * @var string
39
     */
40
    protected $_class = '';
41
42
    /**
43
     * The parts of the query
44
     *
45
     * @var array
46
     */
47
    protected $_parts = array();
48
49
    /**
50
     * The parts of the query that can be used in the backend
51
     *
52
     * @var array
53
     */
54
    protected $_backend = array();
55
56
    /**
57
     * The orm manager
58
     *
59
     * @var Xyster_Orm_Manager
60
     */
61
    protected $_manager;
62
63
    /**
64
     * The query parser
65
     *
66
     * @var Xyster_Orm_Query_Parser
67
     */
68
    protected $_parser;
69
70
    /**
71
     * The parts of the query that must be used at runtime
72
     *
73
     * @var array
74
     */
75
    protected $_runtime = array();
76
77
    /**
78
     * Creates a new query object
79
     *
80
     * @param string $class  The entity to query
81
     */
82
    public function __construct( $class, Xyster_Orm_Manager $manager )
83
    {
84 39
        $this->_class = $class;
85 39
        $this->_manager = $manager;
86 39
        $this->_initParts();
87 39
        $this->_parser = new Xyster_Orm_Query_Parser($manager->getMapperFactory());
88
    }
89
90
    /**
91
     * Executes the query
92
     *
93
     * @return Xyster_Orm_Set
94
     */
95
    public function execute()
96
    {
97 2
        $map = $this->_manager->getMapperFactory()->get($this->_class);
98
99
        // execute the query in the backend
100 2
		$set = $this->_manager->executeQuery($this);
101
102
        // apply any runtime filters to the entity set
103 2
		if ( count($this->_runtime[self::WHERE]) ) {
104 1
    		$set->filter(Xyster_Data_Criterion::fromArray('AND', $this->_runtime[self::WHERE]));
105 1
		}
106
107
		// if the query is runtime, enforce the offset and limit
108 2
		if ( ( $this->_parts[self::LIMIT] || $this->_parts[self::OFFSET] )
109 2
		    && $this->isRuntime() ) {
110 1
			$entities = $map->getSet();
111 1
			$offset = 0;
112 1
			foreach( $set as $entity ) {
113 1
				if ( $offset < $this->_parts[self::OFFSET] ) {
114 1
				    $offset++;
115 1
				} else {
116 1
				    $entities->add($entity);
117
				}
118 1
				if ( $this->_parts[self::LIMIT] && count($entities) == $this->_parts[self::LIMIT] ) {
119 1
				    break;
120 0
				}
121 1
			}
122 1
			$set = $entities;
123 1
		}
124
125
		// apply any runtime sort ordering to the entity set
126 2
		if ( $this->_runtime[self::ORDER] ) {
127 1
			$set->sortBy($this->_parts[self::ORDER]);
128 1
		}
129 2
		return $set;
130
    }
131
132
    /**
133
     * Gets the criteria that can be run in the backend
134
     *
135
     * @return array
136
     */
137
    public function getBackendWhere()
138
    {
139 15
        return $this->_backend[self::WHERE];
140
    }
141
142
    /**
143
     * Gets the entity class being queried
144
     *
145
     * @return string the entity class name
146
     */
147
    public function getFrom()
148
    {
149 13
        return $this->_class;
150
    }
151
152
    /**
153
     * Gets the maximum number of results to be returned
154
     *
155
     * @return int the maximum result count
156
     */
157
    public function getLimit()
158
    {
159 5
        return $this->getPart(self::LIMIT);
160
    }
161
162
    /**
163
     * Gets the starting point in the results
164
     *
165
     * @return int the offset starting point
166
     */
167
    public function getOffset()
168
    {
169 4
        return $this->getPart(self::OFFSET);
170
    }
171
172
    /**
173
     * Gets the order clause (an array of {@link Xyster_Data_Sort} objects)
174
     *
175
     * @return array
176
     */
177
    public function getOrder()
178
    {
179 13
        return $this->getPart(self::ORDER);
180
    }
181
182
    /**
183
     * Gets a part of the query
184
     *
185
     * @param string $part one of the class constants
186
     * @return mixed
187
     */
188
    public function getPart( $part )
189
    {
190 28
        return ( array_key_exists($part, $this->_parts) ) ?
191 28
            $this->_parts[$part] : null;
192
    }
193
194
    /**
195
     * Gets the where clause (an array of {@link Xyster_Data_Criterion} objects)
196
     *
197
     * @return array
198
     */
199
    public function getWhere()
200
    {
201 7
        return $this->getPart(self::WHERE);
202
    }
203
204
    /**
205
     * Gets whether this query has an order clause that evaluates at runtime
206
     *
207
     * @return boolean
208
     */
209
    public function hasRuntimeOrder()
210
    {
211 25
        return (bool) $this->_runtime[self::ORDER];
212
    }
213
214
    /**
215
     * Gets whether this query has a where clause that evaluates at runtime
216
     *
217
     * @return boolean
218
     */
219
    public function hasRuntimeWhere()
220
    {
221 20
        return count($this->_runtime[self::WHERE]) > 0;
222
    }
223
224
    /**
225
     * Gets whether this query has parts that are evaluated at runtime
226
     *
227
     * @return boolean
228
     */
229
    public function isRuntime()
230
    {
231 25
        return $this->hasRuntimeOrder() || $this->hasRuntimeWhere();
232
    }
233
234
    /**
235
     * Impose a maximum number of records to return and a number to skip
236
     *
237
     * @param int $limit The maximum number of records to return
238
     * @param int $offset The number of records to skip
239
     * @return Xyster_Orm_Query provides a fluent interface
240
     */
241
    public function limit( $limit, $offset=0 )
242
    {
243 9
        $this->_parts[self::LIMIT] = intval($limit);
244 9
        $this->_parts[self::OFFSET] = intval($offset);
245 9
        return $this;
246
    }
247
248
    /**
249
     * Adds a sorting to the results
250
     *
251
     * @param Xyster_Data_Sort $order
252
     * @return Xyster_Orm_Query provides a fluent interface
253
     */
254
    public function order( Xyster_Data_Sort $order )
255
    {
256 11
        $this->_parser->assertValidFieldForClass($order->getField(), $this->_class);
257 11
        $this->_runtime[self::ORDER] |= $this->_parser->isRuntime($order, $this->_class);
258
259 11
        $this->_parts[self::ORDER][] = $order;
260
261 11
        return $this;
262
    }
263
264
    /**
265
     * Adds a criterion to the selection
266
     *
267
     * @param Xyster_Data_Criterion $where
268
     * @return Xyster_Orm_Query provides a fluent interface
269
     */
270
    public function where( Xyster_Data_Criterion $where )
271
    {
272 18
        foreach( Xyster_Data_Criterion::getFields($where) as $field ) {
273 18
            if ( $field instanceof Xyster_Data_Field_Aggregate ) {
274 2
                require_once 'Xyster/Orm/Query/Exception.php';
275 2
                throw new Xyster_Orm_Query_Exception('Aggregated fields are not allowed in this query');
276 0
            }
277 16
            $this->_parser->assertValidFieldForClass($field, $this->_class);
278 16
        }
279
280 16
        if ( $this->_parser->isRuntime($where, $this->_class) ) {
281 8
            $this->_runtime[self::WHERE][] = $where;
282 8
        } else {
283 13
            $this->_backend[self::WHERE][] = $where;
284
        }
285
286 16
        $this->_parts[self::WHERE][] = $where;
287
288 16
        return $this;
289
    }
290
291
    /**
292
     * Initializes the parts container
293
     *
294
     */
295
    protected function _initParts()
296
    {
297 39
        $this->_parts[self::LIMIT] = 0;
298 39
        $this->_parts[self::OFFSET] = 0;
299 39
        $this->_parts[self::WHERE] = array();
300 39
        $this->_parts[self::ORDER] = array();
301
302 39
        $this->_runtime[self::WHERE] = array();
303 39
        $this->_runtime[self::ORDER] = false;
304
305 39
        $this->_backend[self::WHERE] = array();
306
    }
307
}


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