composer package updates
[openemr.git] / vendor / doctrine / orm / lib / Doctrine / ORM / Cache / Persister / Entity / AbstractEntityPersister.php
blob0a5aa1c656b21e93e00477dc9a837e2e356d1744
1 <?php
3 /*
4 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
5 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
6 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
7 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
8 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
9 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
10 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
11 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
12 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
13 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
14 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16 * This software consists of voluntary contributions made by many individuals
17 * and is licensed under the MIT license. For more information, see
18 * <http://www.doctrine-project.org>.
21 namespace Doctrine\ORM\Cache\Persister\Entity;
23 use Doctrine\ORM\Cache;
24 use Doctrine\ORM\Cache\Region;
25 use Doctrine\ORM\Cache\EntityCacheKey;
26 use Doctrine\ORM\Cache\CollectionCacheKey;
27 use Doctrine\ORM\Cache\TimestampCacheKey;
28 use Doctrine\ORM\Cache\QueryCacheKey;
29 use Doctrine\ORM\Cache\Persister\CachedPersister;
30 use Doctrine\ORM\Cache\CacheException;
31 use Doctrine\ORM\Mapping\ClassMetadata;
32 use Doctrine\ORM\PersistentCollection;
33 use Doctrine\ORM\EntityManagerInterface;
34 use Doctrine\ORM\Persisters\Entity\EntityPersister;
36 use Doctrine\Common\Util\ClassUtils;
37 use Doctrine\Common\Collections\Criteria;
39 /**
40 * @author Fabio B. Silva <fabio.bat.silva@gmail.com>
41 * @since 2.5
43 abstract class AbstractEntityPersister implements CachedEntityPersister
45 /**
46 * @var \Doctrine\ORM\UnitOfWork
48 protected $uow;
50 /**
51 * @var \Doctrine\ORM\Mapping\ClassMetadataFactory
53 protected $metadataFactory;
55 /**
56 * @var \Doctrine\ORM\Persisters\Entity\EntityPersister
58 protected $persister;
60 /**
61 * @var \Doctrine\ORM\Mapping\ClassMetadata
63 protected $class;
65 /**
66 * @var array
68 protected $queuedCache = array();
70 /**
71 * @var \Doctrine\ORM\Cache\Region
73 protected $region;
75 /**
76 * @var \Doctrine\ORM\Cache\TimestampRegion
78 protected $timestampRegion;
80 /**
81 * @var \Doctrine\ORM\Cache\TimestampCacheKey
83 protected $timestampKey;
85 /**
86 * @var \Doctrine\ORM\Cache\EntityHydrator
88 protected $hydrator;
90 /**
91 * @var \Doctrine\ORM\Cache
93 protected $cache;
95 /**
96 * @var \Doctrine\ORM\Cache\Logging\CacheLogger
98 protected $cacheLogger;
101 * @var string
103 protected $regionName;
106 * Associations configured as FETCH_EAGER, as well as all inverse one-to-one associations.
108 * @var array
110 protected $joinedAssociations;
113 * @param \Doctrine\ORM\Persisters\Entity\EntityPersister $persister The entity persister to cache.
114 * @param \Doctrine\ORM\Cache\Region $region The entity cache region.
115 * @param \Doctrine\ORM\EntityManagerInterface $em The entity manager.
116 * @param \Doctrine\ORM\Mapping\ClassMetadata $class The entity metadata.
118 public function __construct(EntityPersister $persister, Region $region, EntityManagerInterface $em, ClassMetadata $class)
120 $configuration = $em->getConfiguration();
121 $cacheConfig = $configuration->getSecondLevelCacheConfiguration();
122 $cacheFactory = $cacheConfig->getCacheFactory();
124 $this->class = $class;
125 $this->region = $region;
126 $this->persister = $persister;
127 $this->cache = $em->getCache();
128 $this->regionName = $region->getName();
129 $this->uow = $em->getUnitOfWork();
130 $this->metadataFactory = $em->getMetadataFactory();
131 $this->cacheLogger = $cacheConfig->getCacheLogger();
132 $this->timestampRegion = $cacheFactory->getTimestampRegion();
133 $this->hydrator = $cacheFactory->buildEntityHydrator($em, $class);
134 $this->timestampKey = new TimestampCacheKey($this->class->rootEntityName);
138 * {@inheritdoc}
140 public function addInsert($entity)
142 $this->persister->addInsert($entity);
146 * {@inheritdoc}
148 public function getInserts()
150 return $this->persister->getInserts();
154 * {@inheritdoc}
156 public function getSelectSQL($criteria, $assoc = null, $lockMode = null, $limit = null, $offset = null, array $orderBy = null)
158 return $this->persister->getSelectSQL($criteria, $assoc, $lockMode, $limit, $offset, $orderBy);
162 * {@inheritDoc}
164 public function getCountSQL($criteria = array())
166 return $this->persister->getCountSQL($criteria);
170 * {@inheritdoc}
172 public function getInsertSQL()
174 return $this->persister->getInsertSQL();
178 * {@inheritdoc}
180 public function getResultSetMapping()
182 return $this->persister->getResultSetMapping();
186 * {@inheritdoc}
188 public function getSelectConditionStatementSQL($field, $value, $assoc = null, $comparison = null)
190 return $this->persister->getSelectConditionStatementSQL($field, $value, $assoc, $comparison);
194 * {@inheritdoc}
196 public function exists($entity, Criteria $extraConditions = null)
198 if (null === $extraConditions) {
199 $key = new EntityCacheKey($this->class->rootEntityName, $this->class->getIdentifierValues($entity));
201 if ($this->region->contains($key)) {
202 return true;
206 return $this->persister->exists($entity, $extraConditions);
210 * {@inheritdoc}
212 public function getCacheRegion()
214 return $this->region;
218 * @return \Doctrine\ORM\Cache\EntityHydrator
220 public function getEntityHydrator()
222 return $this->hydrator;
226 * {@inheritdoc}
228 public function storeEntityCache($entity, EntityCacheKey $key)
230 $class = $this->class;
231 $className = ClassUtils::getClass($entity);
233 if ($className !== $this->class->name) {
234 $class = $this->metadataFactory->getMetadataFor($className);
237 if ($class->containsForeignIdentifier) {
238 foreach ($class->associationMappings as $name => $assoc) {
239 if (!empty($assoc['id']) && !isset($assoc['cache'])) {
240 throw CacheException::nonCacheableEntityAssociation($class->name, $name);
245 $entry = $this->hydrator->buildCacheEntry($class, $key, $entity);
246 $cached = $this->region->put($key, $entry);
248 if ($this->cacheLogger && $cached) {
249 $this->cacheLogger->entityCachePut($this->regionName, $key);
252 return $cached;
256 * @param object $entity
258 private function storeJoinedAssociations($entity)
260 if ($this->joinedAssociations === null) {
261 $associations = array();
263 foreach ($this->class->associationMappings as $name => $assoc) {
264 if (isset($assoc['cache']) &&
265 ($assoc['type'] & ClassMetadata::TO_ONE) &&
266 ($assoc['fetch'] === ClassMetadata::FETCH_EAGER || ! $assoc['isOwningSide'])) {
268 $associations[] = $name;
272 $this->joinedAssociations = $associations;
275 foreach ($this->joinedAssociations as $name) {
276 $assoc = $this->class->associationMappings[$name];
277 $assocEntity = $this->class->getFieldValue($entity, $name);
279 if ($assocEntity === null) {
280 continue;
283 $assocId = $this->uow->getEntityIdentifier($assocEntity);
284 $assocKey = new EntityCacheKey($assoc['targetEntity'], $assocId);
285 $assocPersister = $this->uow->getEntityPersister($assoc['targetEntity']);
287 $assocPersister->storeEntityCache($assocEntity, $assocKey);
292 * Generates a string of currently query
294 * @param array $query
295 * @param string $criteria
296 * @param array $orderBy
297 * @param integer $limit
298 * @param integer $offset
300 * @return string
302 protected function getHash($query, $criteria, array $orderBy = null, $limit = null, $offset = null)
304 list($params) = ($criteria instanceof Criteria)
305 ? $this->persister->expandCriteriaParameters($criteria)
306 : $this->persister->expandParameters($criteria);
308 return sha1($query . serialize($params) . serialize($orderBy) . $limit . $offset);
312 * {@inheritdoc}
314 public function expandParameters($criteria)
316 return $this->persister->expandParameters($criteria);
320 * {@inheritdoc}
322 public function expandCriteriaParameters(Criteria $criteria)
324 return $this->persister->expandCriteriaParameters($criteria);
328 * {@inheritdoc}
330 public function getClassMetadata()
332 return $this->persister->getClassMetadata();
336 * {@inheritdoc}
338 public function getManyToManyCollection(array $assoc, $sourceEntity, $offset = null, $limit = null)
340 return $this->persister->getManyToManyCollection($assoc, $sourceEntity, $offset, $limit);
344 * {@inheritdoc}
346 public function getOneToManyCollection(array $assoc, $sourceEntity, $offset = null, $limit = null)
348 return $this->persister->getOneToManyCollection($assoc, $sourceEntity, $offset, $limit);
352 * {@inheritdoc}
354 public function getOwningTable($fieldName)
356 return $this->persister->getOwningTable($fieldName);
360 * {@inheritdoc}
362 public function executeInserts()
364 $this->queuedCache['insert'] = $this->persister->getInserts();
366 return $this->persister->executeInserts();
370 * {@inheritdoc}
372 public function load(array $criteria, $entity = null, $assoc = null, array $hints = array(), $lockMode = null, $limit = null, array $orderBy = null)
374 if ($entity !== null || $assoc !== null || ! empty($hints) || $lockMode !== null) {
375 return $this->persister->load($criteria, $entity, $assoc, $hints, $lockMode, $limit, $orderBy);
378 //handle only EntityRepository#findOneBy
379 $query = $this->persister->getSelectSQL($criteria, null, null, $limit, null, $orderBy);
380 $hash = $this->getHash($query, $criteria, null, null, null);
381 $rsm = $this->getResultSetMapping();
382 $queryKey = new QueryCacheKey($hash, 0, Cache::MODE_NORMAL, $this->timestampKey);
383 $queryCache = $this->cache->getQueryCache($this->regionName);
384 $result = $queryCache->get($queryKey, $rsm);
386 if ($result !== null) {
387 if ($this->cacheLogger) {
388 $this->cacheLogger->queryCacheHit($this->regionName, $queryKey);
391 return $result[0];
394 if (($result = $this->persister->load($criteria, $entity, $assoc, $hints, $lockMode, $limit, $orderBy)) === null) {
395 return null;
398 $cached = $queryCache->put($queryKey, $rsm, array($result));
400 if ($this->cacheLogger) {
401 if ($result) {
402 $this->cacheLogger->queryCacheMiss($this->regionName, $queryKey);
405 if ($cached) {
406 $this->cacheLogger->queryCachePut($this->regionName, $queryKey);
410 return $result;
414 * {@inheritdoc}
416 public function loadAll(array $criteria = array(), array $orderBy = null, $limit = null, $offset = null)
418 $query = $this->persister->getSelectSQL($criteria, null, null, $limit, $offset, $orderBy);
419 $hash = $this->getHash($query, $criteria, null, null, null);
420 $rsm = $this->getResultSetMapping();
421 $queryKey = new QueryCacheKey($hash, 0, Cache::MODE_NORMAL, $this->timestampKey);
422 $queryCache = $this->cache->getQueryCache($this->regionName);
423 $result = $queryCache->get($queryKey, $rsm);
425 if ($result !== null) {
426 if ($this->cacheLogger) {
427 $this->cacheLogger->queryCacheHit($this->regionName, $queryKey);
430 return $result;
433 $result = $this->persister->loadAll($criteria, $orderBy, $limit, $offset);
434 $cached = $queryCache->put($queryKey, $rsm, $result);
436 if ($this->cacheLogger) {
437 if ($result) {
438 $this->cacheLogger->queryCacheMiss($this->regionName, $queryKey);
441 if ($cached) {
442 $this->cacheLogger->queryCachePut($this->regionName, $queryKey);
446 return $result;
450 * {@inheritdoc}
452 public function loadById(array $identifier, $entity = null)
454 $cacheKey = new EntityCacheKey($this->class->rootEntityName, $identifier);
455 $cacheEntry = $this->region->get($cacheKey);
456 $class = $this->class;
458 if ($cacheEntry !== null) {
459 if ($cacheEntry->class !== $this->class->name) {
460 $class = $this->metadataFactory->getMetadataFor($cacheEntry->class);
463 if (($entity = $this->hydrator->loadCacheEntry($class, $cacheKey, $cacheEntry, $entity)) !== null) {
464 if ($this->cacheLogger) {
465 $this->cacheLogger->entityCacheHit($this->regionName, $cacheKey);
468 return $entity;
472 $entity = $this->persister->loadById($identifier, $entity);
474 if ($entity === null) {
475 return null;
478 $class = $this->class;
479 $className = ClassUtils::getClass($entity);
481 if ($className !== $this->class->name) {
482 $class = $this->metadataFactory->getMetadataFor($className);
485 $cacheEntry = $this->hydrator->buildCacheEntry($class, $cacheKey, $entity);
486 $cached = $this->region->put($cacheKey, $cacheEntry);
488 if ($cached && ($this->joinedAssociations === null || count($this->joinedAssociations) > 0)) {
489 $this->storeJoinedAssociations($entity);
492 if ($this->cacheLogger) {
493 if ($cached) {
494 $this->cacheLogger->entityCachePut($this->regionName, $cacheKey);
497 $this->cacheLogger->entityCacheMiss($this->regionName, $cacheKey);
500 return $entity;
504 * {@inheritDoc}
506 public function count($criteria = array())
508 return $this->persister->count($criteria);
512 * {@inheritdoc}
514 public function loadCriteria(Criteria $criteria)
516 $orderBy = $criteria->getOrderings();
517 $limit = $criteria->getMaxResults();
518 $offset = $criteria->getFirstResult();
519 $query = $this->persister->getSelectSQL($criteria);
520 $hash = $this->getHash($query, $criteria, $orderBy, $limit, $offset);
521 $rsm = $this->getResultSetMapping();
522 $queryKey = new QueryCacheKey($hash, 0, Cache::MODE_NORMAL, $this->timestampKey);
523 $queryCache = $this->cache->getQueryCache($this->regionName);
524 $cacheResult = $queryCache->get($queryKey, $rsm);
526 if ($cacheResult !== null) {
527 if ($this->cacheLogger) {
528 $this->cacheLogger->queryCacheHit($this->regionName, $queryKey);
531 return $cacheResult;
534 $result = $this->persister->loadCriteria($criteria);
535 $cached = $queryCache->put($queryKey, $rsm, $result);
537 if ($this->cacheLogger) {
538 if ($result) {
539 $this->cacheLogger->queryCacheMiss($this->regionName, $queryKey);
542 if ($cached) {
543 $this->cacheLogger->queryCachePut($this->regionName, $queryKey);
547 return $result;
551 * {@inheritdoc}
553 public function loadManyToManyCollection(array $assoc, $sourceEntity, PersistentCollection $coll)
555 $persister = $this->uow->getCollectionPersister($assoc);
556 $hasCache = ($persister instanceof CachedPersister);
557 $key = null;
559 if ($hasCache) {
560 $ownerId = $this->uow->getEntityIdentifier($coll->getOwner());
561 $key = new CollectionCacheKey($assoc['sourceEntity'], $assoc['fieldName'], $ownerId);
562 $list = $persister->loadCollectionCache($coll, $key);
564 if ($list !== null) {
565 if ($this->cacheLogger) {
566 $this->cacheLogger->collectionCacheHit($persister->getCacheRegion()->getName(), $key);
569 return $list;
573 $list = $this->persister->loadManyToManyCollection($assoc, $sourceEntity, $coll);
575 if ($hasCache) {
576 $persister->storeCollectionCache($key, $list);
578 if ($this->cacheLogger) {
579 $this->cacheLogger->collectionCacheMiss($persister->getCacheRegion()->getName(), $key);
583 return $list;
587 * {@inheritdoc}
589 public function loadOneToManyCollection(array $assoc, $sourceEntity, PersistentCollection $coll)
591 $persister = $this->uow->getCollectionPersister($assoc);
592 $hasCache = ($persister instanceof CachedPersister);
594 if ($hasCache) {
595 $ownerId = $this->uow->getEntityIdentifier($coll->getOwner());
596 $key = new CollectionCacheKey($assoc['sourceEntity'], $assoc['fieldName'], $ownerId);
597 $list = $persister->loadCollectionCache($coll, $key);
599 if ($list !== null) {
600 if ($this->cacheLogger) {
601 $this->cacheLogger->collectionCacheHit($persister->getCacheRegion()->getName(), $key);
604 return $list;
608 $list = $this->persister->loadOneToManyCollection($assoc, $sourceEntity, $coll);
610 if ($hasCache) {
611 $persister->storeCollectionCache($key, $list);
613 if ($this->cacheLogger) {
614 $this->cacheLogger->collectionCacheMiss($persister->getCacheRegion()->getName(), $key);
618 return $list;
622 * {@inheritdoc}
624 public function loadOneToOneEntity(array $assoc, $sourceEntity, array $identifier = array())
626 return $this->persister->loadOneToOneEntity($assoc, $sourceEntity, $identifier);
630 * {@inheritdoc}
632 public function lock(array $criteria, $lockMode)
634 $this->persister->lock($criteria, $lockMode);
638 * {@inheritdoc}
640 public function refresh(array $id, $entity, $lockMode = null)
642 $this->persister->refresh($id, $entity, $lockMode);