From bf6655a534a6775d30cafa67bd801276bda1d98d Mon Sep 17 00:00:00 2001 From: polo Date: Tue, 13 Aug 2024 23:45:21 +0200 Subject: =?UTF-8?q?VERSION=200.2=20doctrine=20ORM=20et=20entit=C3=A9s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Collection/AbstractCollectionPersister.php | 168 +++++++++++++++++++++ .../Collection/CachedCollectionPersister.php | 36 +++++ ...NonStrictReadWriteCachedCollectionPersister.php | 74 +++++++++ .../ReadOnlyCachedCollectionPersister.php | 24 +++ .../ReadWriteCachedCollectionPersister.php | 103 +++++++++++++ 5 files changed, 405 insertions(+) create mode 100644 vendor/doctrine/orm/src/Cache/Persister/Collection/AbstractCollectionPersister.php create mode 100644 vendor/doctrine/orm/src/Cache/Persister/Collection/CachedCollectionPersister.php create mode 100644 vendor/doctrine/orm/src/Cache/Persister/Collection/NonStrictReadWriteCachedCollectionPersister.php create mode 100644 vendor/doctrine/orm/src/Cache/Persister/Collection/ReadOnlyCachedCollectionPersister.php create mode 100644 vendor/doctrine/orm/src/Cache/Persister/Collection/ReadWriteCachedCollectionPersister.php (limited to 'vendor/doctrine/orm/src/Cache/Persister/Collection') diff --git a/vendor/doctrine/orm/src/Cache/Persister/Collection/AbstractCollectionPersister.php b/vendor/doctrine/orm/src/Cache/Persister/Collection/AbstractCollectionPersister.php new file mode 100644 index 0000000..8c087a8 --- /dev/null +++ b/vendor/doctrine/orm/src/Cache/Persister/Collection/AbstractCollectionPersister.php @@ -0,0 +1,168 @@ +getConfiguration(); + $cacheConfig = $configuration->getSecondLevelCacheConfiguration(); + $cacheFactory = $cacheConfig->getCacheFactory(); + + $this->regionName = $region->getName(); + $this->uow = $em->getUnitOfWork(); + $this->metadataFactory = $em->getMetadataFactory(); + $this->cacheLogger = $cacheConfig->getCacheLogger(); + $this->hydrator = $cacheFactory->buildCollectionHydrator($em, $association); + $this->sourceEntity = $em->getClassMetadata($association->sourceEntity); + $this->targetEntity = $em->getClassMetadata($association->targetEntity); + } + + public function getCacheRegion(): Region + { + return $this->region; + } + + public function getSourceEntityMetadata(): ClassMetadata + { + return $this->sourceEntity; + } + + public function getTargetEntityMetadata(): ClassMetadata + { + return $this->targetEntity; + } + + public function loadCollectionCache(PersistentCollection $collection, CollectionCacheKey $key): array|null + { + $cache = $this->region->get($key); + + if ($cache === null) { + return null; + } + + return $this->hydrator->loadCacheEntry($this->sourceEntity, $key, $cache, $collection); + } + + public function storeCollectionCache(CollectionCacheKey $key, Collection|array $elements): void + { + $associationMapping = $this->sourceEntity->associationMappings[$key->association]; + $targetPersister = $this->uow->getEntityPersister($this->targetEntity->rootEntityName); + assert($targetPersister instanceof CachedEntityPersister); + $targetRegion = $targetPersister->getCacheRegion(); + $targetHydrator = $targetPersister->getEntityHydrator(); + + // Only preserve ordering if association configured it + if (! $associationMapping->isIndexed()) { + // Elements may be an array or a Collection + $elements = array_values($elements instanceof Collection ? $elements->getValues() : $elements); + } + + $entry = $this->hydrator->buildCacheEntry($this->targetEntity, $key, $elements); + + foreach ($entry->identifiers as $index => $entityKey) { + if ($targetRegion->contains($entityKey)) { + continue; + } + + $class = $this->targetEntity; + $className = DefaultProxyClassNameResolver::getClass($elements[$index]); + + if ($className !== $this->targetEntity->name) { + $class = $this->metadataFactory->getMetadataFor($className); + } + + $entity = $elements[$index]; + $entityEntry = $targetHydrator->buildCacheEntry($class, $entityKey, $entity); + + $targetRegion->put($entityKey, $entityEntry); + } + + if ($this->region->put($key, $entry)) { + $this->cacheLogger?->collectionCachePut($this->regionName, $key); + } + } + + public function contains(PersistentCollection $collection, object $element): bool + { + return $this->persister->contains($collection, $element); + } + + public function containsKey(PersistentCollection $collection, mixed $key): bool + { + return $this->persister->containsKey($collection, $key); + } + + public function count(PersistentCollection $collection): int + { + $ownerId = $this->uow->getEntityIdentifier($collection->getOwner()); + $key = new CollectionCacheKey($this->sourceEntity->rootEntityName, $this->association->fieldName, $ownerId); + $entry = $this->region->get($key); + + if ($entry !== null) { + return count($entry->identifiers); + } + + return $this->persister->count($collection); + } + + public function get(PersistentCollection $collection, mixed $index): mixed + { + return $this->persister->get($collection, $index); + } + + /** + * {@inheritDoc} + */ + public function slice(PersistentCollection $collection, int $offset, int|null $length = null): array + { + return $this->persister->slice($collection, $offset, $length); + } + + /** + * {@inheritDoc} + */ + public function loadCriteria(PersistentCollection $collection, Criteria $criteria): array + { + return $this->persister->loadCriteria($collection, $criteria); + } +} diff --git a/vendor/doctrine/orm/src/Cache/Persister/Collection/CachedCollectionPersister.php b/vendor/doctrine/orm/src/Cache/Persister/Collection/CachedCollectionPersister.php new file mode 100644 index 0000000..6b10c80 --- /dev/null +++ b/vendor/doctrine/orm/src/Cache/Persister/Collection/CachedCollectionPersister.php @@ -0,0 +1,36 @@ +queuedCache['update'])) { + foreach ($this->queuedCache['update'] as $item) { + $this->storeCollectionCache($item['key'], $item['list']); + } + } + + if (isset($this->queuedCache['delete'])) { + foreach ($this->queuedCache['delete'] as $key) { + $this->region->evict($key); + } + } + + $this->queuedCache = []; + } + + public function afterTransactionRolledBack(): void + { + $this->queuedCache = []; + } + + public function delete(PersistentCollection $collection): void + { + $ownerId = $this->uow->getEntityIdentifier($collection->getOwner()); + $key = new CollectionCacheKey($this->sourceEntity->rootEntityName, $this->association->fieldName, $ownerId); + + $this->persister->delete($collection); + + $this->queuedCache['delete'][spl_object_id($collection)] = $key; + } + + public function update(PersistentCollection $collection): void + { + $isInitialized = $collection->isInitialized(); + $isDirty = $collection->isDirty(); + + if (! $isInitialized && ! $isDirty) { + return; + } + + $ownerId = $this->uow->getEntityIdentifier($collection->getOwner()); + $key = new CollectionCacheKey($this->sourceEntity->rootEntityName, $this->association->fieldName, $ownerId); + + // Invalidate non initialized collections OR ordered collection + if ($isDirty && ! $isInitialized || $this->association->isOrdered()) { + $this->persister->update($collection); + + $this->queuedCache['delete'][spl_object_id($collection)] = $key; + + return; + } + + $this->persister->update($collection); + + $this->queuedCache['update'][spl_object_id($collection)] = [ + 'key' => $key, + 'list' => $collection, + ]; + } +} diff --git a/vendor/doctrine/orm/src/Cache/Persister/Collection/ReadOnlyCachedCollectionPersister.php b/vendor/doctrine/orm/src/Cache/Persister/Collection/ReadOnlyCachedCollectionPersister.php new file mode 100644 index 0000000..96e0a4b --- /dev/null +++ b/vendor/doctrine/orm/src/Cache/Persister/Collection/ReadOnlyCachedCollectionPersister.php @@ -0,0 +1,24 @@ +isDirty() && $collection->getSnapshot()) { + throw CannotUpdateReadOnlyCollection::fromEntityAndField( + DefaultProxyClassNameResolver::getClass($collection->getOwner()), + $this->association->fieldName, + ); + } + + parent::update($collection); + } +} diff --git a/vendor/doctrine/orm/src/Cache/Persister/Collection/ReadWriteCachedCollectionPersister.php b/vendor/doctrine/orm/src/Cache/Persister/Collection/ReadWriteCachedCollectionPersister.php new file mode 100644 index 0000000..347a065 --- /dev/null +++ b/vendor/doctrine/orm/src/Cache/Persister/Collection/ReadWriteCachedCollectionPersister.php @@ -0,0 +1,103 @@ +queuedCache['update'])) { + foreach ($this->queuedCache['update'] as $item) { + $this->region->evict($item['key']); + } + } + + if (isset($this->queuedCache['delete'])) { + foreach ($this->queuedCache['delete'] as $item) { + $this->region->evict($item['key']); + } + } + + $this->queuedCache = []; + } + + public function afterTransactionRolledBack(): void + { + if (isset($this->queuedCache['update'])) { + foreach ($this->queuedCache['update'] as $item) { + $this->region->evict($item['key']); + } + } + + if (isset($this->queuedCache['delete'])) { + foreach ($this->queuedCache['delete'] as $item) { + $this->region->evict($item['key']); + } + } + + $this->queuedCache = []; + } + + public function delete(PersistentCollection $collection): void + { + $ownerId = $this->uow->getEntityIdentifier($collection->getOwner()); + $key = new CollectionCacheKey($this->sourceEntity->rootEntityName, $this->association->fieldName, $ownerId); + $lock = $this->region->lock($key); + + $this->persister->delete($collection); + + if ($lock === null) { + return; + } + + $this->queuedCache['delete'][spl_object_id($collection)] = [ + 'key' => $key, + 'lock' => $lock, + ]; + } + + public function update(PersistentCollection $collection): void + { + $isInitialized = $collection->isInitialized(); + $isDirty = $collection->isDirty(); + + if (! $isInitialized && ! $isDirty) { + return; + } + + $this->persister->update($collection); + + $ownerId = $this->uow->getEntityIdentifier($collection->getOwner()); + $key = new CollectionCacheKey($this->sourceEntity->rootEntityName, $this->association->fieldName, $ownerId); + $lock = $this->region->lock($key); + + if ($lock === null) { + return; + } + + $this->queuedCache['update'][spl_object_id($collection)] = [ + 'key' => $key, + 'lock' => $lock, + ]; + } +} -- cgit v1.2.3