vendor/shopware/core/System/SalesChannel/Entity/SalesChannelRepository.php line 164

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\System\SalesChannel\Entity;
  3. use Shopware\Core\Framework\DataAbstractionLayer\Entity;
  4. use Shopware\Core\Framework\DataAbstractionLayer\EntityCollection;
  5. use Shopware\Core\Framework\DataAbstractionLayer\EntityDefinition;
  6. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityAggregationResultLoadedEvent;
  7. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityLoadedEventFactory;
  8. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntitySearchResultLoadedEvent;
  9. use Shopware\Core\Framework\DataAbstractionLayer\Exception\InconsistentCriteriaIdsException;
  10. use Shopware\Core\Framework\DataAbstractionLayer\Field\AssociationField;
  11. use Shopware\Core\Framework\DataAbstractionLayer\Read\EntityReaderInterface;
  12. use Shopware\Core\Framework\DataAbstractionLayer\RepositorySearchDetector;
  13. use Shopware\Core\Framework\DataAbstractionLayer\Search\AggregationResult\AggregationResultCollection;
  14. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  15. use Shopware\Core\Framework\DataAbstractionLayer\Search\EntityAggregatorInterface;
  16. use Shopware\Core\Framework\DataAbstractionLayer\Search\EntitySearcherInterface;
  17. use Shopware\Core\Framework\DataAbstractionLayer\Search\EntitySearchResult;
  18. use Shopware\Core\Framework\DataAbstractionLayer\Search\IdSearchResult;
  19. use Shopware\Core\Framework\Feature;
  20. use Shopware\Core\Framework\Struct\ArrayEntity;
  21. use Shopware\Core\System\SalesChannel\Event\SalesChannelProcessCriteriaEvent;
  22. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  23. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  24. class SalesChannelRepository implements SalesChannelRepositoryInterface
  25. {
  26.     /**
  27.      * @var EntityDefinition
  28.      */
  29.     protected $definition;
  30.     /**
  31.      * @var EntityReaderInterface
  32.      */
  33.     protected $reader;
  34.     /**
  35.      * @var EntitySearcherInterface
  36.      */
  37.     protected $searcher;
  38.     /**
  39.      * @var EntityAggregatorInterface
  40.      */
  41.     protected $aggregator;
  42.     /**
  43.      * @var EventDispatcherInterface
  44.      */
  45.     protected $eventDispatcher;
  46.     private ?EntityLoadedEventFactory $eventFactory;
  47.     public function __construct(
  48.         EntityDefinition $definition,
  49.         EntityReaderInterface $reader,
  50.         EntitySearcherInterface $searcher,
  51.         EntityAggregatorInterface $aggregator,
  52.         EventDispatcherInterface $eventDispatcher,
  53.         ?EntityLoadedEventFactory $eventFactory
  54.     ) {
  55.         $this->definition $definition;
  56.         $this->reader $reader;
  57.         $this->searcher $searcher;
  58.         $this->aggregator $aggregator;
  59.         $this->eventDispatcher $eventDispatcher;
  60.         if ($eventFactory !== null) {
  61.             $this->eventFactory $eventFactory;
  62.         } else {
  63.             Feature::throwException('FEATURE_NEXT_16155'sprintf('Sales channel repository for definition %s requires the event factory as __construct parameter'$definition->getEntityName()));
  64.         }
  65.     }
  66.     /**
  67.      * @deprecated tag:v6.5.0 - Will be removed,
  68.      */
  69.     public function setEntityLoadedEventFactory(EntityLoadedEventFactory $eventFactory): void
  70.     {
  71.         if ($this->eventFactory === null) {
  72.             Feature::throwException('FEATURE_NEXT_16155'sprintf('Sales channel repository for definition %s requires the event factory as __construct parameter'$this->definition->getEntityName()));
  73.         }
  74.         $this->eventFactory $eventFactory;
  75.     }
  76.     /**
  77.      * @throws InconsistentCriteriaIdsException
  78.      */
  79.     public function search(Criteria $criteriaSalesChannelContext $salesChannelContext): EntitySearchResult
  80.     {
  81.         $criteria = clone $criteria;
  82.         $this->processCriteria($criteria$salesChannelContext);
  83.         $aggregations null;
  84.         if ($criteria->getAggregations()) {
  85.             $aggregations $this->aggregate($criteria$salesChannelContext);
  86.         }
  87.         if (!RepositorySearchDetector::isSearchRequired($this->definition$criteria)) {
  88.             $entities $this->read($criteria$salesChannelContext);
  89.             return new EntitySearchResult($this->definition->getEntityName(), $entities->count(), $entities$aggregations$criteria$salesChannelContext->getContext());
  90.         }
  91.         $ids $this->doSearch($criteria$salesChannelContext);
  92.         if (empty($ids->getIds())) {
  93.             $collection $this->definition->getCollectionClass();
  94.             return new EntitySearchResult($this->definition->getEntityName(), $ids->getTotal(), new $collection(), $aggregations$criteria$salesChannelContext->getContext());
  95.         }
  96.         $readCriteria $criteria->cloneForRead($ids->getIds());
  97.         $entities $this->read($readCriteria$salesChannelContext);
  98.         $search $ids->getData();
  99.         /** @var Entity $element */
  100.         foreach ($entities as $element) {
  101.             if (!\array_key_exists($element->getUniqueIdentifier(), $search)) {
  102.                 continue;
  103.             }
  104.             $data $search[$element->getUniqueIdentifier()];
  105.             unset($data['id']);
  106.             if (empty($data)) {
  107.                 continue;
  108.             }
  109.             $element->addExtension('search', new ArrayEntity($data));
  110.         }
  111.         $result = new EntitySearchResult($this->definition->getEntityName(), $ids->getTotal(), $entities$aggregations$criteria$salesChannelContext->getContext());
  112.         $result->addState(...$ids->getStates());
  113.         $event = new EntitySearchResultLoadedEvent($this->definition$result);
  114.         $this->eventDispatcher->dispatch($event$event->getName());
  115.         $event = new SalesChannelEntitySearchResultLoadedEvent($this->definition$result$salesChannelContext);
  116.         $this->eventDispatcher->dispatch($event$event->getName());
  117.         return $result;
  118.     }
  119.     public function aggregate(Criteria $criteriaSalesChannelContext $salesChannelContext): AggregationResultCollection
  120.     {
  121.         $criteria = clone $criteria;
  122.         $this->processCriteria($criteria$salesChannelContext);
  123.         $result $this->aggregator->aggregate($this->definition$criteria$salesChannelContext->getContext());
  124.         $event = new EntityAggregationResultLoadedEvent($this->definition$result$salesChannelContext->getContext());
  125.         $this->eventDispatcher->dispatch($event$event->getName());
  126.         return $result;
  127.     }
  128.     public function searchIds(Criteria $criteriaSalesChannelContext $salesChannelContext): IdSearchResult
  129.     {
  130.         $criteria = clone $criteria;
  131.         $this->processCriteria($criteria$salesChannelContext);
  132.         return $this->doSearch($criteria$salesChannelContext);
  133.     }
  134.     private function read(Criteria $criteriaSalesChannelContext $salesChannelContext): EntityCollection
  135.     {
  136.         $criteria = clone $criteria;
  137.         $entities $this->reader->read($this->definition$criteria$salesChannelContext->getContext());
  138.         if ($this->eventFactory === null) {
  139.             throw new \RuntimeException('Event loaded factory was not injected');
  140.         }
  141.         $events $this->eventFactory->createForSalesChannel($entities->getElements(), $salesChannelContext);
  142.         foreach ($events as $event) {
  143.             $this->eventDispatcher->dispatch($event);
  144.         }
  145.         return $entities;
  146.     }
  147.     private function doSearch(Criteria $criteriaSalesChannelContext $salesChannelContext): IdSearchResult
  148.     {
  149.         $result $this->searcher->search($this->definition$criteria$salesChannelContext->getContext());
  150.         $event = new SalesChannelEntityIdSearchResultLoadedEvent($this->definition$result$salesChannelContext);
  151.         $this->eventDispatcher->dispatch($event$event->getName());
  152.         return $result;
  153.     }
  154.     private function processCriteria(Criteria $topCriteriaSalesChannelContext $salesChannelContext): void
  155.     {
  156.         if (!$this->definition instanceof SalesChannelDefinitionInterface) {
  157.             return;
  158.         }
  159.         $queue = [
  160.             ['definition' => $this->definition'criteria' => $topCriteria],
  161.         ];
  162.         $maxCount 100;
  163.         $processed = [];
  164.         // process all associations breadth-first
  165.         while (!empty($queue) && --$maxCount 0) {
  166.             $cur array_shift($queue);
  167.             /** @var EntityDefinition $definition */
  168.             $definition $cur['definition'];
  169.             $criteria $cur['criteria'];
  170.             if (isset($processed[\get_class($definition)])) {
  171.                 continue;
  172.             }
  173.             if ($definition instanceof SalesChannelDefinitionInterface) {
  174.                 $definition->processCriteria($criteria$salesChannelContext);
  175.                 $eventName \sprintf('sales_channel.%s.process.criteria'$definition->getEntityName());
  176.                 $event = new SalesChannelProcessCriteriaEvent($criteria$salesChannelContext);
  177.                 $this->eventDispatcher->dispatch($event$eventName);
  178.             }
  179.             $processed[\get_class($definition)] = true;
  180.             foreach ($criteria->getAssociations() as $associationName => $associationCriteria) {
  181.                 // find definition
  182.                 $field $definition->getField($associationName);
  183.                 if (!$field instanceof AssociationField) {
  184.                     continue;
  185.                 }
  186.                 $referenceDefinition $field->getReferenceDefinition();
  187.                 $queue[] = ['definition' => $referenceDefinition'criteria' => $associationCriteria];
  188.             }
  189.         }
  190.     }
  191. }