[BUGFIX] ConfigurationManager use FrontendSimulator only if neccessary
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / Persistence / Query.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2009 Jochen Rau <jochen.rau@typoplanet.de>
6 * All rights reserved
7 *
8 * This class is a backport of the corresponding class of FLOW3.
9 * All credits go to the v5 team.
10 *
11 * This script is part of the TYPO3 project. The TYPO3 project is
12 * free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * The GNU General Public License can be found at
18 * http://www.gnu.org/copyleft/gpl.html.
19 *
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27
28 /**
29 * The Query class used to run queries against the database
30 *
31 * @package Extbase
32 * @subpackage Persistence
33 * @version $Id$
34 * @scope prototype
35 * @api
36 */
37 class Tx_Extbase_Persistence_Query implements Tx_Extbase_Persistence_QueryInterface {
38
39 /**
40 * @var string
41 */
42 protected $type;
43
44 /**
45 * @var Tx_Extbase_Object_ObjectManagerInterface
46 */
47 protected $objectManager;
48
49 /**
50 * @var Tx_Extbase_Persistence_Mapper_DataMapper
51 */
52 protected $dataMapper;
53
54 /**
55 * @var Tx_Extbase_Persistence_ManagerInterface
56 */
57 protected $persistenceManager;
58
59 /**
60 * @var Tx_Extbase_Persistence_QOM_QueryObjectModelFactory
61 */
62 protected $qomFactory;
63
64 /**
65 * @var Tx_Extbase_Persistence_QOM_SourceInterface
66 */
67 protected $source;
68
69 /**
70 * @var Tx_Extbase_Persistence_QOM_ConstraintInterface
71 */
72 protected $constraint;
73
74 /**
75 * @var Tx_Extbase_Persistence_QOM_Statement
76 */
77 protected $statement;
78
79 /**
80 * @var int
81 */
82 protected $orderings = array();
83
84 /**
85 * @var int
86 */
87 protected $limit;
88
89 /**
90 * @var int
91 */
92 protected $offset;
93
94 /**
95 * The query settings.
96 *
97 * @var Tx_Extbase_Persistence_QuerySettingsInterface
98 */
99 protected $querySettings;
100
101 /**
102 * Constructs a query object working on the given class name
103 *
104 * @param string $type
105 */
106 public function __construct($type) {
107 $this->type = $type;
108 }
109
110 /**
111 * @param Tx_Extbase_Object_ObjectManagerInterface $objectManager
112 * @return void
113 */
114 public function injectObjectManager(Tx_Extbase_Object_ObjectManagerInterface $objectManager) {
115 $this->objectManager = $objectManager;
116 }
117
118 /**
119 * Injects the persistence manager, used to fetch the CR session
120 *
121 * @param Tx_Extbase_Persistence_ManagerInterface $persistenceManager
122 * @return void
123 */
124 public function injectPersistenceManager(Tx_Extbase_Persistence_ManagerInterface $persistenceManager) {
125 $this->persistenceManager = $persistenceManager;
126 }
127
128 /**
129 * Injects the DataMapper to map nodes to objects
130 *
131 * @param Tx_Extbase_Persistence_Mapper_DataMapper $dataMapper
132 * @return void
133 */
134 public function injectDataMapper(Tx_Extbase_Persistence_Mapper_DataMapper $dataMapper) {
135 $this->dataMapper = $dataMapper;
136 }
137
138 /**
139 * Injects the Query Object Model Factory
140 *
141 * @param Tx_Extbase_Persistence_QOM_QueryObjectModelFactory $qomFactory
142 * @return void
143 */
144 public function injectQomFactory(Tx_Extbase_Persistence_QOM_QueryObjectModelFactory $qomFactory) {
145 $this->qomFactory = $qomFactory;
146 }
147
148 /**
149 * Sets the Query Settings. These Query settings must match the settings expected by
150 * the specific Storage Backend.
151 *
152 * @param Tx_Extbase_Persistence_QuerySettingsInterface $querySettings The Query Settings
153 * @return void
154 * @api This method is not part of FLOW3 API
155 */
156 public function setQuerySettings(Tx_Extbase_Persistence_QuerySettingsInterface $querySettings) {
157 $this->querySettings = $querySettings;
158 }
159
160 /**
161 * Returns the Query Settings.
162 *
163 * @return Tx_Extbase_Persistence_QuerySettingsInterface $querySettings The Query Settings
164 * @api This method is not part of FLOW3 API
165 */
166 public function getQuerySettings() {
167 if (!($this->querySettings instanceof Tx_Extbase_Persistence_QuerySettingsInterface)) throw new Tx_Extbase_Persistence_Exception('Tried to get the query settings without seting them before.', 1248689115);
168 return $this->querySettings;
169 }
170
171 /**
172 * Returns the type this query cares for.
173 *
174 * @return string
175 * @api
176 */
177 public function getType() {
178 return $this->type;
179 }
180
181 /**
182 * Sets the source to fetch the result from
183 *
184 * @param Tx_Extbase_Persistence_QOM_SourceInterface $source
185 */
186 public function setSource(Tx_Extbase_Persistence_QOM_SourceInterface $source) {
187 $this->source = $source;
188 }
189
190 /**
191 * Returns the selectorn name or an empty string, if the source is not a selector
192 * // TODO This has to be checked at another place
193 * @return string The selector name
194 */
195 protected function getSelectorName() {
196 if ($this->getSource() instanceof Tx_Extbase_Persistence_QOM_SelectorInterface) {
197 return $this->source->getSelectorName();
198 } else {
199 return '';
200 }
201 }
202
203 /**
204 * Gets the node-tuple source for this query.
205 *
206 * @return Tx_Extbase_Persistence_QOM_SourceInterface the node-tuple source; non-null
207 */
208 public function getSource() {
209 if ($this->source === NULL) {
210 $this->source = $this->qomFactory->selector($this->getType(), $this->dataMapper->convertClassNameToTableName($this->getType()));
211 }
212 return $this->source;
213 }
214
215 /**
216 * Executes the query against the database and returns the result
217 *
218 * @return Tx_Extbase_Persistence_QueryResultInterface|array The query result object or an array if $this->getQuerySettings()->getReturnRawQueryResult() is TRUE
219 * @api
220 */
221 public function execute() {
222 if ($this->getQuerySettings()->getReturnRawQueryResult() === TRUE) {
223 return $this->persistenceManager->getObjectDataByQuery($this);
224 } else {
225 return $this->objectManager->create('Tx_Extbase_Persistence_QueryResultInterface', $this);
226 }
227 }
228
229 /**
230 * Executes the number of matching objects for the query
231 *
232 * @return integer The number of matching objects
233 * @deprecated since Extbase 1.3.0; was removed in FLOW3; will be removed in Extbase 1.5.0; use Query::execute()::count() instead
234 */
235 public function count() {
236 t3lib_div::logDeprecatedFunction();
237 return $this->persistenceManager->getObjectCountByQuery($this);
238 }
239
240 /**
241 * Sets the property names to order the result by. Expected like this:
242 * array(
243 * 'foo' => Tx_Extbase_Persistence_QueryInterface::ORDER_ASCENDING,
244 * 'bar' => Tx_Extbase_Persistence_QueryInterface::ORDER_DESCENDING
245 * )
246 * where 'foo' and 'bar' are property names.
247 *
248 * @param array $orderings The property names to order by
249 * @return Tx_Extbase_Persistence_QueryInterface
250 * @api
251 */
252 public function setOrderings(array $orderings) {
253 $this->orderings = $orderings;
254 return $this;
255 }
256
257 /**
258 * Returns the property names to order the result by. Like this:
259 * array(
260 * 'foo' => Tx_Extbase_Persistence_QueryInterface::ORDER_ASCENDING,
261 * 'bar' => Tx_Extbase_Persistence_QueryInterface::ORDER_DESCENDING
262 * )
263 *
264 * @return array
265 * @api
266 */
267 public function getOrderings() {
268 return $this->orderings;
269 }
270
271 /**
272 * Sets the maximum size of the result set to limit. Returns $this to allow
273 * for chaining (fluid interface)
274 *
275 * @param integer $limit
276 * @return Tx_Extbase_Persistence_QueryInterface
277 * @api
278 */
279 public function setLimit($limit) {
280 if (!is_int($limit) || $limit < 1) throw new InvalidArgumentException('The limit must be an integer >= 1', 1245071870);
281 $this->limit = $limit;
282 return $this;
283 }
284
285 /**
286 * Resets a previously set maximum size of the result set. Returns $this to allow
287 * for chaining (fluid interface)
288 *
289 * @return Tx_Extbase_Persistence_QueryInterface
290 * @api
291 */
292 public function unsetLimit() {
293 unset($this->limit);
294 return $this;
295 }
296
297 /**
298 * Returns the maximum size of the result set to limit.
299 *
300 * @param integer
301 * @api
302 */
303 public function getLimit() {
304 return $this->limit;
305 }
306
307 /**
308 * Sets the start offset of the result set to offset. Returns $this to
309 * allow for chaining (fluid interface)
310 *
311 * @param integer $offset
312 * @return Tx_Extbase_Persistence_QueryInterface
313 * @api
314 */
315 public function setOffset($offset) {
316 if (!is_int($offset) || $offset < 0) throw new InvalidArgumentException('The offset must be a positive integer', 1245071872);
317 $this->offset = $offset;
318 return $this;
319 }
320
321 /**
322 * Returns the start offset of the result set.
323 *
324 * @return integer
325 * @api
326 */
327 public function getOffset() {
328 return $this->offset;
329 }
330
331 /**
332 * The constraint used to limit the result set. Returns $this to allow
333 * for chaining (fluid interface)
334 *
335 * @param Tx_Extbase_Persistence_QOM_ConstraintInterface $constraint
336 * @return Tx_Extbase_Persistence_QueryInterface
337 * @api
338 */
339 public function matching($constraint) {
340 $this->constraint = $constraint;
341 return $this;
342 }
343
344 /**
345 * Sets the statement of this query programmatically. If you use this, you will lose the abstraction from a concrete storage
346 * backend (database).
347 *
348 * @param string $statement The statement
349 * @param array $paramerters An array of parameters. These will be bound to placeholders '?' in the $statement.
350 * @return Tx_Extbase_Persistence_QueryInterface
351 */
352 public function statement($statement, array $parameters = array()) {
353 $this->statement = $this->qomFactory->statement($statement, $parameters);
354 return $this;
355 }
356
357 /**
358 * Returns the statement of this query.
359 *
360 * @return Tx_Extbase_Persistence_QOM_Statement
361 */
362 public function getStatement() {
363 return $this->statement;
364 }
365
366 /**
367 * Gets the constraint for this query.
368 *
369 * @return Tx_Extbase_Persistence_QOM_Constraint the constraint, or null if none
370 * @api
371 */
372 public function getConstraint() {
373 return $this->constraint;
374 }
375
376 /**
377 * Performs a logical conjunction of the given constraints. The method takes one or more contraints and concatenates them with a boolean AND.
378 * It also scepts a single array of constraints to be concatenated.
379 *
380 * @param mixed $constraint1 The first of multiple constraints or an array of constraints.
381 * @return Tx_Extbase_Persistence_QOM_AndInterface
382 * @api
383 */
384 public function logicalAnd($constraint1) {
385 if (is_array($constraint1)) {
386 $resultingConstraint = array_shift($constraint1);
387 $constraints = $constraint1;
388 } else {
389 $constraints = func_get_args();
390 $resultingConstraint = array_shift($constraints);
391 }
392 if ($resultingConstraint === NULL) {
393 throw new Tx_Extbase_Persistence_Exception_InvalidNumberOfConstraints('There must be at least one constraint or a non-empty array of constraints given.', 1268056288);
394 }
395 foreach ($constraints as $constraint) {
396 $resultingConstraint = $this->qomFactory->_and(
397 $resultingConstraint,
398 $constraint
399 );
400 }
401 return $resultingConstraint;
402 }
403
404 /**
405 * Performs a logical disjunction of the two given constraints
406 *
407 * @param mixed $constraint1 The first of multiple constraints or an array of constraints.
408 * @return Tx_Extbase_Persistence_QOM_OrInterface
409 * @api
410 */
411 public function logicalOr($constraint1) {
412 if (is_array($constraint1)) {
413 $resultingConstraint = array_shift($constraint1);
414 $constraints = $constraint1;
415 } else {
416 $constraints = func_get_args();
417 $resultingConstraint = array_shift($constraints);
418 }
419 if ($resultingConstraint === NULL) {
420 throw new Tx_Extbase_Persistence_Exception_InvalidNumberOfConstraints('There must be at least one constraint or a non-empty array of constraints given.', 1268056288);
421 }
422 foreach ($constraints as $constraint) {
423 $resultingConstraint = $this->qomFactory->_or(
424 $resultingConstraint,
425 $constraint
426 );
427 }
428 return $resultingConstraint;
429 }
430
431 /**
432 * Performs a logical negation of the given constraint
433 *
434 * @param object $constraint Constraint to negate
435 * @return Tx_Extbase_Persistence_QOM_NotInterface
436 * @api
437 */
438 public function logicalNot($constraint) {
439 return $this->qomFactory->not($constraint);
440 }
441
442 /**
443 * Matches against the (internal) uid.
444 *
445 * @param int $uid The uid to match against
446 * @return Tx_Extbase_Persistence_QOM_ComparisonInterface
447 * @deprecated since Extbase 1.2.0; was removed in FLOW3; will be removed in Extbase 1.4.0; use equals() instead
448 */
449 public function withUid($operand) {
450 t3lib_div::logDeprecatedFunction();
451 return $this->qomFactory->comparison(
452 $this->qomFactory->propertyValue('uid', $this->getSelectorName()),
453 Tx_Extbase_Persistence_QueryInterface::OPERATOR_EQUAL_TO,
454 $operand
455 );
456 }
457
458 /**
459 * Returns an equals criterion used for matching objects against a query
460 *
461 * @param string $propertyName The name of the property to compare against
462 * @param mixed $operand The value to compare with
463 * @param boolean $caseSensitive Whether the equality test should be done case-sensitive
464 * @return Tx_Extbase_Persistence_QOM_ComparisonInterface
465 * @api
466 */
467 public function equals($propertyName, $operand, $caseSensitive = TRUE) {
468 if (is_object($operand) || $caseSensitive) {
469 $comparison = $this->qomFactory->comparison(
470 $this->qomFactory->propertyValue($propertyName, $this->getSelectorName()),
471 Tx_Extbase_Persistence_QueryInterface::OPERATOR_EQUAL_TO,
472 $operand
473 );
474 } else {
475 $comparison = $this->qomFactory->comparison(
476 $this->qomFactory->lowerCase(
477 $this->qomFactory->propertyValue($propertyName, $this->getSelectorName())
478 ),
479 Tx_Extbase_Persistence_QueryInterface::OPERATOR_EQUAL_TO,
480 strtolower($operand)
481 );
482 }
483
484 return $comparison;
485 }
486
487 /**
488 * Returns a like criterion used for matching objects against a query
489 *
490 * @param string $propertyName The name of the property to compare against
491 * @param mixed $operand The value to compare with
492 * @return Tx_Extbase_Persistence_QOM_ComparisonInterface
493 * @api
494 */
495 public function like($propertyName, $operand) {
496 return $this->qomFactory->comparison(
497 $this->qomFactory->propertyValue($propertyName, $this->getSelectorName()),
498 Tx_Extbase_Persistence_QueryInterface::OPERATOR_LIKE,
499 $operand
500 );
501 }
502
503 /**
504 * Returns a "contains" criterion used for matching objects against a query.
505 * It matches if the multivalued property contains the given operand.
506 *
507 * @param string $propertyName The name of the (multivalued) property to compare against
508 * @param mixed $operand The value to compare with
509 * @return Tx_Extbase_Persistence_QOM_ComparisonInterface
510 * @api
511 */
512 public function contains($propertyName, $operand){
513 return $this->qomFactory->comparison(
514 $this->qomFactory->propertyValue($propertyName, $this->getSelectorName()),
515 Tx_Extbase_Persistence_QueryInterface::OPERATOR_CONTAINS,
516 $operand
517 );
518 }
519
520 /**
521 * Returns an "in" criterion used for matching objects against a query. It
522 * matches if the property's value is contained in the multivalued operand.
523 *
524 * @param string $propertyName The name of the property to compare against
525 * @param mixed $operand The value to compare with, multivalued
526 * @return Tx_Extbase_Persistence_QOM_ComparisonInterface
527 * @api
528 */
529 public function in($propertyName, $operand) {
530 if (!is_array($operand) && (!$operand instanceof ArrayAccess) && (!$operand instanceof Traversable)) {
531 throw new Tx_Extbase_Persistence_Exception_UnexpectedTypeException('The "in" operator must be given a mutlivalued operand (array, ArrayAccess, Traversable).', 1264678095);
532 }
533
534 return $this->qomFactory->comparison(
535 $this->qomFactory->propertyValue($propertyName, $this->getSelectorName()),
536 Tx_Extbase_Persistence_QueryInterface::OPERATOR_IN,
537 $operand
538 );
539 }
540
541 /**
542 * Returns a less than criterion used for matching objects against a query
543 *
544 * @param string $propertyName The name of the property to compare against
545 * @param mixed $operand The value to compare with
546 * @return Tx_Extbase_Persistence_QOM_ComparisonInterface
547 * @api
548 */
549 public function lessThan($propertyName, $operand) {
550 return $this->qomFactory->comparison(
551 $this->qomFactory->propertyValue($propertyName, $this->getSelectorName()),
552 Tx_Extbase_Persistence_QueryInterface::OPERATOR_LESS_THAN,
553 $operand
554 );
555 }
556
557 /**
558 * Returns a less or equal than criterion used for matching objects against a query
559 *
560 * @param string $propertyName The name of the property to compare against
561 * @param mixed $operand The value to compare with
562 * @return Tx_Extbase_Persistence_QOM_ComparisonInterface
563 * @api
564 */
565 public function lessThanOrEqual($propertyName, $operand) {
566 return $this->qomFactory->comparison(
567 $this->qomFactory->propertyValue($propertyName, $this->getSelectorName()),
568 Tx_Extbase_Persistence_QueryInterface::OPERATOR_LESS_THAN_OR_EQUAL_TO,
569 $operand
570 );
571 }
572
573 /**
574 * Returns a greater than criterion used for matching objects against a query
575 *
576 * @param string $propertyName The name of the property to compare against
577 * @param mixed $operand The value to compare with
578 * @return Tx_Extbase_Persistence_QOM_ComparisonInterface
579 * @api
580 */
581 public function greaterThan($propertyName, $operand) {
582 return $this->qomFactory->comparison(
583 $this->qomFactory->propertyValue($propertyName, $this->getSelectorName()),
584 Tx_Extbase_Persistence_QueryInterface::OPERATOR_GREATER_THAN,
585 $operand
586 );
587 }
588
589 /**
590 * Returns a greater than or equal criterion used for matching objects against a query
591 *
592 * @param string $propertyName The name of the property to compare against
593 * @param mixed $operand The value to compare with
594 * @return Tx_Extbase_Persistence_QOM_ComparisonInterface
595 * @api
596 */
597 public function greaterThanOrEqual($propertyName, $operand) {
598 return $this->qomFactory->comparison(
599 $this->qomFactory->propertyValue($propertyName, $this->getSelectorName()),
600 Tx_Extbase_Persistence_QueryInterface::OPERATOR_GREATER_THAN_OR_EQUAL_TO,
601 $operand
602 );
603 }
604
605 /**
606 * @return void
607 */
608 public function __wakeup() {
609 $this->objectManager = t3lib_div::makeInstance('Tx_Extbase_Object_ObjectManager');
610 $this->persistenceManager = $this->objectManager->get('Tx_Extbase_Persistence_ManagerInterface');
611 $this->dataMapper = $this->objectManager->get('Tx_Extbase_Persistence_Mapper_DataMapper');
612 $this->qomFactory = $this->objectManager->get('Tx_Extbase_Persistence_QOM_QueryObjectModelFactory');
613 }
614
615 /**
616 * @return array
617 */
618 public function __sleep() {
619 return array('type', 'source', 'constraint', 'statement', 'orderings', 'limit', 'offset', 'querySettings');
620 }
621
622 }
623 ?>