vendor/shopware/core/Framework/DataAbstractionLayer/EntityRepository.php line 104

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Framework\DataAbstractionLayer;
  3. use Shopware\Core\Framework\Context;
  4. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityAggregationResultLoadedEvent;
  5. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityIdSearchResultLoadedEvent;
  6. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityLoadedEventFactory;
  7. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntitySearchedEvent;
  8. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntitySearchResultLoadedEvent;
  9. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenContainerEvent;
  10. use Shopware\Core\Framework\DataAbstractionLayer\Read\EntityReaderInterface;
  11. use Shopware\Core\Framework\DataAbstractionLayer\Search\AggregationResult\AggregationResultCollection;
  12. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  13. use Shopware\Core\Framework\DataAbstractionLayer\Search\EntityAggregatorInterface;
  14. use Shopware\Core\Framework\DataAbstractionLayer\Search\EntitySearcherInterface;
  15. use Shopware\Core\Framework\DataAbstractionLayer\Search\EntitySearchResult;
  16. use Shopware\Core\Framework\DataAbstractionLayer\Search\IdSearchResult;
  17. use Shopware\Core\Framework\DataAbstractionLayer\Write\CloneBehavior;
  18. use Shopware\Core\Framework\DataAbstractionLayer\Write\WriteContext;
  19. use Shopware\Core\Framework\Feature;
  20. use Shopware\Core\Framework\Struct\ArrayEntity;
  21. use Shopware\Core\Framework\Uuid\Exception\InvalidUuidException;
  22. use Shopware\Core\Framework\Uuid\Uuid;
  23. use Shopware\Core\Profiling\Profiler;
  24. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  25. class EntityRepository implements EntityRepositoryInterface
  26. {
  27.     private EntityReaderInterface $reader;
  28.     private EntitySearcherInterface $searcher;
  29.     private EntityAggregatorInterface $aggregator;
  30.     private EventDispatcherInterface $eventDispatcher;
  31.     private VersionManager $versionManager;
  32.     private EntityDefinition $definition;
  33.     private ?EntityLoadedEventFactory $eventFactory;
  34.     /**
  35.      * @internal
  36.      *
  37.      * @deprecated tag:v6.5.0 - parameter $eventFactory will be required
  38.      */
  39.     public function __construct(
  40.         EntityDefinition $definition,
  41.         EntityReaderInterface $reader,
  42.         VersionManager $versionManager,
  43.         EntitySearcherInterface $searcher,
  44.         EntityAggregatorInterface $aggregator,
  45.         EventDispatcherInterface $eventDispatcher,
  46.         ?EntityLoadedEventFactory $eventFactory = null
  47.     ) {
  48.         $this->reader = $reader;
  49.         $this->searcher = $searcher;
  50.         $this->aggregator = $aggregator;
  51.         $this->eventDispatcher = $eventDispatcher;
  52.         $this->versionManager = $versionManager;
  53.         $this->definition = $definition;
  54.         if ($eventFactory !== null) {
  55.             $this->eventFactory = $eventFactory;
  56.         } else {
  57.             Feature::triggerDeprecationOrThrow(
  58.                 'v6.5.0.0',
  59.                 sprintf('EntityRepository constructor for definition %s requires the event factory as required 7th parameter in v6.5.0.0', $definition->getEntityName())
  60.             );
  61.         }
  62.     }
  63.     /**
  64.      * @deprecated tag:v6.5.0 - Will be removed, inject entity loaded event factory in __construct
  65.      */
  66.     public function setEntityLoadedEventFactory(EntityLoadedEventFactory $eventFactory): void
  67.     {
  68.         if (isset($this->eventFactory)) {
  69.             return;
  70.         }
  71.         Feature::triggerDeprecationOrThrow(
  72.             'v6.5.0.0',
  73.             sprintf('Repository for definition %s requires the event factory as __construct parameter', $this->definition->getEntityName())
  74.         );
  75.         $this->eventFactory = $eventFactory;
  76.     }
  77.     public function getDefinition(): EntityDefinition
  78.     {
  79.         return $this->definition;
  80.     }
  81.     public function search(Criteria $criteria, Context $context): EntitySearchResult
  82.     {
  83.         if (!$criteria->getTitle()) {
  84.             return $this->_search($criteria, $context);
  85.         }
  86.         return Profiler::trace($criteria->getTitle(), function () use ($criteria, $context) {
  87.             return $this->_search($criteria, $context);
  88.         }, 'repository');
  89.     }
  90.     public function aggregate(Criteria $criteria, Context $context): AggregationResultCollection
  91.     {
  92.         $criteria = clone $criteria;
  93.         $result = $this->aggregator->aggregate($this->definition, $criteria, $context);
  94.         $event = new EntityAggregationResultLoadedEvent($this->definition, $result, $context);
  95.         $this->eventDispatcher->dispatch($event, $event->getName());
  96.         return $result;
  97.     }
  98.     public function searchIds(Criteria $criteria, Context $context): IdSearchResult
  99.     {
  100.         $criteria = clone $criteria;
  101.         $this->eventDispatcher->dispatch(new EntitySearchedEvent($criteria, $this->definition, $context));
  102.         $result = $this->searcher->search($this->definition, $criteria, $context);
  103.         $event = new EntityIdSearchResultLoadedEvent($this->definition, $result);
  104.         $this->eventDispatcher->dispatch($event, $event->getName());
  105.         return $result;
  106.     }
  107.     public function update(array $data, Context $context): EntityWrittenContainerEvent
  108.     {
  109.         $affected = $this->versionManager->update($this->definition, $data, WriteContext::createFromContext($context));
  110.         $event = EntityWrittenContainerEvent::createWithWrittenEvents($affected, $context, []);
  111.         $this->eventDispatcher->dispatch($event);
  112.         return $event;
  113.     }
  114.     public function upsert(array $data, Context $context): EntityWrittenContainerEvent
  115.     {
  116.         $affected = $this->versionManager->upsert($this->definition, $data, WriteContext::createFromContext($context));
  117.         $event = EntityWrittenContainerEvent::createWithWrittenEvents($affected, $context, []);
  118.         $this->eventDispatcher->dispatch($event);
  119.         return $event;
  120.     }
  121.     public function create(array $data, Context $context): EntityWrittenContainerEvent
  122.     {
  123.         $affected = $this->versionManager->insert($this->definition, $data, WriteContext::createFromContext($context));
  124.         $event = EntityWrittenContainerEvent::createWithWrittenEvents($affected, $context, []);
  125.         $this->eventDispatcher->dispatch($event);
  126.         return $event;
  127.     }
  128.     public function delete(array $ids, Context $context): EntityWrittenContainerEvent
  129.     {
  130.         $affected = $this->versionManager->delete($this->definition, $ids, WriteContext::createFromContext($context));
  131.         $event = EntityWrittenContainerEvent::createWithDeletedEvents($affected->getDeleted(), $context, $affected->getNotFound());
  132.         if ($affected->getWritten()) {
  133.             $updates = EntityWrittenContainerEvent::createWithWrittenEvents($affected->getWritten(), $context, []);
  134.             $event->addEvent(...$updates->getEvents());
  135.         }
  136.         $this->eventDispatcher->dispatch($event);
  137.         return $event;
  138.     }
  139.     public function createVersion(string $id, Context $context, ?string $name = null, ?string $versionId = null): string
  140.     {
  141.         if (!$this->definition->isVersionAware()) {
  142.             throw new \RuntimeException(sprintf('Entity %s is not version aware', $this->definition->getEntityName()));
  143.         }
  144.         return $this->versionManager->createVersion($this->definition, $id, WriteContext::createFromContext($context), $name, $versionId);
  145.     }
  146.     public function merge(string $versionId, Context $context): void
  147.     {
  148.         if (!$this->definition->isVersionAware()) {
  149.             throw new \RuntimeException(sprintf('Entity %s is not version aware', $this->definition->getEntityName()));
  150.         }
  151.         $this->versionManager->merge($versionId, WriteContext::createFromContext($context));
  152.     }
  153.     public function clone(string $id, Context $context, ?string $newId = null, ?CloneBehavior $behavior = null): EntityWrittenContainerEvent
  154.     {
  155.         $newId = $newId ?? Uuid::randomHex();
  156.         if (!Uuid::isValid($newId)) {
  157.             throw new InvalidUuidException($newId);
  158.         }
  159.         $affected = $this->versionManager->clone(
  160.             $this->definition,
  161.             $id,
  162.             $newId,
  163.             $context->getVersionId(),
  164.             WriteContext::createFromContext($context),
  165.             $behavior ?? new CloneBehavior()
  166.         );
  167.         $event = EntityWrittenContainerEvent::createWithWrittenEvents($affected, $context, []);
  168.         $this->eventDispatcher->dispatch($event);
  169.         return $event;
  170.     }
  171.     private function read(Criteria $criteria, Context $context): EntityCollection
  172.     {
  173.         $criteria = clone $criteria;
  174.         $entities = $this->reader->read($this->definition, $criteria, $context);
  175.         if ($this->eventFactory === null) {
  176.             throw new \RuntimeException('Event loaded factory was not injected');
  177.         }
  178.         if ($criteria->getFields() === []) {
  179.             $event = $this->eventFactory->create($entities->getElements(), $context);
  180.         } else {
  181.             $event = $this->eventFactory->createPartial($entities->getElements(), $context);
  182.         }
  183.         $this->eventDispatcher->dispatch($event);
  184.         return $entities;
  185.     }
  186.     private function _search(Criteria $criteria, Context $context): EntitySearchResult
  187.     {
  188.         $criteria = clone $criteria;
  189.         $aggregations = null;
  190.         if ($criteria->getAggregations()) {
  191.             $aggregations = $this->aggregate($criteria, $context);
  192.         }
  193.         if (!RepositorySearchDetector::isSearchRequired($this->definition, $criteria)) {
  194.             $this->eventDispatcher->dispatch(
  195.                 new EntitySearchedEvent($criteria, $this->definition, $context)
  196.             );
  197.             $entities = $this->read($criteria, $context);
  198.             return new EntitySearchResult($this->definition->getEntityName(), $entities->count(), $entities, $aggregations, $criteria, $context);
  199.         }
  200.         $ids = $this->searchIds($criteria, $context);
  201.         if (empty($ids->getIds())) {
  202.             $collection = $this->definition->getCollectionClass();
  203.             return new EntitySearchResult($this->definition->getEntityName(), $ids->getTotal(), new $collection(), $aggregations, $criteria, $context);
  204.         }
  205.         $readCriteria = $criteria->cloneForRead($ids->getIds());
  206.         $entities = $this->read($readCriteria, $context);
  207.         $search = $ids->getData();
  208.         /** @var Entity $element */
  209.         foreach ($entities as $element) {
  210.             if (!\array_key_exists($element->getUniqueIdentifier(), $search)) {
  211.                 continue;
  212.             }
  213.             $data = $search[$element->getUniqueIdentifier()];
  214.             unset($data['id']);
  215.             if (empty($data)) {
  216.                 continue;
  217.             }
  218.             $element->addExtension('search', new ArrayEntity($data));
  219.         }
  220.         $result = new EntitySearchResult($this->definition->getEntityName(), $ids->getTotal(), $entities, $aggregations, $criteria, $context);
  221.         $result->addState(...$ids->getStates());
  222.         $event = new EntitySearchResultLoadedEvent($this->definition, $result);
  223.         $this->eventDispatcher->dispatch($event, $event->getName());
  224.         return $result;
  225.     }
  226. }