custom/static-plugins/marketing-tools/src/Subscriber/HeaderPageletLoadedSubscriber.php line 111

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Wexo\MarketingTools\Subscriber;
  3. use Shopware\Core\Content\Category\CategoryDefinition;
  4. use Shopware\Core\Content\ProductStream\Service\ProductStreamBuilderInterface;
  5. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  6. use Shopware\Core\Framework\DataAbstractionLayer\Search\Aggregation\Aggregation;
  7. use Shopware\Core\Framework\DataAbstractionLayer\Search\Aggregation\Bucket\FilterAggregation;
  8. use Shopware\Core\Framework\DataAbstractionLayer\Search\Aggregation\Bucket\TermsAggregation;
  9. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  10. use Shopware\Core\Framework\DataAbstractionLayer\Search\EntitySearchResult;
  11. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsAnyFilter;
  12. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  13. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\OrFilter;
  14. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  15. use Shopware\Storefront\Pagelet\Header\HeaderPageletLoadedEvent;
  16. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  17. use Symfony\Component\HttpFoundation\Request;
  18. use Wexo\MarketingTools\Core\Content\MarketingTools\Banner\MarketingBannerCollection;
  19. use Wexo\MarketingTools\Core\Content\MarketingTools\MarketingToolsEntityInterface;
  20. use Wexo\MarketingTools\Core\Content\MarketingTools\Modal\MarketingModalEntity;
  21. use Wexo\MarketingTools\Helper\MarketingToolsHelper;
  22. use Wexo\MarketingTools\Struct\MarketingBannerData;
  23. /**
  24.  * Class HeaderPageletLoadedSubscriber
  25.  * @package Wexo\MarketingTools\Subscriber
  26.  */
  27. class HeaderPageletLoadedSubscriber implements EventSubscriberInterface
  28. {
  29.     const MODAL_COOKIE_IDENTIFIER 'marketing-modal-';
  30.     /** @var EntityRepositoryInterface */
  31.     protected $marketingBannerRepository;
  32.     /** @var EntityRepositoryInterface */
  33.     protected $marketingModalRepository;
  34.     /** @var EntityRepositoryInterface */
  35.     protected $productRepository;
  36.     /** @var MarketingToolsHelper */
  37.     protected $helper;
  38.     /** @var ProductStreamBuilderInterface */
  39.     protected $productStreamBuilder;
  40.     /**
  41.      * HeaderPageletLoadedSubscriber constructor.
  42.      * @param EntityRepositoryInterface $marketingBannerRepository
  43.      * @param EntityRepositoryInterface $marketingModalRepository
  44.      * @param EntityRepositoryInterface $productRepository
  45.      * @param MarketingToolsHelper $marketingToolsHelper
  46.      * @param ProductStreamBuilderInterface $productStreamBuilder
  47.      */
  48.     public function __construct(
  49.         EntityRepositoryInterface $marketingBannerRepository,
  50.         EntityRepositoryInterface $marketingModalRepository,
  51.         EntityRepositoryInterface $productRepository,
  52.         MarketingToolsHelper $marketingToolsHelper,
  53.         ProductStreamBuilderInterface $productStreamBuilder
  54.     ) {
  55.         $this->marketingBannerRepository $marketingBannerRepository;
  56.         $this->marketingModalRepository $marketingModalRepository;
  57.         $this->productRepository $productRepository;
  58.         $this->helper $marketingToolsHelper;
  59.         $this->productStreamBuilder $productStreamBuilder;
  60.     }
  61.     /**
  62.      * @return string[]
  63.      */
  64.     public static function getSubscribedEvents()
  65.     {
  66.         return [
  67.             HeaderPageletLoadedEvent::class => 'onHeaderPagelet'
  68.         ];
  69.     }
  70.     /**
  71.      * @param HeaderPageletLoadedEvent $event
  72.      */
  73.     public function onHeaderPagelet(HeaderPageletLoadedEvent $event)
  74.     {
  75.         $request $event->getRequest();
  76.         if (!$request->get('productId'null)
  77.             && (!$request->get('navigationId') && $request->get('_route') !== 'frontend.home.page')
  78.         ) {
  79.             return;
  80.         }
  81.         $criteria $this->helper->getValidationCriteria($event->getSalesChannelContext());
  82.         $criteria->addAssociation('products.product');
  83.         $criteria->addAssociation('categories');
  84.         $banners $this->getBanners($event$criteria);
  85.         $modals $this->getModals($event$criteria);
  86.         $event->getPagelet()->addExtension(
  87.             'marketing_banners',
  88.             $this->getBannerData(
  89.                 $this->modifyResult($banners$event)
  90.             )
  91.         );
  92.         $event->getPagelet()->addExtension(
  93.             'marketing_modal',
  94.             $this->getModalData(
  95.                 $this->modifyResult($modals$event),
  96.                 $request
  97.             )
  98.         );
  99.     }
  100.     /**
  101.      * @param EntitySearchResult $result
  102.      * @param Request $request
  103.      * @return MarketingModalEntity|null
  104.      */
  105.     protected function getModalData(EntitySearchResult $resultRequest $request): ?MarketingModalEntity
  106.     {
  107.         // Find all cookies set by modals
  108.         $tokens array_filter($request->cookies->all(), function ($key) {
  109.             return strpos($keyself::MODAL_COOKIE_IDENTIFIER) !== false;
  110.         }, ARRAY_FILTER_USE_KEY);
  111.         // Filter the result to only return modals whose token is not set in the cookies
  112.         $result $result->filter(function ($item) use ($tokens) {
  113.             return !in_array($item->getToken(), $tokens);
  114.         });
  115.         // Return the first found or null if none are found
  116.         return $result->first();
  117.     }
  118.     /**
  119.      * @param EntitySearchResult $result
  120.      * @return MarketingBannerData
  121.      */
  122.     protected function getBannerData(EntitySearchResult $result): MarketingBannerData
  123.     {
  124.         $data = new MarketingBannerData();
  125.         if ($fullAggregation $result->getAggregations()->get('full')) {
  126.             /** @var MarketingBannerCollection $fullCollection */
  127.             $fullCollection $result->getEntities()->getList($fullAggregation->getKeys());
  128.             $data->setFull($fullCollection);
  129.         }
  130.         if ($halfAggregation $result->getAggregations()->get('half')) {
  131.             /** @var MarketingBannerCollection $halfCollection */
  132.             $halfCollection $result->getEntities()->getList($halfAggregation->getKeys());
  133.             // This allows half banners to be combined
  134.             /*if ($halfCollection->count() && $halfCollection->count() % 2 !== 0) {
  135.                 $last = $halfCollection->getKeys()[$halfCollection->count()-1];
  136.                 $data->getFull()->add($halfCollection->get($last));
  137.                 $halfCollection->remove($last);
  138.             }*/
  139.             $data->setHalf($halfCollection);
  140.         }
  141.         return $data;
  142.     }
  143.     /**
  144.      * @param HeaderPageletLoadedEvent $event
  145.      * @param Criteria $criteria
  146.      * @return EntitySearchResult
  147.      */
  148.     protected function getBanners(HeaderPageletLoadedEvent $eventCriteria $criteria): EntitySearchResult
  149.     {
  150.         $bannerCriteria = clone($criteria);
  151.         $bannerCriteria->addAggregation($this->getBannerWidthAggregation('half'));
  152.         $bannerCriteria->addAggregation($this->getBannerWidthAggregation('full'));
  153.         return $this->marketingBannerRepository->search($bannerCriteria$event->getContext());
  154.     }
  155.     /**
  156.      * @param HeaderPageletLoadedEvent $event
  157.      * @param Criteria $criteria
  158.      * @return EntitySearchResult
  159.      */
  160.     protected function getModals(HeaderPageletLoadedEvent $eventCriteria $criteria): EntitySearchResult
  161.     {
  162.         return $this->marketingModalRepository->search($criteria$event->getContext());
  163.     }
  164.     /**
  165.      * @param string $bannerWidth
  166.      * @return Aggregation
  167.      */
  168.     private function getBannerWidthAggregation(string $bannerWidth): Aggregation
  169.     {
  170.         return new FilterAggregation(
  171.             "$bannerWidth-filter",
  172.             new TermsAggregation($bannerWidth'id'),
  173.             [
  174.                 new EqualsFilter('bannerWidth'$bannerWidth)
  175.             ]
  176.         );
  177.     }
  178.     /**
  179.      * @param EntitySearchResult $result
  180.      * @param HeaderPageletLoadedEvent $event
  181.      * @return EntitySearchResult
  182.      */
  183.     private function modifyResult(EntitySearchResult $resultHeaderPageletLoadedEvent $event): EntitySearchResult
  184.     {
  185.         $navigation $event->getPagelet()->getNavigation();
  186.         $activeCategoryId $navigation->getActive() ? $navigation->getActive()->getId() : null;
  187.         $productId $event->getRequest()->get('productId'null);
  188.         /** @var MarketingToolsEntityInterface $entity */
  189.         foreach ($result->getEntities() as $entity) {
  190.             $condition false;
  191.             // If we are on a product page only check product condition
  192.             // This is because the product page does not count as a category page
  193.             // And if the current page is not a navigation page shopware will default navigationId to the home category
  194.             if ($productId) {
  195.                 if ($assignedProductIds $this->getAssignedProducts($entity$event->getSalesChannelContext())) {
  196.                     $condition in_array($productId$assignedProductIds);
  197.                 }
  198.             } elseif ($activeCategoryId && $assignedCategories $entity->getCategories()) {
  199.                 $condition in_array($activeCategoryId$assignedCategories->getCategoryIds());
  200.             }
  201.             if (!$condition) {
  202.                 $result->remove($entity->getId());
  203.                 $result->getEntities()->remove($entity->getId());
  204.             }
  205.         }
  206.         return $result;
  207.     }
  208.     /**
  209.      * @param MarketingToolsEntityInterface $entity
  210.      * @param SalesChannelContext $context
  211.      * @return array
  212.      */
  213.     private function getAssignedProducts(MarketingToolsEntityInterface $entitySalesChannelContext $context): array
  214.     {
  215.         if ($entity->getProductAssignmentType() === CategoryDefinition::PRODUCT_ASSIGNMENT_TYPE_PRODUCT_STREAM &&
  216.             $entity->getProductStreamId() !== null
  217.         ) {
  218.             $filters $this->productStreamBuilder->buildFilters(
  219.                 $entity->getProductStreamId(),
  220.                 $context->getContext()
  221.             );
  222.             $criteria = new Criteria();
  223.             $criteria->addFilter(...$filters);
  224.             $products $this->productRepository->searchIds($criteria$context->getContext())->getIds();
  225.         } else {
  226.             $products $entity->getProducts()->getProductIds();
  227.         }
  228.         return $products;
  229.     }
  230. }