Total Complexity | 113 |
Total Lines | 1088 |
Duplicated Lines | 4.69 % |
Coverage | 93.55% |
Changes | 0 |
Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like AbstractQuery often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use AbstractQuery, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
41 | abstract class AbstractQuery |
||
42 | { |
||
43 | /* Hydration mode constants */ |
||
44 | |||
45 | /** |
||
46 | * Hydrates an object graph. This is the default behavior. |
||
47 | */ |
||
48 | const HYDRATE_OBJECT = 1; |
||
49 | |||
50 | /** |
||
51 | * Hydrates an array graph. |
||
52 | */ |
||
53 | const HYDRATE_ARRAY = 2; |
||
54 | |||
55 | /** |
||
56 | * Hydrates a flat, rectangular result set with scalar values. |
||
57 | */ |
||
58 | const HYDRATE_SCALAR = 3; |
||
59 | |||
60 | /** |
||
61 | * Hydrates a single scalar value. |
||
62 | */ |
||
63 | const HYDRATE_SINGLE_SCALAR = 4; |
||
64 | |||
65 | /** |
||
66 | * Very simple object hydrator (optimized for performance). |
||
67 | */ |
||
68 | const HYDRATE_SIMPLEOBJECT = 5; |
||
69 | |||
70 | /** |
||
71 | * The parameter map of this query. |
||
72 | * |
||
73 | * @var \Doctrine\Common\Collections\ArrayCollection |
||
74 | */ |
||
75 | protected $parameters; |
||
76 | |||
77 | /** |
||
78 | * The user-specified ResultSetMapping to use. |
||
79 | * |
||
80 | * @var \Doctrine\ORM\Query\ResultSetMapping |
||
81 | */ |
||
82 | protected $_resultSetMapping; |
||
83 | |||
84 | /** |
||
85 | * The entity manager used by this query object. |
||
86 | * |
||
87 | * @var EntityManagerInterface |
||
88 | */ |
||
89 | protected $_em; |
||
90 | |||
91 | /** |
||
92 | * The map of query hints. |
||
93 | * |
||
94 | * @var array |
||
95 | */ |
||
96 | protected $_hints = []; |
||
97 | |||
98 | /** |
||
99 | * The hydration mode. |
||
100 | * |
||
101 | * @var integer |
||
102 | */ |
||
103 | protected $_hydrationMode = self::HYDRATE_OBJECT; |
||
104 | |||
105 | /** |
||
106 | * @var \Doctrine\DBAL\Cache\QueryCacheProfile |
||
107 | */ |
||
108 | protected $_queryCacheProfile; |
||
109 | |||
110 | /** |
||
111 | * Whether or not expire the result cache. |
||
112 | * |
||
113 | * @var boolean |
||
114 | */ |
||
115 | protected $_expireResultCache = false; |
||
116 | |||
117 | /** |
||
118 | * @var \Doctrine\DBAL\Cache\QueryCacheProfile |
||
119 | */ |
||
120 | protected $_hydrationCacheProfile; |
||
121 | |||
122 | /** |
||
123 | * Whether to use second level cache, if available. |
||
124 | * |
||
125 | * @var boolean |
||
126 | */ |
||
127 | protected $cacheable = false; |
||
128 | |||
129 | /** |
||
130 | * @var boolean |
||
131 | */ |
||
132 | protected $hasCache = false; |
||
133 | |||
134 | /** |
||
135 | * Second level cache region name. |
||
136 | * |
||
137 | * @var string|null |
||
138 | */ |
||
139 | protected $cacheRegion; |
||
140 | |||
141 | /** |
||
142 | * Second level query cache mode. |
||
143 | * |
||
144 | * @var integer|null |
||
145 | */ |
||
146 | protected $cacheMode; |
||
147 | |||
148 | /** |
||
149 | * @var \Doctrine\ORM\Cache\Logging\CacheLogger|null |
||
150 | */ |
||
151 | protected $cacheLogger; |
||
152 | |||
153 | /** |
||
154 | * @var integer |
||
155 | */ |
||
156 | protected $lifetime = 0; |
||
157 | |||
158 | /** |
||
159 | * Initializes a new instance of a class derived from <tt>AbstractQuery</tt>. |
||
160 | * |
||
161 | * @param \Doctrine\ORM\EntityManagerInterface $em |
||
162 | */ |
||
163 | 985 | public function __construct(EntityManagerInterface $em) |
|
174 | } |
||
175 | 985 | } |
|
176 | |||
177 | /** |
||
178 | * Enable/disable second level query (result) caching for this query. |
||
179 | * |
||
180 | * @param boolean $cacheable |
||
181 | * |
||
182 | * @return static This query instance. |
||
183 | */ |
||
184 | 133 | public function setCacheable($cacheable) |
|
185 | { |
||
186 | 133 | $this->cacheable = (boolean) $cacheable; |
|
187 | |||
188 | 133 | return $this; |
|
189 | } |
||
190 | |||
191 | /** |
||
192 | * @return boolean TRUE if the query results are enable for second level cache, FALSE otherwise. |
||
193 | */ |
||
194 | 90 | public function isCacheable() |
|
195 | { |
||
196 | 90 | return $this->cacheable; |
|
197 | } |
||
198 | |||
199 | /** |
||
200 | * @param string $cacheRegion |
||
201 | * |
||
202 | * @return static This query instance. |
||
203 | */ |
||
204 | 2 | public function setCacheRegion($cacheRegion) |
|
205 | { |
||
206 | 2 | $this->cacheRegion = (string) $cacheRegion; |
|
207 | |||
208 | 2 | return $this; |
|
209 | } |
||
210 | |||
211 | /** |
||
212 | * Obtain the name of the second level query cache region in which query results will be stored |
||
213 | * |
||
214 | * @return string|null The cache region name; NULL indicates the default region. |
||
215 | */ |
||
216 | 1 | public function getCacheRegion() |
|
217 | { |
||
218 | 1 | return $this->cacheRegion; |
|
219 | } |
||
220 | |||
221 | /** |
||
222 | * @return boolean TRUE if the query cache and second level cache are enabled, FALSE otherwise. |
||
223 | */ |
||
224 | 29 | protected function isCacheEnabled() |
|
225 | { |
||
226 | 29 | return $this->cacheable && $this->hasCache; |
|
227 | } |
||
228 | |||
229 | /** |
||
230 | * @return integer |
||
231 | */ |
||
232 | 1 | public function getLifetime() |
|
233 | { |
||
234 | 1 | return $this->lifetime; |
|
235 | } |
||
236 | |||
237 | /** |
||
238 | * Sets the life-time for this query into second level cache. |
||
239 | * |
||
240 | * @param integer $lifetime |
||
241 | * |
||
242 | * @return \Doctrine\ORM\AbstractQuery This query instance. |
||
243 | */ |
||
244 | 2 | public function setLifetime($lifetime) |
|
245 | { |
||
246 | 2 | $this->lifetime = (integer) $lifetime; |
|
247 | |||
248 | 2 | return $this; |
|
249 | } |
||
250 | |||
251 | /** |
||
252 | * @return integer |
||
253 | */ |
||
254 | 1 | public function getCacheMode() |
|
255 | { |
||
256 | 1 | return $this->cacheMode; |
|
257 | } |
||
258 | |||
259 | /** |
||
260 | * @param integer $cacheMode |
||
261 | * |
||
262 | * @return \Doctrine\ORM\AbstractQuery This query instance. |
||
263 | */ |
||
264 | 4 | public function setCacheMode($cacheMode) |
|
265 | { |
||
266 | 4 | $this->cacheMode = (integer) $cacheMode; |
|
267 | |||
268 | 4 | return $this; |
|
269 | } |
||
270 | |||
271 | /** |
||
272 | * Gets the SQL query that corresponds to this query object. |
||
273 | * The returned SQL syntax depends on the connection driver that is used |
||
274 | * by this query object at the time of this method call. |
||
275 | * |
||
276 | * @return string SQL query |
||
277 | */ |
||
278 | abstract public function getSQL(); |
||
279 | |||
280 | /** |
||
281 | * Retrieves the associated EntityManager of this Query instance. |
||
282 | * |
||
283 | * @return \Doctrine\ORM\EntityManager |
||
284 | */ |
||
285 | 903 | public function getEntityManager() |
|
286 | { |
||
287 | 903 | return $this->_em; |
|
288 | } |
||
289 | |||
290 | /** |
||
291 | * Frees the resources used by the query object. |
||
292 | * |
||
293 | * Resets Parameters, Parameter Types and Query Hints. |
||
294 | * |
||
295 | * @return void |
||
296 | */ |
||
297 | 211 | public function free() |
|
298 | { |
||
299 | 211 | $this->parameters = new ArrayCollection(); |
|
300 | |||
301 | 211 | $this->_hints = $this->_em->getConfiguration()->getDefaultQueryHints(); |
|
302 | 211 | } |
|
303 | |||
304 | /** |
||
305 | * Get all defined parameters. |
||
306 | * |
||
307 | * @return \Doctrine\Common\Collections\ArrayCollection The defined query parameters. |
||
308 | */ |
||
309 | 143 | public function getParameters() |
|
310 | { |
||
311 | 143 | return $this->parameters; |
|
312 | } |
||
313 | |||
314 | /** |
||
315 | * Gets a query parameter. |
||
316 | * |
||
317 | * @param mixed $key The key (index or name) of the bound parameter. |
||
318 | * |
||
319 | * @return Query\Parameter|null The value of the bound parameter, or NULL if not available. |
||
320 | */ |
||
321 | 271 | View Code Duplication | public function getParameter($key) |
322 | { |
||
323 | 271 | $filteredParameters = $this->parameters->filter( |
|
324 | 271 | function (Query\Parameter $parameter) use ($key) : bool { |
|
325 | 153 | $parameterName = $parameter->getName(); |
|
326 | |||
327 | 153 | return $key === $parameterName || (string) $key === (string) $parameterName; |
|
328 | 271 | } |
|
329 | ); |
||
330 | |||
331 | 271 | return ! $filteredParameters->isEmpty() ? $filteredParameters->first() : null; |
|
332 | } |
||
333 | |||
334 | /** |
||
335 | * Sets a collection of query parameters. |
||
336 | * |
||
337 | * @param \Doctrine\Common\Collections\ArrayCollection|array $parameters |
||
338 | * |
||
339 | * @return static This query instance. |
||
340 | */ |
||
341 | 189 | View Code Duplication | public function setParameters($parameters) |
357 | } |
||
358 | |||
359 | /** |
||
360 | * Sets a query parameter. |
||
361 | * |
||
362 | * @param string|int $key The parameter position or name. |
||
363 | * @param mixed $value The parameter value. |
||
364 | * @param string|null $type The parameter type. If specified, the given value will be run through |
||
365 | * the type conversion of this type. This is usually not needed for |
||
366 | * strings and numeric types. |
||
367 | * |
||
368 | * @return static This query instance. |
||
369 | */ |
||
370 | 184 | public function setParameter($key, $value, $type = null) |
|
383 | } |
||
384 | |||
385 | /** |
||
386 | * Processes an individual parameter value. |
||
387 | * |
||
388 | * @param mixed $value |
||
389 | * |
||
390 | * @return array|string |
||
391 | * |
||
392 | * @throws \Doctrine\ORM\ORMInvalidArgumentException |
||
393 | */ |
||
394 | 180 | public function processParameterValue($value) |
|
395 | { |
||
396 | 180 | if (is_scalar($value)) { |
|
397 | 167 | return $value; |
|
398 | } |
||
399 | |||
400 | 90 | if ($value instanceof Collection) { |
|
401 | 1 | $value = $value->toArray(); |
|
402 | } |
||
403 | |||
404 | 90 | if (is_array($value)) { |
|
405 | 73 | foreach ($value as $key => $paramValue) { |
|
406 | 73 | $paramValue = $this->processParameterValue($paramValue); |
|
407 | 73 | $value[$key] = is_array($paramValue) ? reset($paramValue) : $paramValue; |
|
408 | } |
||
409 | |||
410 | 73 | return $value; |
|
411 | } |
||
412 | |||
413 | 20 | if (is_object($value) && $this->_em->getMetadataFactory()->hasMetadataFor(ClassUtils::getClass($value))) { |
|
414 | 14 | $value = $this->_em->getUnitOfWork()->getSingleIdentifierValue($value); |
|
415 | |||
416 | 14 | if ($value === null) { |
|
417 | throw ORMInvalidArgumentException::invalidIdentifierBindingEntity(); |
||
418 | } |
||
419 | } |
||
420 | |||
421 | 20 | if ($value instanceof Mapping\ClassMetadata) { |
|
422 | 1 | return $value->name; |
|
423 | } |
||
424 | |||
425 | 19 | return $value; |
|
426 | } |
||
427 | |||
428 | /** |
||
429 | * Sets the ResultSetMapping that should be used for hydration. |
||
430 | * |
||
431 | * @param \Doctrine\ORM\Query\ResultSetMapping $rsm |
||
432 | * |
||
433 | * @return static This query instance. |
||
434 | */ |
||
435 | 30 | public function setResultSetMapping(Query\ResultSetMapping $rsm) |
|
436 | { |
||
437 | 30 | $this->translateNamespaces($rsm); |
|
438 | 30 | $this->_resultSetMapping = $rsm; |
|
439 | |||
440 | 30 | return $this; |
|
441 | } |
||
442 | |||
443 | /** |
||
444 | * Gets the ResultSetMapping used for hydration. |
||
445 | * |
||
446 | * @return \Doctrine\ORM\Query\ResultSetMapping |
||
447 | */ |
||
448 | 22 | protected function getResultSetMapping() |
|
449 | { |
||
450 | 22 | return $this->_resultSetMapping; |
|
451 | } |
||
452 | |||
453 | /** |
||
454 | * Allows to translate entity namespaces to full qualified names. |
||
455 | * |
||
456 | * @param Query\ResultSetMapping $rsm |
||
457 | * |
||
458 | * @return void |
||
459 | */ |
||
460 | private function translateNamespaces(Query\ResultSetMapping $rsm) |
||
461 | { |
||
462 | 30 | $translate = function ($alias) { |
|
463 | 18 | return $this->_em->getClassMetadata($alias)->getName(); |
|
464 | 30 | }; |
|
465 | |||
466 | 30 | $rsm->aliasMap = array_map($translate, $rsm->aliasMap); |
|
467 | 30 | $rsm->declaringClasses = array_map($translate, $rsm->declaringClasses); |
|
468 | 30 | } |
|
469 | |||
470 | /** |
||
471 | * Set a cache profile for hydration caching. |
||
472 | * |
||
473 | * If no result cache driver is set in the QueryCacheProfile, the default |
||
474 | * result cache driver is used from the configuration. |
||
475 | * |
||
476 | * Important: Hydration caching does NOT register entities in the |
||
477 | * UnitOfWork when retrieved from the cache. Never use result cached |
||
478 | * entities for requests that also flush the EntityManager. If you want |
||
479 | * some form of caching with UnitOfWork registration you should use |
||
480 | * {@see AbstractQuery::setResultCacheProfile()}. |
||
481 | * |
||
482 | * @example |
||
483 | * $lifetime = 100; |
||
484 | * $resultKey = "abc"; |
||
485 | * $query->setHydrationCacheProfile(new QueryCacheProfile()); |
||
486 | * $query->setHydrationCacheProfile(new QueryCacheProfile($lifetime, $resultKey)); |
||
487 | * |
||
488 | * @param \Doctrine\DBAL\Cache\QueryCacheProfile $profile |
||
489 | * |
||
490 | * @return static This query instance. |
||
491 | */ |
||
492 | 3 | View Code Duplication | public function setHydrationCacheProfile(QueryCacheProfile $profile = null) |
493 | { |
||
494 | 3 | if ($profile !== null && ! $profile->getResultCacheDriver()) { |
|
495 | $resultCacheDriver = $this->_em->getConfiguration()->getHydrationCacheImpl(); |
||
496 | $profile = $profile->setResultCacheDriver($resultCacheDriver); |
||
497 | } |
||
498 | |||
499 | 3 | $this->_hydrationCacheProfile = $profile; |
|
500 | |||
501 | 3 | return $this; |
|
502 | } |
||
503 | |||
504 | /** |
||
505 | * @return \Doctrine\DBAL\Cache\QueryCacheProfile |
||
506 | */ |
||
507 | 3 | public function getHydrationCacheProfile() |
|
508 | { |
||
509 | 3 | return $this->_hydrationCacheProfile; |
|
510 | } |
||
511 | |||
512 | /** |
||
513 | * Set a cache profile for the result cache. |
||
514 | * |
||
515 | * If no result cache driver is set in the QueryCacheProfile, the default |
||
516 | * result cache driver is used from the configuration. |
||
517 | * |
||
518 | * @param \Doctrine\DBAL\Cache\QueryCacheProfile $profile |
||
519 | * |
||
520 | * @return static This query instance. |
||
521 | */ |
||
522 | View Code Duplication | public function setResultCacheProfile(QueryCacheProfile $profile = null) |
|
523 | { |
||
524 | if ( ! $profile->getResultCacheDriver()) { |
||
|
|||
525 | $resultCacheDriver = $this->_em->getConfiguration()->getResultCacheImpl(); |
||
526 | $profile = $profile->setResultCacheDriver($resultCacheDriver); |
||
527 | } |
||
528 | |||
529 | $this->_queryCacheProfile = $profile; |
||
530 | |||
531 | return $this; |
||
532 | } |
||
533 | |||
534 | /** |
||
535 | * Defines a cache driver to be used for caching result sets and implicitly enables caching. |
||
536 | * |
||
537 | * @param \Doctrine\Common\Cache\Cache|null $resultCacheDriver Cache driver |
||
538 | * |
||
539 | * @return static This query instance. |
||
540 | * |
||
541 | * @throws ORMException |
||
542 | */ |
||
543 | 8 | public function setResultCacheDriver($resultCacheDriver = null) |
|
544 | { |
||
545 | 8 | if ($resultCacheDriver !== null && ! ($resultCacheDriver instanceof \Doctrine\Common\Cache\Cache)) { |
|
546 | throw ORMException::invalidResultCacheDriver(); |
||
547 | } |
||
548 | |||
549 | 8 | $this->_queryCacheProfile = $this->_queryCacheProfile |
|
550 | 1 | ? $this->_queryCacheProfile->setResultCacheDriver($resultCacheDriver) |
|
551 | 7 | : new QueryCacheProfile(0, null, $resultCacheDriver); |
|
552 | |||
553 | 8 | return $this; |
|
554 | } |
||
555 | |||
556 | /** |
||
557 | * Returns the cache driver used for caching result sets. |
||
558 | * |
||
559 | * @deprecated |
||
560 | * |
||
561 | * @return \Doctrine\Common\Cache\Cache Cache driver |
||
562 | */ |
||
563 | 3 | public function getResultCacheDriver() |
|
564 | { |
||
565 | 3 | if ($this->_queryCacheProfile && $this->_queryCacheProfile->getResultCacheDriver()) { |
|
566 | 3 | return $this->_queryCacheProfile->getResultCacheDriver(); |
|
567 | } |
||
568 | |||
569 | return $this->_em->getConfiguration()->getResultCacheImpl(); |
||
570 | } |
||
571 | |||
572 | /** |
||
573 | * Set whether or not to cache the results of this query and if so, for |
||
574 | * how long and which ID to use for the cache entry. |
||
575 | * |
||
576 | * @param boolean $bool |
||
577 | * @param integer $lifetime |
||
578 | * @param string $resultCacheId |
||
579 | * |
||
580 | * @return static This query instance. |
||
581 | */ |
||
582 | 8 | public function useResultCache($bool, $lifetime = null, $resultCacheId = null) |
|
583 | { |
||
584 | 8 | if ($bool) { |
|
585 | 8 | $this->setResultCacheLifetime($lifetime); |
|
586 | 8 | $this->setResultCacheId($resultCacheId); |
|
587 | |||
588 | 8 | return $this; |
|
589 | } |
||
590 | |||
591 | 1 | $this->_queryCacheProfile = null; |
|
592 | |||
593 | 1 | return $this; |
|
594 | } |
||
595 | |||
596 | /** |
||
597 | * Defines how long the result cache will be active before expire. |
||
598 | * |
||
599 | * @param integer $lifetime How long the cache entry is valid. |
||
600 | * |
||
601 | * @return static This query instance. |
||
602 | */ |
||
603 | 9 | public function setResultCacheLifetime($lifetime) |
|
604 | { |
||
605 | 9 | $lifetime = ($lifetime !== null) ? (int) $lifetime : 0; |
|
606 | |||
607 | 9 | $this->_queryCacheProfile = $this->_queryCacheProfile |
|
608 | 4 | ? $this->_queryCacheProfile->setLifetime($lifetime) |
|
609 | 5 | : new QueryCacheProfile($lifetime, null, $this->_em->getConfiguration()->getResultCacheImpl()); |
|
610 | |||
611 | 9 | return $this; |
|
612 | } |
||
613 | |||
614 | /** |
||
615 | * Retrieves the lifetime of resultset cache. |
||
616 | * |
||
617 | * @deprecated |
||
618 | * |
||
619 | * @return integer |
||
620 | */ |
||
621 | public function getResultCacheLifetime() |
||
622 | { |
||
623 | return $this->_queryCacheProfile ? $this->_queryCacheProfile->getLifetime() : 0; |
||
624 | } |
||
625 | |||
626 | /** |
||
627 | * Defines if the result cache is active or not. |
||
628 | * |
||
629 | * @param boolean $expire Whether or not to force resultset cache expiration. |
||
630 | * |
||
631 | * @return static This query instance. |
||
632 | */ |
||
633 | 4 | public function expireResultCache($expire = true) |
|
634 | { |
||
635 | 4 | $this->_expireResultCache = $expire; |
|
636 | |||
637 | 4 | return $this; |
|
638 | } |
||
639 | |||
640 | /** |
||
641 | * Retrieves if the resultset cache is active or not. |
||
642 | * |
||
643 | * @return boolean |
||
644 | */ |
||
645 | 8 | public function getExpireResultCache() |
|
646 | { |
||
647 | 8 | return $this->_expireResultCache; |
|
648 | } |
||
649 | |||
650 | /** |
||
651 | * @return QueryCacheProfile |
||
652 | */ |
||
653 | 1 | public function getQueryCacheProfile() |
|
654 | { |
||
655 | 1 | return $this->_queryCacheProfile; |
|
656 | } |
||
657 | |||
658 | /** |
||
659 | * Change the default fetch mode of an association for this query. |
||
660 | * |
||
661 | * $fetchMode can be one of ClassMetadata::FETCH_EAGER or ClassMetadata::FETCH_LAZY |
||
662 | * |
||
663 | * @param string $class |
||
664 | * @param string $assocName |
||
665 | * @param int $fetchMode |
||
666 | * |
||
667 | * @return static This query instance. |
||
668 | */ |
||
669 | 3 | public function setFetchMode($class, $assocName, $fetchMode) |
|
670 | { |
||
671 | 3 | if ($fetchMode !== Mapping\ClassMetadata::FETCH_EAGER) { |
|
672 | $fetchMode = Mapping\ClassMetadata::FETCH_LAZY; |
||
673 | } |
||
674 | |||
675 | 3 | $this->_hints['fetchMode'][$class][$assocName] = $fetchMode; |
|
676 | |||
677 | 3 | return $this; |
|
678 | } |
||
679 | |||
680 | /** |
||
681 | * Defines the processing mode to be used during hydration / result set transformation. |
||
682 | * |
||
683 | * @param integer $hydrationMode Doctrine processing mode to be used during hydration process. |
||
684 | * One of the Query::HYDRATE_* constants. |
||
685 | * |
||
686 | * @return static This query instance. |
||
687 | */ |
||
688 | 386 | public function setHydrationMode($hydrationMode) |
|
689 | { |
||
690 | 386 | $this->_hydrationMode = $hydrationMode; |
|
691 | |||
692 | 386 | return $this; |
|
693 | } |
||
694 | |||
695 | /** |
||
696 | * Gets the hydration mode currently used by the query. |
||
697 | * |
||
698 | * @return integer |
||
699 | */ |
||
700 | 656 | public function getHydrationMode() |
|
701 | { |
||
702 | 656 | return $this->_hydrationMode; |
|
703 | } |
||
704 | |||
705 | /** |
||
706 | * Gets the list of results for the query. |
||
707 | * |
||
708 | * Alias for execute(null, $hydrationMode = HYDRATE_OBJECT). |
||
709 | * |
||
710 | * @param int $hydrationMode |
||
711 | * |
||
712 | * @return mixed |
||
713 | */ |
||
714 | 309 | public function getResult($hydrationMode = self::HYDRATE_OBJECT) |
|
715 | { |
||
716 | 309 | return $this->execute(null, $hydrationMode); |
|
717 | } |
||
718 | |||
719 | /** |
||
720 | * Gets the array of results for the query. |
||
721 | * |
||
722 | * Alias for execute(null, HYDRATE_ARRAY). |
||
723 | * |
||
724 | * @return array |
||
725 | */ |
||
726 | 26 | public function getArrayResult() |
|
727 | { |
||
728 | 26 | return $this->execute(null, self::HYDRATE_ARRAY); |
|
729 | } |
||
730 | |||
731 | /** |
||
732 | * Gets the scalar results for the query. |
||
733 | * |
||
734 | * Alias for execute(null, HYDRATE_SCALAR). |
||
735 | * |
||
736 | * @return array |
||
737 | */ |
||
738 | 87 | public function getScalarResult() |
|
741 | } |
||
742 | |||
743 | /** |
||
744 | * Get exactly one result or null. |
||
745 | * |
||
746 | * @param int $hydrationMode |
||
747 | * |
||
748 | * @return mixed |
||
749 | * |
||
750 | * @throws NonUniqueResultException |
||
751 | */ |
||
752 | 16 | public function getOneOrNullResult($hydrationMode = null) |
|
753 | { |
||
754 | try { |
||
755 | 16 | $result = $this->execute(null, $hydrationMode); |
|
756 | 1 | } catch (NoResultException $e) { |
|
757 | 1 | return null; |
|
758 | } |
||
759 | |||
760 | |||
761 | 15 | if ($this->_hydrationMode !== self::HYDRATE_SINGLE_SCALAR && ! $result) { |
|
762 | 2 | return null; |
|
763 | } |
||
764 | |||
765 | 13 | if ( ! is_array($result)) { |
|
766 | 1 | return $result; |
|
767 | } |
||
768 | |||
769 | 13 | if (count($result) > 1) { |
|
770 | 1 | throw new NonUniqueResultException; |
|
771 | } |
||
772 | |||
773 | 12 | return array_shift($result); |
|
774 | } |
||
775 | |||
776 | /** |
||
777 | * Gets the single result of the query. |
||
778 | * |
||
779 | * Enforces the presence as well as the uniqueness of the result. |
||
780 | * |
||
781 | * If the result is not unique, a NonUniqueResultException is thrown. |
||
782 | * If there is no result, a NoResultException is thrown. |
||
783 | * |
||
784 | * @param integer $hydrationMode |
||
785 | * |
||
786 | * @return mixed |
||
787 | * |
||
788 | * @throws NonUniqueResultException If the query result is not unique. |
||
789 | * @throws NoResultException If the query returned no result and hydration mode is not HYDRATE_SINGLE_SCALAR. |
||
790 | */ |
||
791 | 104 | public function getSingleResult($hydrationMode = null) |
|
792 | { |
||
793 | 104 | $result = $this->execute(null, $hydrationMode); |
|
794 | |||
795 | 98 | if ($this->_hydrationMode !== self::HYDRATE_SINGLE_SCALAR && ! $result) { |
|
796 | 2 | throw new NoResultException; |
|
797 | } |
||
798 | |||
799 | 97 | if ( ! is_array($result)) { |
|
800 | 9 | return $result; |
|
801 | } |
||
802 | |||
803 | 89 | if (count($result) > 1) { |
|
804 | 1 | throw new NonUniqueResultException; |
|
805 | } |
||
806 | |||
807 | 88 | return array_shift($result); |
|
808 | } |
||
809 | |||
810 | /** |
||
811 | * Gets the single scalar result of the query. |
||
812 | * |
||
813 | * Alias for getSingleResult(HYDRATE_SINGLE_SCALAR). |
||
814 | * |
||
815 | * @return mixed The scalar result, or NULL if the query returned no result. |
||
816 | * |
||
817 | * @throws NonUniqueResultException If the query result is not unique. |
||
818 | */ |
||
819 | 11 | public function getSingleScalarResult() |
|
820 | { |
||
821 | 11 | return $this->getSingleResult(self::HYDRATE_SINGLE_SCALAR); |
|
822 | } |
||
823 | |||
824 | /** |
||
825 | * Sets a query hint. If the hint name is not recognized, it is silently ignored. |
||
826 | * |
||
827 | * @param string $name The name of the hint. |
||
828 | * @param mixed $value The value of the hint. |
||
829 | * |
||
830 | * @return static This query instance. |
||
831 | */ |
||
832 | 463 | public function setHint($name, $value) |
|
837 | } |
||
838 | |||
839 | /** |
||
840 | * Gets the value of a query hint. If the hint name is not recognized, FALSE is returned. |
||
841 | * |
||
842 | * @param string $name The name of the hint. |
||
843 | * |
||
844 | * @return mixed The value of the hint or FALSE, if the hint name is not recognized. |
||
845 | */ |
||
846 | 800 | public function getHint($name) |
|
847 | { |
||
848 | 800 | return isset($this->_hints[$name]) ? $this->_hints[$name] : false; |
|
849 | } |
||
850 | |||
851 | /** |
||
852 | * Check if the query has a hint |
||
853 | * |
||
854 | * @param string $name The name of the hint |
||
855 | * |
||
856 | * @return bool False if the query does not have any hint |
||
857 | */ |
||
858 | 17 | public function hasHint($name) |
|
859 | { |
||
860 | 17 | return isset($this->_hints[$name]); |
|
861 | } |
||
862 | |||
863 | /** |
||
864 | * Return the key value map of query hints that are currently set. |
||
865 | * |
||
866 | * @return array |
||
867 | */ |
||
868 | 136 | public function getHints() |
|
869 | { |
||
870 | 136 | return $this->_hints; |
|
871 | } |
||
872 | |||
873 | /** |
||
874 | * Executes the query and returns an IterableResult that can be used to incrementally |
||
875 | * iterate over the result. |
||
876 | * |
||
877 | * @param ArrayCollection|array|null $parameters The query parameters. |
||
878 | * @param integer|null $hydrationMode The hydration mode to use. |
||
879 | * |
||
880 | * @return \Doctrine\ORM\Internal\Hydration\IterableResult |
||
881 | */ |
||
882 | 10 | public function iterate($parameters = null, $hydrationMode = null) |
|
883 | { |
||
884 | 10 | if ($hydrationMode !== null) { |
|
885 | 10 | $this->setHydrationMode($hydrationMode); |
|
886 | } |
||
887 | |||
888 | 10 | if ( ! empty($parameters)) { |
|
889 | 1 | $this->setParameters($parameters); |
|
890 | } |
||
891 | |||
892 | 10 | $rsm = $this->getResultSetMapping(); |
|
893 | 7 | $stmt = $this->_doExecute(); |
|
894 | |||
895 | 7 | return $this->_em->newHydrator($this->_hydrationMode)->iterate($stmt, $rsm, $this->_hints); |
|
896 | } |
||
897 | |||
898 | /** |
||
899 | * Executes the query. |
||
900 | * |
||
901 | * @param ArrayCollection|array|null $parameters Query parameters. |
||
902 | * @param integer|null $hydrationMode Processing mode to be used during the hydration process. |
||
903 | * |
||
904 | * @return mixed |
||
905 | */ |
||
906 | 485 | public function execute($parameters = null, $hydrationMode = null) |
|
907 | { |
||
908 | 485 | if ($this->cacheable && $this->isCacheEnabled()) { |
|
909 | 29 | return $this->executeUsingQueryCache($parameters, $hydrationMode); |
|
910 | } |
||
911 | |||
912 | 458 | return $this->executeIgnoreQueryCache($parameters, $hydrationMode); |
|
913 | } |
||
914 | |||
915 | /** |
||
916 | * Execute query ignoring second level cache. |
||
917 | * |
||
918 | * @param ArrayCollection|array|null $parameters |
||
919 | * @param integer|null $hydrationMode |
||
920 | * |
||
921 | * @return mixed |
||
922 | */ |
||
923 | 485 | private function executeIgnoreQueryCache($parameters = null, $hydrationMode = null) |
|
924 | { |
||
925 | 485 | if ($hydrationMode !== null) { |
|
926 | 376 | $this->setHydrationMode($hydrationMode); |
|
927 | } |
||
928 | |||
929 | 485 | if ( ! empty($parameters)) { |
|
930 | $this->setParameters($parameters); |
||
931 | } |
||
932 | |||
933 | $setCacheEntry = function() {}; |
||
934 | |||
935 | 485 | if ($this->_hydrationCacheProfile !== null) { |
|
936 | 2 | list($cacheKey, $realCacheKey) = $this->getHydrationCacheId(); |
|
937 | |||
938 | 2 | $queryCacheProfile = $this->getHydrationCacheProfile(); |
|
939 | 2 | $cache = $queryCacheProfile->getResultCacheDriver(); |
|
940 | 2 | $result = $cache->fetch($cacheKey); |
|
941 | |||
942 | 2 | if (isset($result[$realCacheKey])) { |
|
943 | 2 | return $result[$realCacheKey]; |
|
944 | } |
||
945 | |||
946 | 2 | if ( ! $result) { |
|
947 | 2 | $result = []; |
|
948 | } |
||
949 | |||
950 | 2 | $setCacheEntry = function($data) use ($cache, $result, $cacheKey, $realCacheKey, $queryCacheProfile) { |
|
951 | 2 | $result[$realCacheKey] = $data; |
|
952 | |||
953 | 2 | $cache->save($cacheKey, $result, $queryCacheProfile->getLifetime()); |
|
954 | 2 | }; |
|
955 | } |
||
956 | |||
957 | 485 | $stmt = $this->_doExecute(); |
|
958 | |||
959 | 473 | if (is_numeric($stmt)) { |
|
960 | 27 | $setCacheEntry($stmt); |
|
961 | |||
962 | 27 | return $stmt; |
|
963 | } |
||
964 | |||
965 | 458 | $rsm = $this->getResultSetMapping(); |
|
966 | 458 | $data = $this->_em->newHydrator($this->_hydrationMode)->hydrateAll($stmt, $rsm, $this->_hints); |
|
967 | |||
968 | 454 | $setCacheEntry($data); |
|
969 | |||
970 | 454 | return $data; |
|
971 | } |
||
972 | |||
973 | /** |
||
974 | * Load from second level cache or executes the query and put into cache. |
||
975 | * |
||
976 | * @param ArrayCollection|array|null $parameters |
||
977 | * @param integer|null $hydrationMode |
||
978 | * |
||
979 | * @return mixed |
||
980 | */ |
||
981 | 29 | private function executeUsingQueryCache($parameters = null, $hydrationMode = null) |
|
982 | { |
||
983 | 29 | $rsm = $this->getResultSetMapping(); |
|
984 | 29 | $queryCache = $this->_em->getCache()->getQueryCache($this->cacheRegion); |
|
985 | 29 | $queryKey = new QueryCacheKey( |
|
986 | 29 | $this->getHash(), |
|
987 | 29 | $this->lifetime, |
|
988 | 29 | $this->cacheMode ?: Cache::MODE_NORMAL, |
|
989 | 29 | $this->getTimestampKey() |
|
990 | ); |
||
991 | |||
992 | 29 | $result = $queryCache->get($queryKey, $rsm, $this->_hints); |
|
993 | |||
994 | 29 | if ($result !== null) { |
|
995 | 16 | if ($this->cacheLogger) { |
|
996 | 16 | $this->cacheLogger->queryCacheHit($queryCache->getRegion()->getName(), $queryKey); |
|
997 | } |
||
998 | |||
999 | 16 | return $result; |
|
1000 | } |
||
1001 | |||
1002 | 29 | $result = $this->executeIgnoreQueryCache($parameters, $hydrationMode); |
|
1003 | 29 | $cached = $queryCache->put($queryKey, $rsm, $result, $this->_hints); |
|
1004 | |||
1005 | 26 | if ($this->cacheLogger) { |
|
1006 | 26 | $this->cacheLogger->queryCacheMiss($queryCache->getRegion()->getName(), $queryKey); |
|
1007 | |||
1008 | 26 | if ($cached) { |
|
1009 | 26 | $this->cacheLogger->queryCachePut($queryCache->getRegion()->getName(), $queryKey); |
|
1010 | } |
||
1011 | } |
||
1012 | |||
1013 | 26 | return $result; |
|
1014 | } |
||
1015 | |||
1016 | /** |
||
1017 | * @return \Doctrine\ORM\Cache\TimestampCacheKey|null |
||
1018 | */ |
||
1019 | 29 | private function getTimestampKey() |
|
1020 | { |
||
1021 | 29 | $entityName = reset($this->_resultSetMapping->aliasMap); |
|
1022 | |||
1023 | 29 | if (empty($entityName)) { |
|
1024 | 2 | return null; |
|
1025 | } |
||
1026 | |||
1027 | 27 | $metadata = $this->_em->getClassMetadata($entityName); |
|
1028 | |||
1029 | 27 | return new Cache\TimestampCacheKey($metadata->rootEntityName); |
|
1030 | } |
||
1031 | |||
1032 | /** |
||
1033 | * Get the result cache id to use to store the result set cache entry. |
||
1034 | * Will return the configured id if it exists otherwise a hash will be |
||
1035 | * automatically generated for you. |
||
1036 | * |
||
1037 | * @return array ($key, $hash) |
||
1038 | */ |
||
1039 | 2 | protected function getHydrationCacheId() |
|
1040 | { |
||
1041 | 2 | $parameters = []; |
|
1042 | |||
1043 | 2 | foreach ($this->getParameters() as $parameter) { |
|
1044 | 1 | $parameters[$parameter->getName()] = $this->processParameterValue($parameter->getValue()); |
|
1045 | } |
||
1046 | |||
1047 | 2 | $sql = $this->getSQL(); |
|
1048 | 2 | $queryCacheProfile = $this->getHydrationCacheProfile(); |
|
1049 | 2 | $hints = $this->getHints(); |
|
1050 | 2 | $hints['hydrationMode'] = $this->getHydrationMode(); |
|
1051 | |||
1052 | 2 | ksort($hints); |
|
1053 | |||
1054 | 2 | return $queryCacheProfile->generateCacheKeys($sql, $parameters, $hints); |
|
1055 | } |
||
1056 | |||
1057 | /** |
||
1058 | * Set the result cache id to use to store the result set cache entry. |
||
1059 | * If this is not explicitly set by the developer then a hash is automatically |
||
1060 | * generated for you. |
||
1061 | * |
||
1062 | * @param string $id |
||
1063 | * |
||
1064 | * @return static This query instance. |
||
1065 | */ |
||
1066 | 11 | public function setResultCacheId($id) |
|
1067 | { |
||
1068 | 11 | $this->_queryCacheProfile = $this->_queryCacheProfile |
|
1069 | 11 | ? $this->_queryCacheProfile->setCacheKey($id) |
|
1070 | : new QueryCacheProfile(0, $id, $this->_em->getConfiguration()->getResultCacheImpl()); |
||
1071 | |||
1072 | 11 | return $this; |
|
1073 | } |
||
1074 | |||
1075 | /** |
||
1076 | * Get the result cache id to use to store the result set cache entry if set. |
||
1077 | * |
||
1078 | * @deprecated |
||
1079 | * |
||
1080 | * @return string |
||
1081 | */ |
||
1082 | public function getResultCacheId() |
||
1085 | } |
||
1086 | |||
1087 | /** |
||
1088 | * Executes the query and returns a the resulting Statement object. |
||
1089 | * |
||
1090 | * @return \Doctrine\DBAL\Driver\Statement The executed database statement that holds the results. |
||
1091 | */ |
||
1092 | abstract protected function _doExecute(); |
||
1093 | |||
1094 | /** |
||
1095 | * Cleanup Query resource when clone is called. |
||
1096 | * |
||
1097 | * @return void |
||
1098 | */ |
||
1099 | 136 | public function __clone() |
|
1105 | 136 | } |
|
1106 | |||
1107 | /** |
||
1108 | * Generates a string of currently query to use for the cache second level cache. |
||
1109 | * |
||
1110 | * @return string |
||
1111 | */ |
||
1112 | 29 | protected function getHash() |
|
1113 | { |
||
1114 | 29 | $query = $this->getSQL(); |
|
1115 | 29 | $hints = $this->getHints(); |
|
1116 | 29 | $params = array_map(function(Parameter $parameter) { |
|
1117 | // Small optimization |
||
1118 | // Does not invoke processParameterValue for scalar values |
||
1129 | } |
||
1130 | } |
||
1131 |
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.
This is most likely a typographical error or the method has been renamed.