[-TASK] Extbase (Persistence): Removed unnecessary classes, code and empty interfaces.
[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_Persistence_DataMapper
46 */
47 protected $dataMapper;
48
49 /**
50 * @var Tx_Extbase_Persistence_Manager
51 */
52 protected $persistenceManager;
53
54 /**
55 * @var Tx_Extbase_Persistence_QOM_QueryObjectModelFactoryInterface
56 */
57 protected $qomFactory;
58
59 /**
60 * @var Tx_Extbase_Persistence_QOM_SourceInterface
61 */
62 protected $source;
63
64 /**
65 * @var Tx_Extbase_Persistence_QOM_ConstraintInterface
66 */
67 protected $constraint;
68
69 /**
70 * @var int
71 */
72 protected $orderings = array();
73
74 /**
75 * @var int
76 */
77 protected $limit;
78
79 /**
80 * @var int
81 */
82 protected $offset;
83
84 /**
85 * The query settings.
86 *
87 * @var Tx_Extbase_Persistence_QuerySettingsInterface
88 */
89 protected $querySettings;
90
91 /**
92 * Constructs a query object working on the given class name
93 *
94 * @param string $type
95 */
96 public function __construct($type) {
97 $this->type = $type;
98 }
99
100 /**
101 * Injects the persistence manager, used to fetch the CR session
102 *
103 * @param Tx_Extbase_Persistence_ManagerInterface $persistenceManager
104 * @return void
105 */
106 public function injectPersistenceManager(Tx_Extbase_Persistence_ManagerInterface $persistenceManager) {
107 $this->persistenceManager = $persistenceManager;
108 $this->qomFactory = $this->persistenceManager->getBackend()->getQomFactory();
109 }
110
111 /**
112 * Injects the DataMapper to map nodes to objects
113 *
114 * @param Tx_Extbase_Persistence_Mapper_DataMapper $dataMapper
115 * @return void
116 */
117 public function injectDataMapper(Tx_Extbase_Persistence_Mapper_DataMapper $dataMapper) {
118 $this->dataMapper = $dataMapper;
119 }
120
121 /**
122 * Sets the Query Settings. These Query settings must match the settings expected by
123 * the specific Storage Backend.
124 *
125 * @param Tx_Extbase_Persistence_QuerySettingsInterface $querySettings The Query Settings
126 * @return void
127 * @api This method is not part of FLOW3 API
128 */
129 public function setQuerySettings(Tx_Extbase_Persistence_QuerySettingsInterface $querySettings) {
130 $this->querySettings = $querySettings;
131 }
132
133 /**
134 * Returns the Query Settings.
135 *
136 * @return Tx_Extbase_Persistence_QuerySettingsInterface $querySettings The Query Settings
137 * @api This method is not part of FLOW3 API
138 */
139 public function getQuerySettings() {
140 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);
141 return $this->querySettings;
142 }
143
144 /**
145 * Returns the type this query cares for.
146 *
147 * @return string
148 * @api
149 */
150 public function getType() {
151 return $this->type;
152 }
153
154 /**
155 * Sets the source to fetch the result from
156 *
157 * @param Tx_Extbase_Persistence_QOM_SourceInterface $source
158 */
159 public function setSource(Tx_Extbase_Persistence_QOM_SourceInterface $source) {
160 $this->source = $source;
161 }
162
163 /**
164 * Returns the selectorn name or an empty string, if the source is not a selector
165 * // TODO This has to be checked at another place
166 * @return string The selector name
167 */
168 protected function getSelectorName() {
169 if ($this->getSource() instanceof Tx_Extbase_Persistence_QOM_SelectorInterface) {
170 return $this->source->getSelectorName();
171 } else {
172 return '';
173 }
174 }
175
176 /**
177 * Gets the node-tuple source for this query.
178 *
179 * @return Tx_Extbase_Persistence_QOM_SourceInterface the node-tuple source; non-null
180 */
181 public function getSource() {
182 if ($this->source === NULL) {
183 $this->source = $this->qomFactory->selector($this->getType(), $this->dataMapper->convertClassNameToTableName($this->getType()));
184 }
185 return $this->source;
186 }
187
188 /**
189 * Executes the query against the database and returns the result
190 *
191 * @return array<object> The query result as an array of objects
192 * @api
193 */
194 public function execute() {
195 $rows = $this->persistenceManager->getObjectDataByQuery($this);
196 if ($this->getQuerySettings()->getReturnRawQueryResult() === TRUE) {
197 return $rows;
198 } else {
199 return $this->dataMapper->map($this->getType(), $rows);
200 }
201 }
202
203 /**
204 * Executes the number of matching objects for the query
205 *
206 * @return integer The number of matching objects
207 * @api
208 */
209 public function count() {
210 return $this->persistenceManager->getObjectCountByQuery($this);
211 }
212
213 /**
214 * Sets the property names to order the result by. Expected like this:
215 * array(
216 * 'foo' => Tx_Extbase_Persistence_QueryInterface::ORDER_ASCENDING,
217 * 'bar' => Tx_Extbase_Persistence_QueryInterface::ORDER_DESCENDING
218 * )
219 * where 'foo' and 'bar' are property names.
220 *
221 * @param array $orderings The property names to order by
222 * @return Tx_Extbase_Persistence_QueryInterface
223 * @api
224 */
225 public function setOrderings(array $orderings) {
226 $parsedOrderings = array();
227 foreach ($orderings as $propertyName => $order) {
228 if ($order === Tx_Extbase_Persistence_QueryInterface::ORDER_DESCENDING) {
229 $parsedOrderings[] = $this->qomFactory->descending($this->qomFactory->propertyValue($propertyName));
230 } elseif ($order === Tx_Extbase_Persistence_QueryInterface::ORDER_ASCENDING) {
231 $parsedOrderings[] = $this->qomFactory->ascending($this->qomFactory->propertyValue($propertyName));
232 } else {
233 throw new Tx_Extbase_Persistence_Exception_UnsupportedOrder('The order you specified for your query is not supported.', 1253785630);
234 }
235 }
236 $this->orderings = $parsedOrderings;
237 return $this;
238 }
239
240 /**
241 * Returns the property names to order the result by. Like this:
242 * array(
243 * 'foo' => \F3\FLOW3\Persistence\QueryInterface::ORDER_ASCENDING,
244 * 'bar' => \F3\FLOW3\Persistence\QueryInterface::ORDER_DESCENDING
245 * )
246 *
247 * @return array
248 * @api
249 */
250 public function getOrderings() {
251 return $this->orderings;
252 }
253
254 /**
255 * Sets the maximum size of the result set to limit. Returns $this to allow
256 * for chaining (fluid interface)
257 *
258 * @param integer $limit
259 * @return Tx_Extbase_Persistence_QueryInterface
260 * @api
261 */
262 public function setLimit($limit) {
263 if (!is_int($limit) || $limit < 1) throw new InvalidArgumentException('The limit must be an integer >= 1', 1245071870);
264 $this->limit = $limit;
265 return $this;
266 }
267
268 /**
269 * Returns the maximum size of the result set to limit.
270 *
271 * @param integer
272 * @api
273 */
274 public function getLimit() {
275 return $this->limit;
276 }
277
278 /**
279 * Sets the start offset of the result set to offset. Returns $this to
280 * allow for chaining (fluid interface)
281 *
282 * @param integer $offset
283 * @return Tx_Extbase_Persistence_QueryInterface
284 * @api
285 */
286 public function setOffset($offset) {
287 if (!is_int($offset) || $offset < 0) throw new InvalidArgumentException('The offset must be a positive integer', 1245071872);
288 $this->offset = $offset;
289 return $this;
290 }
291
292 /**
293 * Returns the start offset of the result set.
294 *
295 * @return integer
296 * @api
297 */
298 public function getOffset() {
299 return $this->offset;
300 }
301
302 /**
303 * The constraint used to limit the result set. Returns $this to allow
304 * for chaining (fluid interface)
305 *
306 * @param Tx_Extbase_Persistence_QOM_ConstraintInterface $constraint
307 * @return Tx_Extbase_Persistence_QueryInterface
308 * @api
309 */
310 public function matching($constraint) {
311 $this->constraint = $constraint;
312 return $this;
313 }
314
315 /**
316 * Sets the statement of this query programmatically. If you use this, you will lose the abstraction from a concrete storage
317 * backend (database).
318 *
319 * @param string $statement The statement
320 * @param array $paramerters An array of parameters. These will be bound to placeholders '?' in the $statement.
321 * @param object $language The language of the statement. Must be a supported languanguage defined as Tx_Extbase_Persistence_QOM_QueryObjectModelInterface::JCR_* or Tx_Extbase_Persistence_QOM_QueryObjectModelInterface::TYPO3_* or
322 * @return Tx_Extbase_Persistence_QOM_StatementInterface
323 */
324 public function statement($statement, array $parameters = array(), $language = Tx_Extbase_Persistence_QOM_QueryObjectModelInterface::TYPO3_SQL_MYSQL) {
325 $this->constraint = $this->qomFactory->statement($statement, $parameters, $language);
326 return $this;
327 }
328
329 /**
330 * Gets the constraint for this query.
331 *
332 * @return Tx_Extbase_Persistence_QOM_Constraint the constraint, or null if none
333 * @author Karsten Dambekalns <karsten@typo3.org>
334 * @api
335 */
336 public function getConstraint() {
337 return $this->constraint;
338 }
339
340 /**
341 * Performs a logical conjunction of the given constraints.
342 *
343 * @param object $constraint1 First constraint
344 * @param object $constraint2 Second constraint
345 * @return Tx_Extbase_Persistence_QOM_AndInterface
346 * @api Passing more than two constraints as arguments is currently not yet conform to the api of FLOW3
347 */
348 public function logicalAnd($constraint1, $constraint2) {
349 $constraints = func_get_args();
350 $numberOfConstraints = func_num_args();
351 if (func_num_args() > 1) {
352 $resultingConstraint = array_shift($constraints);
353 foreach ($constraints as $constraint) {
354 $resultingConstraint = $this->qomFactory->_and(
355 $resultingConstraint,
356 $constraint
357 );
358 }
359 } else {
360 throw new Tx_Extbase_Persistence_Exception_InvalidNumberOfConstraints('There must be at least two constraints. Got only ' . func_num_args() . '.', 1268056288);
361 }
362 return $resultingConstraint;
363 }
364
365 /**
366 * Performs a logical conjunction of the given constraints.
367 *
368 * @param array $constraints An array of constraints
369 * @return Tx_Extbase_Persistence_QOM_AndInterface
370 */
371 public function implodeAnd(array $constraints) {
372 $numberOfConstraints = count($constraints);
373 $resultingConstraint = NULL;
374 if ($numberOfConstraints === 1) {
375 return array_shift($constraints);
376 } elseif ($numberOfConstraints > 1) {
377 $resultingConstraint = array_shift($constraints);
378 foreach ($constraints as $constraint) {
379 $resultingConstraint = $this->qomFactory->_and(
380 $resultingConstraint,
381 $constraint
382 );
383 }
384 }
385 return $resultingConstraint;
386 }
387
388 /**
389 * Performs a logical disjunction of the two given constraints
390 *
391 * @param object $constraint1 First constraint
392 * @param object $constraint2 Second constraint
393 * @return Tx_Extbase_Persistence_QOM_OrInterface
394 * @api Passing more than two constraints as arguments is currently not yet conform to the api of FLOW3
395 */
396 public function logicalOr($constraint1, $constraint2) {
397 $constraints = func_get_args();
398 $numberOfConstraints = func_num_args();
399 if (func_num_args() > 1) {
400 $resultingConstraint = array_shift($constraints);
401 foreach ($constraints as $constraint) {
402 $resultingConstraint = $this->qomFactory->_or(
403 $resultingConstraint,
404 $constraint
405 );
406 }
407 } else {
408 throw new Tx_Extbase_Persistence_Exception_InvalidNumberOfConstraints('There must be at least two constraints. Got only ' . func_num_args() . '.', 1268056288);
409 }
410 return $resultingConstraint;
411 }
412
413 /**
414 * Performs a logical conjunction of the given constraints.
415 *
416 * @param array $constraints An array of constraints
417 * @return Tx_Extbase_Persistence_QOM_AndInterface
418 */
419 public function implodeOr(array $constraints) {
420 $numberOfConstraints = count($constraints);
421 $resultingConstraint = NULL;
422 if ($numberOfConstraints === 1) {
423 return array_shift($constraints);
424 } elseif ($numberOfConstraints > 1) {
425 $resultingConstraint = array_shift($constraints);
426 foreach ($constraints as $constraint) {
427 $resultingConstraint = $this->qomFactory->_or(
428 $resultingConstraint,
429 $constraint
430 );
431 }
432 }
433 return $resultingConstraint;
434 }
435
436 /**
437 * Performs a logical negation of the given constraint
438 *
439 * @param object $constraint Constraint to negate
440 * @return Tx_Extbase_Persistence_QOM_NotInterface
441 * @api
442 */
443 public function logicalNot($constraint) {
444 return $this->qomFactory->not($constraint);
445 }
446
447 /**
448 * Matches against the (internal) uid.
449 *
450 * @param int $uid The uid to match against
451 * @return Tx_Extbase_Persistence_QOM_ComparisonInterface
452 * @deprecated since Extbase 2.0; was removed in FLOW3; will be removed in Extbase 3.0; use equals() ínstead
453 */
454 public function withUid($operand) {
455 t3lib_div::logDeprecatedFunction();
456 return $this->qomFactory->comparison(
457 $this->qomFactory->propertyValue('uid', $this->getSelectorName()),
458 Tx_Extbase_Persistence_QueryInterface::OPERATOR_EQUAL_TO,
459 $operand
460 );
461 }
462
463 /**
464 * Returns an equals criterion used for matching objects against a query
465 *
466 * @param string $propertyName The name of the property to compare against
467 * @param mixed $operand The value to compare with
468 * @param boolean $caseSensitive Whether the equality test should be done case-sensitive
469 * @return Tx_Extbase_Persistence_QOM_ComparisonInterface
470 * @api
471 */
472 public function equals($propertyName, $operand, $caseSensitive = TRUE) {
473 if (is_object($operand) || $caseSensitive) {
474 $comparison = $this->qomFactory->comparison(
475 $this->qomFactory->propertyValue($propertyName, $this->getSelectorName()),
476 Tx_Extbase_Persistence_QueryInterface::OPERATOR_EQUAL_TO,
477 $operand
478 );
479 } else {
480 $comparison = $this->qomFactory->comparison(
481 $this->qomFactory->lowerCase(
482 $this->qomFactory->propertyValue($propertyName, $this->getSelectorName())
483 ),
484 Tx_Extbase_Persistence_QueryInterface::OPERATOR_EQUAL_TO,
485 strtolower($operand)
486 );
487 }
488
489 return $comparison;
490 }
491
492 /**
493 * Returns a like criterion used for matching objects against a query
494 *
495 * @param string $propertyName The name of the property to compare against
496 * @param mixed $operand The value to compare with
497 * @return Tx_Extbase_Persistence_QOM_ComparisonInterface
498 * @api
499 */
500 public function like($propertyName, $operand) {
501 return $this->qomFactory->comparison(
502 $this->qomFactory->propertyValue($propertyName, $this->getSelectorName()),
503 Tx_Extbase_Persistence_QueryInterface::OPERATOR_LIKE,
504 $operand
505 );
506 }
507
508 /**
509 * Returns a "contains" criterion used for matching objects against a query.
510 * It matches if the multivalued property contains the given operand.
511 *
512 * @param string $propertyName The name of the (multivalued) property to compare against
513 * @param mixed $operand The value to compare with
514 * @return Tx_Extbase_Persistence_QOM_ComparisonInterface
515 * @api
516 */
517 public function contains($propertyName, $operand){
518 return $this->qomFactory->comparison(
519 $this->qomFactory->propertyValue($propertyName, $this->getSelectorName()),
520 Tx_Extbase_Persistence_QueryInterface::OPERATOR_CONTAINS,
521 $operand
522 );
523 }
524
525 /**
526 * Returns an "in" criterion used for matching objects against a query. It
527 * matches if the property's value is contained in the multivalued operand.
528 *
529 * @param string $propertyName The name of the property to compare against
530 * @param mixed $operand The value to compare with, multivalued
531 * @return Tx_Extbase_Persistence_QOM_ComparisonInterface
532 * @api
533 */
534 public function in($propertyName, $operand) {
535 if (!is_array($operand) && (!$operand instanceof ArrayAccess) && (!$operand instanceof Traversable)) {
536 throw new Tx_Extbase_Persistence_Exception_UnexpectedTypeException('The "in" operator must be given a mutlivalued operand (array, ArrayAccess, Traversable).', 1264678095);
537 }
538
539 return $this->qomFactory->comparison(
540 $this->qomFactory->propertyValue($propertyName, $this->getSelectorName()),
541 Tx_Extbase_Persistence_QueryInterface::OPERATOR_IN,
542 $operand
543 );
544 }
545
546 /**
547 * Returns a less than criterion used for matching objects against a query
548 *
549 * @param string $propertyName The name of the property to compare against
550 * @param mixed $operand The value to compare with
551 * @return Tx_Extbase_Persistence_QOM_ComparisonInterface
552 * @api
553 */
554 public function lessThan($propertyName, $operand) {
555 return $this->qomFactory->comparison(
556 $this->qomFactory->propertyValue($propertyName, $this->getSelectorName()),
557 Tx_Extbase_Persistence_QueryInterface::OPERATOR_LESS_THAN,
558 $operand
559 );
560 }
561
562 /**
563 * Returns a less or equal than criterion used for matching objects against a query
564 *
565 * @param string $propertyName The name of the property to compare against
566 * @param mixed $operand The value to compare with
567 * @return Tx_Extbase_Persistence_QOM_ComparisonInterface
568 * @api
569 */
570 public function lessThanOrEqual($propertyName, $operand) {
571 return $this->qomFactory->comparison(
572 $this->qomFactory->propertyValue($propertyName, $this->getSelectorName()),
573 Tx_Extbase_Persistence_QueryInterface::OPERATOR_LESS_THAN_OR_EQUAL_TO,
574 $operand
575 );
576 }
577
578 /**
579 * Returns a greater than criterion used for matching objects against a query
580 *
581 * @param string $propertyName The name of the property to compare against
582 * @param mixed $operand The value to compare with
583 * @return Tx_Extbase_Persistence_QOM_ComparisonInterface
584 * @api
585 */
586 public function greaterThan($propertyName, $operand) {
587 return $this->qomFactory->comparison(
588 $this->qomFactory->propertyValue($propertyName, $this->getSelectorName()),
589 Tx_Extbase_Persistence_QueryInterface::OPERATOR_GREATER_THAN,
590 $operand
591 );
592 }
593
594 /**
595 * Returns a greater than or equal criterion used for matching objects against a query
596 *
597 * @param string $propertyName The name of the property to compare against
598 * @param mixed $operand The value to compare with
599 * @return Tx_Extbase_Persistence_QOM_ComparisonInterface
600 * @api
601 */
602 public function greaterThanOrEqual($propertyName, $operand) {
603 return $this->qomFactory->comparison(
604 $this->qomFactory->propertyValue($propertyName, $this->getSelectorName()),
605 Tx_Extbase_Persistence_QueryInterface::OPERATOR_GREATER_THAN_OR_EQUAL_TO,
606 $operand
607 );
608 }
609
610 }
611 ?>