custom/plugins/IntediaDoofinderSW6/src/Core/Content/ProductExport/Subscriber/ProductExportSubscriber.php line 63

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Intedia\Doofinder\Core\Content\ProductExport\Subscriber;
  3. use Doctrine\DBAL\Connection;
  4. use Shopware\Core\Content\Category\CategoryDefinition;
  5. use Shopware\Core\Content\Category\CategoryEntity;
  6. use Shopware\Core\Content\Category\Service\NavigationLoaderInterface;
  7. use Shopware\Core\Content\Category\Tree\Tree;
  8. use Shopware\Core\Content\Product\Aggregate\ProductVisibility\ProductVisibilityDefinition;
  9. use Shopware\Core\Content\Product\SalesChannel\ProductAvailableFilter;
  10. use Shopware\Core\Content\ProductExport\Event\ProductExportProductCriteriaEvent;
  11. use Shopware\Core\Content\ProductExport\Event\ProductExportRenderBodyContextEvent;
  12. use Shopware\Core\Content\ProductExport\ProductExportEntity;
  13. use Shopware\Core\Content\ProductStream\Service\ProductStreamBuilderInterface;
  14. use Shopware\Core\Framework\Context;
  15. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  16. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  17. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  18. use Shopware\Core\System\SalesChannel\Entity\SalesChannelRepositoryInterface;
  19. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  20. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  21. class ProductExportSubscriber implements EventSubscriberInterface
  22. {
  23.     protected NavigationLoaderInterface $navigationLoader;
  24.     protected ProductStreamBuilderInterface $productStreamBuilder;
  25.     protected EntityRepositoryInterface $categoryRepository;
  26.     protected Connection $connection;
  27.     protected SalesChannelRepositoryInterface $salesChannelRepository;
  28.     protected ?Tree $categoryTree null;
  29.     protected array $productStreamCategories = [];
  30.     protected array $productNumberIdMapping = [];
  31.     protected bool $usesDooFinderGroupIdExtension false;
  32.     protected bool $usesDooFinderCategoriesExtension false;
  33.     protected bool $runOnCriteriaEvent false;
  34.     public function __construct(NavigationLoaderInterface $navigationLoaderProductStreamBuilderInterface $productStreamBuilderEntityRepositoryInterface $categoryRepositoryConnection $connectionSalesChannelRepositoryInterface $salesChannelRepository)
  35.     {
  36.         $this->navigationLoader       $navigationLoader;
  37.         $this->productStreamBuilder   $productStreamBuilder;
  38.         $this->categoryRepository     $categoryRepository;
  39.         $this->connection             $connection;
  40.         $this->salesChannelRepository $salesChannelRepository;
  41.     }
  42.     public static function getSubscribedEvents(): array
  43.     {
  44.         return [
  45.             ProductExportProductCriteriaEvent::class   => 'onProductExportCriteriaEvent',
  46.             ProductExportRenderBodyContextEvent::class => 'onProductExportRenderBodyContextEvent'
  47.         ];
  48.     }
  49.     public function onProductExportCriteriaEvent(ProductExportProductCriteriaEvent $event): void
  50.     {
  51.         $criteria      $event->getCriteria();
  52.         $productExport $event->getProductExport();
  53.         $context       $event->getSalesChannelContext();
  54.         $this->usesDooFinderCategoriesExtension $this->usesDooFinderCategoriesExtension($productExport);
  55.         $this->usesDooFinderGroupIdExtension    $this->usesDooFinderGroupIdExtension($productExport);
  56.         if ($this->usesDooFinderCategoriesExtension || $this->usesDooFinderGroupIdExtension) {
  57.             $this->raiseMemoryLimit();
  58.             if ($this->usesDooFinderCategoriesExtension) {
  59.                 $this->addDooFinderCategoriesData($criteria$context);
  60.             }
  61.             if ($this->usesDooFinderGroupIdExtension) {
  62.                 $this->addDooFinderGroupIdData();
  63.             }
  64.         }
  65.         $this->runOnCriteriaEvent true;
  66.     }
  67.     protected function addDooFinderGroupIdData(): void
  68.     {
  69.         $this->productNumberIdMapping $this->getProductNumberIdMapping();
  70.     }
  71.     protected function addDooFinderCategoriesData(Criteria $criteriaSalesChannelContext $context): void
  72.     {
  73.         if (!$criteria->hasAssociation('categories')) {
  74.             $criteria->addAssociation('categories');
  75.         }
  76.         if ($context->getSalesChannel()) {
  77.             $navigationCategoryId $context->getSalesChannel()->getNavigationCategoryId();
  78.             $this->categoryTree   $this->navigationLoader->load($navigationCategoryId$context$navigationCategoryId10);
  79.             $this->buildProductStreamCategories($context);
  80.         }
  81.     }
  82.     protected function buildProductStreamCategories(SalesChannelContext $context)
  83.     {
  84.         foreach ($this->getCategoriesHavingStreams($context->getContext()) as $category)
  85.         {
  86.             foreach ($this->getProductIdsInStream($category$context) as $productId)
  87.             {
  88.                 if (!array_key_exists($productId$this->productStreamCategories)) {
  89.                     $this->productStreamCategories[$productId] = [];
  90.                 }
  91.                 $this->productStreamCategories[$productId][] = $category->getId();
  92.             }
  93.         }
  94.     }
  95.     public function onProductExportRenderBodyContextEvent(ProductExportRenderBodyContextEvent $event): void
  96.     {
  97.         $context $event->getContext();
  98.         if ($this->runOnCriteriaEvent) {
  99.             if ($this->usesDooFinderGroupIdExtension) {
  100.                 $context['groupIds'] = $this->productNumberIdMapping ?: [];
  101.             }
  102.             if ($this->usesDooFinderCategoriesExtension) {
  103.                 $context['categoryTree']            = $this->categoryTree ?: null;
  104.                 $context['productStreamCategories'] = $this->productStreamCategories ?: [];
  105.             }
  106.         }
  107.         else {
  108.             if (!array_key_exists('groupIds'$context)) {
  109.                 $context['groupIds'] = [];
  110.             }
  111.             if (!array_key_exists('categoryTree'$context)) {
  112.                 $context['categoryTree'] = null;
  113.             }
  114.             if (!array_key_exists('productStreamCategories'$context)) {
  115.                 $context['productStreamCategories'] = [];
  116.             }
  117.         }
  118.         $event->setContext($context);
  119.     }
  120.     protected function getProductIdsInStream(CategoryEntity $categorySalesChannelContext $salesChannelContext): array
  121.     {
  122.         if (is_null($category->getProductStreamId())) {
  123.             return [];
  124.         }
  125.         try {
  126.             $filters $this->productStreamBuilder->buildFilters($category->getProductStreamId(), $salesChannelContext->getContext());
  127.             $criteria = new Criteria();
  128.             $criteria->addFilter(...$filters);
  129.             $criteria->addFilter(
  130.                 new ProductAvailableFilter($salesChannelContext->getSalesChannel()->getId(), ProductVisibilityDefinition::VISIBILITY_ALL)
  131.             );
  132.             return $this->salesChannelRepository->searchIds($criteria$salesChannelContext)->getIds();
  133.         }
  134.         catch (\Exception $exception) {
  135.         }
  136.         return [];
  137.     }
  138.     protected function getCategoriesHavingStreams(Context $context)
  139.     {
  140.         $criteria = new Criteria();
  141.         $criteria->addFilter(new EqualsFilter('productAssignmentType'CategoryDefinition::PRODUCT_ASSIGNMENT_TYPE_PRODUCT_STREAM));
  142.         return $this->categoryRepository->search($criteria$context)->getEntities();
  143.     }
  144.     protected function usesDooFinderCategoriesExtension(ProductExportEntity $productExport): bool
  145.     {
  146.         return strpos($productExport->getBodyTemplate(), 'doofinderCategories') !== false;
  147.     }
  148.     protected function usesDooFinderGroupIdExtension(ProductExportEntity $productExport): bool
  149.     {
  150.         return strpos($productExport->getBodyTemplate(), 'doofinderGroupId') !== false;
  151.     }
  152.     protected function getProductNumberIdMapping(): array
  153.     {
  154.         return $this->connection->fetchAllKeyValue("SELECT lower(hex(id)), product_number from product");
  155.     }
  156.     protected function raiseMemoryLimit()
  157.     {
  158.         ini_set('memory_limit''5G');
  159.     }
  160. }