| 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.