custom/plugins/BALThreeDimensionModelView/src/Subscriber/ProductPageSubscriber.php line 49

Open in your IDE?
  1. <?php
  2. namespace BAL\Plugin\ThreeDimensionModelView\Subscriber;
  3. use BAL\Plugin\ThreeDimensionModelView\Entity\Category\CategoryExtension;
  4. use BAL\Plugin\ThreeDimensionModelView\Entity\CategoryExtension\CategoryExtensionEntity;
  5. use BAL\Plugin\ThreeDimensionModelView\Entity\Product\ProductExtension;
  6. use BAL\Plugin\ThreeDimensionModelView\Entity\ProductModel\ProductModelCollection;
  7. use BAL\Plugin\ThreeDimensionModelView\Entity\ProductModel\ProductModelEntity;
  8. use Shopware\Core\Content\Category\CategoryEntity;
  9. use Shopware\Core\Content\Media\MediaDefinition;
  10. use Shopware\Core\Content\Product\SalesChannel\SalesChannelProductEntity;
  11. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  12. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityLoadedEvent;
  13. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  14. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  15. use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting;
  16. use Shopware\Storefront\Page\Product\ProductPageCriteriaEvent;
  17. use Shopware\Storefront\Page\Product\ProductPageLoadedEvent;
  18. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  19. use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
  20. class ProductPageSubscriber implements EventSubscriberInterface
  21. {
  22.     private const MODE_BREADCRUMB 'breadcrumb';
  23.     private const MODE_TREE 'tree';
  24.     private EventDispatcherInterface $eventDispatcher;
  25.     private MediaDefinition $mediaDefinition;
  26.     private EntityRepositoryInterface $categoryRepository;
  27.     public function __construct(
  28.         EventDispatcherInterface $eventDispatcher,
  29.         MediaDefinition $mediaDefinition,
  30.         EntityRepositoryInterface $categoryRepository
  31.     ) {
  32.         $this->eventDispatcher    $eventDispatcher;
  33.         $this->mediaDefinition    $mediaDefinition;
  34.         $this->categoryRepository $categoryRepository;
  35.     }
  36.     public static function getSubscribedEvents() : array
  37.     {
  38.         return [
  39.             ProductPageCriteriaEvent::class => 'onProductPageCriteriaEvent',
  40.             ProductPageLoadedEvent::class   => 'onProductPageLoadedEvent',
  41.         ];
  42.     }
  43.     public function onProductPageCriteriaEvent(ProductPageCriteriaEvent $event) : void
  44.     {
  45.         $productModelCriteria $event->getCriteria()->getAssociation(ProductExtension::FIELD_NAME);
  46.         $productModelCriteria->addAssociation('threeDimensionModel');
  47.         $productModelCriteria->addFilter(
  48.             new EqualsFilter('active'true),
  49.             new EqualsFilter('threeDimensionModel.active'true),
  50.         );
  51.         $productModelCriteria->addSorting(new FieldSorting('position'FieldSorting::ASCENDING));
  52.     }
  53.     public function onProductPageLoadedEvent(ProductPageLoadedEvent $event) : void
  54.     {
  55.         /**
  56.          * @var SalesChannelProductEntity $productEntity
  57.          * @var CategoryEntity|null $seoCategoryEntity
  58.          * @var ProductModelCollection|null $productModelCollection
  59.          */
  60.         $backgroundColor        null;
  61.         $categoryViewerConfigs  = [];
  62.         $productEntity          $event->getPage()->getProduct();
  63.         $seoCategoryEntity      $productEntity->getSeoCategory();
  64.         $productModelCollection $productEntity->getExtension(ProductExtension::FIELD_NAME);
  65.         if ($productModelCollection !== null) {
  66.             if ($seoCategoryEntity === null) {
  67.                 $this->collectCategoryViewerConfigs(
  68.                     $categoryViewerConfigs,
  69.                     $backgroundColor,
  70.                     self::MODE_TREE,
  71.                     $productEntity->getCategoryTree(),
  72.                     $event
  73.                 );
  74.             } else {
  75.                 $this->collectCategoryViewerConfigs(
  76.                     $categoryViewerConfigs,
  77.                     $backgroundColor,
  78.                     self::MODE_BREADCRUMB,
  79.                     array_keys($seoCategoryEntity->getPlainBreadcrumb()),
  80.                     $event,
  81.                     $productEntity->getCategoryIds()
  82.                 );
  83.             }
  84.             $categoryConfig $this->mergeViewerConfigs(...$categoryViewerConfigs);
  85.             $this->dispatchMediaLoadedEvent($productModelCollection$event);
  86.             /** @var ProductModelEntity $productModelEntity */
  87.             foreach ($productModelCollection->getElements() as $productModelEntity) {
  88.                 $threeDimensionModel $productModelEntity->getThreeDimensionModel();
  89.                 if ($threeDimensionModel === null || !$threeDimensionModel->isActive()) {
  90.                     // shouldn't actually happen, because model is required and criteria with active filter
  91.                     continue;
  92.                 }
  93.                 $productModelViewerConfig $productModelEntity->getViewerConfig();
  94.                 $modelViewerConfig        $threeDimensionModel->getViewerConfig();
  95.                 $productModelEntity->setViewerConfig($this->mergeViewerConfigs($modelViewerConfig$categoryConfig$productModelViewerConfig));
  96.                 $productModelEntity->setBackgroundColor(
  97.                     $this->mergeColor(
  98.                         $productModelEntity->getBackgroundColor(),
  99.                         $backgroundColor,
  100.                         $threeDimensionModel->getBackgroundColor()
  101.                     )
  102.                 );
  103.             }
  104.         }
  105.     }
  106.     protected function collectCategoryViewerConfigs(
  107.         array &$categoryViewerConfigs,
  108.         ?string &$backgroundColor,
  109.         string $mode,
  110.         ?array $categoryIds,
  111.         ProductPageLoadedEvent $event,
  112.         ?array $leadCategoryIds null
  113.     ) {
  114.         if (empty($categoryIds)) {
  115.             return;
  116.         }
  117.         $searchResult $this->categoryRepository->search(new Criteria($categoryIds), $event->getContext());
  118.         if ($searchResult->getTotal() === 0) {
  119.             return;
  120.         }
  121.         if ($mode === self::MODE_BREADCRUMB) {
  122.             foreach ($categoryIds as $categoryId) {
  123.                 $this->collectCategoryViewerConfig(
  124.                     $categoryViewerConfigs,
  125.                     $backgroundColor,
  126.                     $searchResult->get($categoryId)
  127.                 );
  128.             }
  129.         } elseif ($mode === self::MODE_TREE) {
  130.             // other algorithmus, tree based? leaf's in $leadCategoryIds
  131.             foreach ($categoryIds as $categoryId) {
  132.                 $this->collectCategoryViewerConfig(
  133.                     $categoryViewerConfigs,
  134.                     $backgroundColor,
  135.                     $searchResult->get($categoryId)
  136.                 );
  137.             }
  138.         }
  139.     }
  140.     protected function collectCategoryViewerConfig(
  141.         array &$categoryViewerConfigs,
  142.         ?string &$backgroundColor,
  143.         ?CategoryEntity $categoryEntity
  144.     ) {
  145.         if ($categoryEntity !== null) {
  146.             /** @var CategoryExtensionEntity|null $configEntity */
  147.             $configEntity $categoryEntity->getExtension(CategoryExtension::FIELD_NAME);
  148.             if ($configEntity !== null) {
  149.                 $backgroundColor         $this->mergeColor($configEntity->getBackgroundColor(), $backgroundColor);
  150.                 $categoryViewerConfigs[] = $configEntity->getViewerConfig();
  151.             }
  152.         }
  153.     }
  154.     protected function dispatchMediaLoadedEvent(ProductModelCollection $productModelCollectionProductPageLoadedEvent $event)
  155.     {
  156.         $medias = [];
  157.         foreach ($productModelCollection->getElements() as $productModelEntity) {
  158.             /** @var ProductModelEntity $productModelEntity */
  159.             if ($productModelEntity->getThreeDimensionModel() !== null) {
  160.                 foreach (
  161.                     [
  162.                         $productModelEntity->getThreeDimensionModel()->getModel(),
  163.                         $productModelEntity->getThreeDimensionModel()->getBackgroundImage(),
  164.                         $productModelEntity->getThreeDimensionModel()->getPreviewImage(),
  165.                     ] as $media
  166.                 ) {
  167.                     if ($media !== null) {
  168.                         $medias[$media->getId()] = $media;
  169.                     }
  170.                 }
  171.             }
  172.         }
  173.         $mediaLoadedEvent = new EntityLoadedEvent($this->mediaDefinition$medias$event->getContext());
  174.         $this->eventDispatcher->dispatch(
  175.             $mediaLoadedEvent,
  176.             $mediaLoadedEvent->getName()
  177.         );
  178.     }
  179.     protected function mergeViewerConfigs(array...$configs) : array
  180.     {
  181.         $configs array_filter($configs'is_array');
  182.         return array_merge(...$configs);
  183.     }
  184.     protected function mergeColor(?string...$colors) : ?string
  185.     {
  186.         foreach ($colors as $color) {
  187.             if ( !empty($color)) {
  188.                 return $color;
  189.             }
  190.         }
  191.         return null;
  192.     }
  193. }