custom/plugins/CbaxModulCrossSelling/src/Subscriber/FrontendSubscriber.php line 253

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Cbax\ModulCrossSelling\Subscriber;
  3. use Doctrine\DBAL\Connection;
  4. use Shopware\Core\Framework\Uuid\Uuid;
  5. use Shopware\Core\Defaults;
  6. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  7. use Shopware\Storefront\Page\Product\ProductPageLoadedEvent;
  8. use Shopware\Storefront\Page\Checkout\Cart\CheckoutCartPageLoadedEvent;
  9. use Shopware\Storefront\Page\Checkout\Finish\CheckoutFinishPageLoadedEvent;
  10. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  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\Sorting\FieldSorting;
  14. use Shopware\Core\System\SystemConfig\SystemConfigService;
  15. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  16. use Shopware\Core\System\SalesChannel\Entity\SalesChannelRepositoryInterface;
  17. use Symfony\Contracts\Translation\TranslatorInterface;
  18. use Shopware\Core\Content\Product\Aggregate\ProductCrossSelling\ProductCrossSellingEntity;
  19. use Shopware\Core\Content\Product\SalesChannel\CrossSelling\CrossSellingElementCollection;
  20. use Shopware\Core\Content\Product\SalesChannel\CrossSelling\CrossSellingElement;
  21. use Shopware\Core\Content\Product\SalesChannel\CrossSelling\AbstractProductCrossSellingRoute;
  22. use Shopware\Core\Content\Product\ProductCollection;
  23. //use Shopware\Core\Checkout\Order\Aggregate\OrderLineItem\OrderLineItemCollection;
  24. use Shopware\Storefront\Page\Navigation\NavigationPageLoadedEvent;
  25. use Shopware\Storefront\Page\Search\SearchPageLoadedEvent;
  26. use Shopware\Storefront\Page\LandingPage\LandingPageLoadedEvent;
  27. use Cbax\ModulCrossSelling\CbaxModulCrossSelling;
  28. class FrontendSubscriber implements EventSubscriberInterface
  29. {
  30.     /**
  31.      * @var TranslatorInterface
  32.      */
  33.     private $translator;
  34.     /**
  35.      * @var SystemConfigService
  36.      */
  37.     private $systemConfigService;
  38.     /** SalesChannelProductRepository */
  39.     /**
  40.      * @var SalesChannelRepositoryInterface
  41.      */
  42.     private $salesChannelProductRepository;
  43.     /**
  44.      * @var EntityRepositoryInterface
  45.      */
  46.     private $productRepository;
  47.     /**
  48.      * @var EntityRepositoryInterface
  49.      */
  50.     private $cbaxCrossSellingRepository;
  51.     /**
  52.      * @var EntityRepositoryInterface
  53.      */
  54.     private $alsoViewedRepository;
  55.     /**
  56.      * @var EntityRepositoryInterface
  57.      */
  58.     private $alsoBoughtRepository;
  59.     /**
  60.      * @var AbstractProductCrossSellingRoute
  61.      */
  62.     private $crossSellingLoader;
  63.     /**
  64.      * @var CrossSellingElementCollection
  65.      */
  66.     private $filteredAccessories;
  67.     /**
  68.      * @var CrossSellingElementCollection
  69.      */
  70.     private $filteredSimilarArticle;
  71.     /**
  72.      * @var Connection
  73.      */
  74.     private $connection;
  75.     /**
  76.      * @var string
  77.      */
  78.     private $shopwareVersion;
  79.     public function __construct(
  80.         SystemConfigService $systemConfigService,
  81.         EntityRepositoryInterface $productRepository,
  82.         SalesChannelRepositoryInterface $salesChannelProductRepository,
  83.         EntityRepositoryInterface $cbaxCrossSellingRepository,
  84.         EntityRepositoryInterface $alsoViewedRepository,
  85.         EntityRepositoryInterface $alsoBoughtRepository,
  86.         AbstractProductCrossSellingRoute $crossSellingLoader,
  87.         Connection $connection,
  88.         TranslatorInterface $translator,
  89.         $shopwareVersion
  90.     )
  91.     {
  92.         $this->systemConfigService $systemConfigService;
  93.         $this->productRepository $productRepository;
  94.         $this->salesChannelProductRepository $salesChannelProductRepository;
  95.         $this->cbaxCrossSellingRepository $cbaxCrossSellingRepository;
  96.         $this->crossSellingLoader $crossSellingLoader;
  97.         $this->shopwareVersion $shopwareVersion;
  98.         $this->alsoViewedRepository $alsoViewedRepository;
  99.         $this->alsoBoughtRepository $alsoBoughtRepository;
  100.         $this->connection $connection;
  101.         $this->translator $translator;
  102.     }
  103.     public static function getSubscribedEvents(): array
  104.     {
  105.         return[
  106.             ProductPageLoadedEvent::class => 'onProductPageLoadedEvent',
  107.             CheckoutCartPageLoadedEvent::class => 'onCheckoutCartPageLoadedEvent',
  108.             CheckoutFinishPageLoadedEvent::class => ['onOrderFinished', -1],
  109.             NavigationPageLoadedEvent::class => 'onNavigationPageLoaded',
  110.             SearchPageLoadedEvent::class => 'onSearchPageLoaded',
  111.             LandingPageLoadedEvent::class => 'onLandingPageLoaded'
  112.         ];
  113.     }
  114.     public function onLandingPageLoaded(LandingPageLoadedEvent $event)
  115.     {
  116.         $context $event->getSalesChannelContext();
  117.         $salesChannelId $context->getSalesChannelId();
  118.         $config $this->systemConfigService->get(CbaxModulCrossSelling::MODUL_NAME$salesChannelId)['config'];
  119.         if (!empty($config['showLastSeen']) && !empty($config['lastSeenPageTypes']) && in_array('landing'$config['lastSeenPageTypes'])) {
  120.             $lastSeenProducts $this->getlastSeenProducts($event$context);
  121.             if (count($lastSeenProducts) > 0) {
  122.                 $page $event->getPage();
  123.                 $page->assign(['lastSeenArticle' => $lastSeenProducts]);
  124.             }
  125.         }
  126.     }
  127.     public function onSearchPageLoaded(SearchPageLoadedEvent $event)
  128.     {
  129.         $context $event->getSalesChannelContext();
  130.         $salesChannelId $context->getSalesChannelId();
  131.         $config $this->systemConfigService->get(CbaxModulCrossSelling::MODUL_NAME$salesChannelId)['config'];
  132.         if (!empty($config['showLastSeen']) && !empty($config['lastSeenPageTypes']) && in_array('search'$config['lastSeenPageTypes'])) {
  133.             $lastSeenProducts $this->getlastSeenProducts($event$context);
  134.             if (count($lastSeenProducts) > 0) {
  135.                 $page $event->getPage();
  136.                 $page->assign(['lastSeenArticle' => $lastSeenProducts]);
  137.             }
  138.         }
  139.     }
  140.     private function getlastSeenProducts($event$context)
  141.     {
  142.         $session $event->getRequest()->getSession();
  143.         $lastSeen = [];
  144.         if ($session->has('cbaxLastSeen')) {
  145.             $lastSeen $session->get('cbaxLastSeen');
  146.             $lastSeen is_array($lastSeen) ? $lastSeen : [];
  147.         }
  148.         if (count($lastSeen) > 0) {
  149.             $lastSeenCriteria = new Criteria();
  150.             $lastSeenCriteria->addFilter(new EqualsAnyFilter('id'$lastSeen));
  151.             return $this->salesChannelProductRepository->search($lastSeenCriteria$context)->getElements();
  152.         } else {
  153.             return [];
  154.         }
  155.     }
  156.     public function onNavigationPageLoaded(NavigationPageLoadedEvent $event)
  157.     {
  158.         $context $event->getSalesChannelContext();
  159.         $salesChannelId $context->getSalesChannelId();
  160.         $config $this->systemConfigService->get(CbaxModulCrossSelling::MODUL_NAME$salesChannelId)['config'];
  161.         $page $event->getPage();
  162.         if (!empty($config['showLastSeen']) && !empty($config['lastSeenPageTypes']) && in_array('navigation'$config['lastSeenPageTypes'])) {
  163.             $lastSeenProducts $this->getlastSeenProducts($event$context);
  164.             if (count($lastSeenProducts) > 0) {
  165.                 $page->assign(['lastSeenArticle' => $lastSeenProducts]);
  166.             }
  167.         }
  168.     }
  169.     public function onOrderFinished(CheckoutFinishPageLoadedEvent $event)
  170.     {
  171.         $context $event->getSalesChannelContext();
  172.         $salesChannelId $context->getSalesChannelId();
  173.         $config $this->systemConfigService->get(CbaxModulCrossSelling::MODUL_NAME$salesChannelId)['config'];
  174.         if (empty($config['showAlsoBought'])) return;
  175.         $order $event->getPage()->getOrder();
  176.         if (!empty($order) and !empty($order->getLineItems()) and $order->getLineItems()->count() > 1)
  177.         {
  178.             $lineItems $order->getLineItems();
  179.             $combinations = [];
  180.             $insertValues '';
  181.             $createdAt = (new \DateTimeImmutable())->format(Defaults::STORAGE_DATE_TIME_FORMAT);
  182.             foreach ($lineItems as $key1 => $item1)
  183.             {
  184.                 foreach ($lineItems as $key2 => $item2)
  185.                 {
  186.                     if ($key1 === $key2) continue;
  187.                     if ($item1->getType() !== 'product' || $item2->getType() !== 'product') continue;
  188.                     $combinations[] = [$item1->getProductId(), $item2->getProductId()];
  189.                 }
  190.             }
  191.             foreach ($combinations as $idPair)
  192.             {
  193.                 $insertValues .= '(UNHEX("' Uuid::randomHex() . '"),UNHEX("' $idPair[0] . '"),UNHEX("' $idPair[1] . '"),1,:created_at),';
  194.             }
  195.             $insertValues rtrim($insertValues', ');
  196.             if (!empty($insertValues))
  197.             {
  198.                 try {
  199.                     $this->connection->executeUpdate('
  200.                         INSERT INTO `cbax_cross_selling_also_bought`
  201.                             (`id`, `product_id`, `related_product_id`, `sales`, `created_at`)
  202.                         VALUES ' $insertValues ' ON DUPLICATE KEY UPDATE sales=sales+1;',
  203.                         [
  204.                             'created_at' => $createdAt
  205.                         ]
  206.                     );
  207.                 } catch (\Exception $e) {
  208.                 }
  209.             }
  210.         }
  211.     }
  212.     public function onProductPageLoadedEvent(ProductPageLoadedEvent $productPageLoadedEvent)
  213.     {
  214.         $context $productPageLoadedEvent->getSalesChannelContext();
  215.         $salesChannelId $context->getSalesChannelId();
  216.         $config $this->systemConfigService->get(CbaxModulCrossSelling::MODUL_NAME$salesChannelId)['config'];
  217.         $page $productPageLoadedEvent->getPage();
  218.         if (!empty($config['showLastSeen']) || !empty($config['showAlsoViewed']))
  219.         {
  220.             $productId $productPageLoadedEvent->getPage()->getProduct()->getId();
  221.             $session $productPageLoadedEvent->getRequest()->getSession();
  222.             $lastSeenLimit = !empty($config['lastSeenLimit']) ? $config['lastSeenLimit'] : 5;
  223.             if ($session->has('cbaxLastSeen'))
  224.             {
  225.                 $lastSeen $session->get('cbaxLastSeen');
  226.                 if (is_array($lastSeen))
  227.                 {
  228.                     $lastSeen array_filter($lastSeen, function($e) use ($productId) {
  229.                         return ($e !== $productId);
  230.                     });
  231.                     $lastSeen[] = $productId;
  232.                 } else {
  233.                     $lastSeen = [$productId];
  234.                 }
  235.             } else {
  236.                 $lastSeen = [$productId];
  237.             }
  238.             if (count($lastSeen) > $lastSeenLimit 1)
  239.             {
  240.                 array_shift($lastSeen);
  241.             }
  242.             $session->set('cbaxLastSeen'$lastSeen);
  243.             array_pop($lastSeen);
  244.             if (!empty($config['showLastSeen']) && !empty($config['lastSeenPageTypes']) && in_array('product'$config['lastSeenPageTypes']) && count($lastSeen) > 0)
  245.             {
  246.                 $lastSeenCriteria = new Criteria();
  247.                 $lastSeenCriteria->addFilter(new EqualsAnyFilter('id'$lastSeen));
  248.                 $lastSeenProducts $this->salesChannelProductRepository->search($lastSeenCriteria$context)->getElements();
  249.                 if (count($lastSeenProducts) > 0)
  250.                 {
  251.                     $page->assign(['lastSeenArticle' => $lastSeenProducts]);
  252.                 }
  253.             }
  254.             if (!empty($config['showAlsoViewed']))
  255.             {
  256.                 $alsoViewedLimit = !empty($config['alsoViewedLimit']) ? $config['alsoViewedLimit'] : 5;
  257.                 $alsoViewedCriteria1 = new Criteria();
  258.                 $alsoViewedCriteria1->addFilter(new EqualsFilter('productId'$productId));
  259.                 $alsoViewedCriteria1->addSorting(new FieldSorting('viewed'FieldSorting::DESCENDING));
  260.                 $alsoViewedCriteria1->setLimit($alsoViewedLimit);
  261.                 $alsoViewedResult $this->alsoViewedRepository->search($alsoViewedCriteria1$context->getContext())->getElements();
  262.                 if (count($alsoViewedResult) > 0)
  263.                 {
  264.                     $alsoViewedIds array_map(static function($item) {
  265.                         return $item->getRelatedProductId();
  266.                     }, $alsoViewedResult);
  267.                     $alsoViewedCriteria2 = new Criteria($alsoViewedIds);
  268.                     $alsoViewedCriteria2->addFilter(new EqualsFilter('active'true));
  269.                     $alsoViewedProducts $this->salesChannelProductRepository->search($alsoViewedCriteria2$context);
  270.                     if ($alsoViewedProducts->getTotal() > 0)
  271.                     {
  272.                         if ($config['alsoProductsLocation'] == 'crossSelling')
  273.                         {
  274.                             $locale $this->translator->getLocale() ?? 'en-GB';
  275.                             $alsoViewedTitle $this->translator->trans('cbaxCrossSelling.alsoViewed.title', [], null$locale);
  276.                             $alsoViewedPCSEntity = new ProductCrossSellingEntity();
  277.                             $alsoViewedPCSEntity->setActive(true);
  278.                             $alsoViewedPCSEntity->setId(Uuid::randomHex());
  279.                             $alsoViewedPCSEntity->setTranslated(['name' => $alsoViewedTitle]);
  280.                             $alsoViewedPCSEntity->setName($alsoViewedTitle);
  281.                             $alsoViewedCSElement = new CrossSellingElement();
  282.                             $alsoViewedCSElement->setCrossSelling($alsoViewedPCSEntity);
  283.                             $alsoViewedCSElement->setProducts($alsoViewedProducts->getEntities());
  284.                             $alsoViewedCSElement->setTotal($alsoViewedProducts->getTotal());
  285.                         } else {
  286.                             $page->assign(['alsoViewedArticle' => $alsoViewedProducts->getElements()]);
  287.                         }
  288.                     }
  289.                 }
  290.                 if (count($lastSeen) > 0)
  291.                 {
  292.                     $insertValues '';
  293.                     $createdAt = (new \DateTimeImmutable())->format(Defaults::STORAGE_DATE_TIME_FORMAT);
  294.                     $productIdBytes Uuid::fromHexToBytes($productId);
  295.                     foreach ($lastSeen as $seenId)
  296.                     {
  297.                         $insertValues .= '(UNHEX("' Uuid::randomHex() . '"),:product_id,UNHEX("' $seenId '"),1,:created_at),';
  298.                         $insertValues .= '(UNHEX("' Uuid::randomHex() . '"),UNHEX("' $seenId '"),:product_id,1,:created_at),';
  299.                     }
  300.                     $insertValues rtrim($insertValues', ');
  301.                     try {
  302.                         $this->connection->executeUpdate('
  303.                         INSERT INTO `cbax_cross_selling_also_viewed`
  304.                             (`id`, `product_id`, `related_product_id`, `viewed`, `created_at`)
  305.                         VALUES ' $insertValues ' ON DUPLICATE KEY UPDATE viewed=viewed+1;',
  306.                             [
  307.                                 'created_at' => $createdAt,
  308.                                 'product_id' => $productIdBytes
  309.                             ]
  310.                         );
  311.                     } catch (\Exception $e) {
  312.                     }
  313.                 }
  314.             }
  315.         }
  316.         if (!empty($config['showAlsoBought']) && !empty($productId)) {
  317.             $alsoBoughtLimit = !empty($config['alsoBoughtLimit']) ? $config['alsoBoughtLimit'] : 5;
  318.             $alsoBoughtCriteria1 = new Criteria();
  319.             $alsoBoughtCriteria1->addFilter(new EqualsFilter('productId'$productId));
  320.             $alsoBoughtCriteria1->addSorting(new FieldSorting('sales'FieldSorting::DESCENDING));
  321.             $alsoBoughtCriteria1->setLimit($alsoBoughtLimit);
  322.             $alsoBoughtResult $this->alsoBoughtRepository->search($alsoBoughtCriteria1$context->getContext())->getElements();
  323.             if (count($alsoBoughtResult) > 0) {
  324.                 $alsoBoughtIds array_map(static function ($item) {
  325.                     return $item->getRelatedProductId();
  326.                 }, $alsoBoughtResult);
  327.                 $alsoBoughtCriteria2 = new Criteria($alsoBoughtIds);
  328.                 $alsoBoughtCriteria2->addFilter(new EqualsFilter('active'true));
  329.                 $alsoBoughtProducts $this->salesChannelProductRepository->search($alsoBoughtCriteria2$context);
  330.                 if ($alsoBoughtProducts->getTotal() > 0)
  331.                 {
  332.                     if ($config['alsoProductsLocation'] == 'crossSelling')
  333.                     {
  334.                         if (empty($locale))
  335.                         {
  336.                             $locale $this->translator->getLocale() ?? 'en-GB';
  337.                         }
  338.                         $alsoBoughtTitle $this->translator->trans('cbaxCrossSelling.alsoBought.title', [], null$locale);
  339.                         $alsoBoughtPCSEntity = new ProductCrossSellingEntity();
  340.                         $alsoBoughtPCSEntity->setActive(true);
  341.                         $alsoBoughtPCSEntity->setId(Uuid::randomHex());
  342.                         $alsoBoughtPCSEntity->setTranslated(['name' => $alsoBoughtTitle]);
  343.                         $alsoBoughtPCSEntity->setName($alsoBoughtTitle);
  344.                         $alsoBoughtCSElement = new CrossSellingElement();
  345.                         $alsoBoughtCSElement->setCrossSelling($alsoBoughtPCSEntity);
  346.                         $alsoBoughtCSElement->setProducts($alsoBoughtProducts->getEntities());
  347.                         $alsoBoughtCSElement->setTotal($alsoBoughtProducts->getTotal());
  348.                     } else {
  349.                         $page->assign(['alsoBoughtProducts' => $alsoBoughtProducts->getElements()]);
  350.                     }
  351.                 }
  352.             }
  353.         }
  354.         if (empty($config['activeSimilarContainer']) && empty($config['activeAccessoriesTab'])) return;
  355.         $cmsPage $page->getCmsPage();
  356.         if (empty($cmsPage))
  357.         {
  358.             $result $page->getCrossSellings();
  359.         } else
  360.         {
  361.             $crossSellingElement $cmsPage->getFirstElementOfType('cross-selling');
  362.             if (!empty($crossSellingElement) && !empty($crossSellingElement->getData()))
  363.             {
  364.                 $result $crossSellingElement->getData()->getCrossSellings();
  365.             }
  366.         }
  367.         // Filtern nur nötig bei echten CS Elementen, wenn nur also.. Pseudo CS Elemnte, nicht nötig
  368.         if (!empty($result) && $result->count() > 0)
  369.         {
  370.             $doFilterung true;
  371.         } else {
  372.             $doFilterung false;
  373.         }
  374.         if (!empty($alsoViewedCSElement)) {
  375.             if (empty($result))
  376.             {
  377.                 $result = new CrossSellingElementCollection();
  378.             }
  379.             $result->add($alsoViewedCSElement);
  380.         }
  381.         if (!empty($alsoBoughtCSElement)) {
  382.             if (empty($result))
  383.             {
  384.                 $result = new CrossSellingElementCollection();
  385.             }
  386.             $result->add($alsoBoughtCSElement);
  387.         }
  388.         if (empty($result)) return;
  389.         if ($result->count() === 0) return;
  390.         $crossSellingIds array_map(static function ($item) {
  391.             return $item->getCrossSelling()->get('id');
  392.         }, $result->getElements());
  393.         if (count($crossSellingIds) > 0)
  394.         {
  395.             // Filtern nur nötig bei echten CS Elementen, wenn nur also... Pseudo CS Elemente, nicht nötig
  396.             if ($doFilterung)
  397.             {
  398.                 $this->filteredAccessories = new CrossSellingElementCollection();
  399.                 $this->filteredSimilarArticle = new CrossSellingElementCollection();
  400.                 $criteria = new Criteria();
  401.                 $criteria->addFilter(new EqualsAnyFilter('crossSellingId'$crossSellingIds));
  402.                 $criteria->addAssociation('crossSelling');
  403.                 $crossSellings $this->cbaxCrossSellingRepository->search($criteria$context->getContext())->getElements();
  404.                 $filtered $result->filter(function ($element) use ($crossSellings$config) {return $this->filterData($element$crossSellings$config);});
  405.                 $result $filtered;
  406.                 $page->assign(['cbaxCrossSelling' => $crossSellings]);
  407.                 $page->assign(['filteredAccessories' => $this->filteredAccessories]);
  408.                 $page->assign(['filteredSimilarArticle' => $this->filteredSimilarArticle]);
  409.             }
  410.             if (empty($cmsPage))
  411.             {
  412.                 $page->setCrossSellings($result);
  413.             } else {
  414.                 $crossSellingElement->getData()->setCrossSellings($result);
  415.             }
  416.             if (version_compare($this->shopwareVersion'6.4.11''>='))
  417.             {
  418.                 $page->assign(['cbaxSW6411' => true]);
  419.             } else {
  420.                 $page->assign(['cbaxSW6411' => false]);
  421.             }
  422.         }
  423.     }
  424.     public function filterData(CrossSellingElement $element, array $crossSellings$config)
  425.     {
  426.         $accessoriesIds = array();
  427.         $similarArticleIds = array();
  428.         foreach ($crossSellings as $item) {
  429.             if ($item->getCrossSellingGroup() === 'accessories') {
  430.                 $accessoriesIds[] = $item->crossSellingId;
  431.             }
  432.             if ($item->getCrossSellingGroup() === 'similar_article') {
  433.                 $similarArticleIds[] = $item->crossSellingId;
  434.             }
  435.         }
  436.         if (in_array($element->getCrossSelling()->get('id'), $accessoriesIds)) {
  437.             $this->filteredAccessories->add($element);
  438.             if (!empty($config['filterAccessories'])) {
  439.                 return false;
  440.             }
  441.         }
  442.         if (in_array($element->getCrossSelling()->get('id'), $similarArticleIds)) {
  443.             $this->filteredSimilarArticle->add($element);
  444.             if (!empty($config['filterSimilarArticle'])) {
  445.                 return false;
  446.             }
  447.         }
  448.         return true;
  449.     }
  450.     public function onCheckoutCartPageLoadedEvent(CheckoutCartPageLoadedEvent $checkoutCartPageLoadedEvent)
  451.     {
  452.         $salesChannelId $checkoutCartPageLoadedEvent->getSalesChannelContext()->getSalesChannelId();
  453.         $config $this->systemConfigService->get(CbaxModulCrossSelling::MODUL_NAME$salesChannelId)['config'];
  454.         if (empty($config['activeAccessoriesInCart'])) return;
  455.         $page $checkoutCartPageLoadedEvent->getPage();
  456.         $lineItems $page->getCart()->getLineItems();
  457.         $filteredLineItems $lineItems->filterType('product');
  458.         if ($filteredLineItems->count() > 0)
  459.         {
  460.             $context $checkoutCartPageLoadedEvent->getSalesChannelContext();
  461.             $emptyCriteria = new Criteria();
  462.             $criteria = new Criteria();
  463.             $criteria->addFilter(new EqualsAnyFilter('id'$filteredLineItems->getKeys()));
  464.             $criteria->addAssociation('crossSellings');
  465.             $products $this->productRepository->search($criteria$context->getContext());
  466.             $crossSellingIds = array();
  467.             foreach($products->getElements() as $product)
  468.             {
  469.                 $crossSellingIds array_merge($crossSellingIds$product->getCrossSellings()->getIds());
  470.             }
  471.             if (count($crossSellingIds) > 0)
  472.             {
  473.                 $request $checkoutCartPageLoadedEvent->getRequest();
  474.                 $this->filteredAccessories = new CrossSellingElementCollection();
  475.                 $this->filteredSimilarArticle = new CrossSellingElementCollection();
  476.                 $criteria = new Criteria();
  477.                 $criteria->addFilter(new EqualsAnyFilter('crossSellingId'$crossSellingIds));
  478.                 $criteria->addAssociation('crossSelling');
  479.                 $cbaxCrossSellings $this->cbaxCrossSellingRepository->search($criteria$context->getContext())->getElements();
  480.                 foreach($filteredLineItems->getKeys() as $id)
  481.                 {
  482.                     $elements $this->crossSellingLoader->load($id$request$context$emptyCriteria)->getResult();
  483.                     foreach($elements->getElements() as $element)
  484.                     {
  485.                         $this->sortData($element$cbaxCrossSellings);
  486.                     }
  487.                 }
  488.                 $this->filterSameAccessories($filteredLineItems->getKeys(), $config);
  489.                 if (!empty($config['accessoriesCartOneSlider']) && $this->filteredAccessories->count() > 1)
  490.                 {
  491.                     $counter 0;
  492.                     $productCollection = new ProductCollection();
  493.                     foreach ($this->filteredAccessories->getElements() as $index => $crossSellingElement)
  494.                     {
  495.                         if ($counter === 0)
  496.                         {
  497.                             $remainingElement $crossSellingElement;
  498.                         }
  499.                         foreach ($crossSellingElement->getProducts()->getElements() as $prod)
  500.                         {
  501.                             if ($counter $config['accessoriesCartOneSliderNumber'])
  502.                             {
  503.                                 $productCollection->add($prod);
  504.                                 $counter++;
  505.                             } else {
  506.                                 break;
  507.                             }
  508.                         }
  509.                         $this->filteredAccessories->remove($index);
  510.                     }
  511.                     $remainingElement->setProducts($productCollection);
  512.                     $this->filteredAccessories->add($remainingElement);
  513.                 }
  514.                 if (version_compare($this->shopwareVersion'6.4.11''>='))
  515.                 {
  516.                     $page->assign(['cbaxSW6411' => true]);
  517.                 } else {
  518.                     $page->assign(['cbaxSW6411' => false]);
  519.                 }
  520.                 $page->assign(['cbaxCrossSelling' => $cbaxCrossSellings]);
  521.                 $page->assign(['filteredAccessories' => $this->filteredAccessories]);
  522.                 //$page->assign(['filteredSimilarArticle' => $this->filteredSimilarArticle]);
  523.             }
  524.         }
  525.     }
  526.     public function sortData($element$crossSellings)
  527.     {
  528.         $accessoriesIds = array();
  529.         $similarArticleIds = array();
  530.         foreach ($crossSellings as $item) {
  531.             if ($item->getCrossSellingGroup() === 'accessories') {
  532.                 $accessoriesIds[] = $item->crossSellingId;
  533.             }
  534.             if ($item->getCrossSellingGroup() === 'similar_article') {
  535.                 $similarArticleIds[] = $item->crossSellingId;
  536.             }
  537.         }
  538.         if (in_array($element->getCrossSelling()->get('id'), $accessoriesIds)) {
  539.             $this->filteredAccessories->add($element);
  540.         }
  541.         if (in_array($element->getCrossSelling()->get('id'), $similarArticleIds)) {
  542.             $this->filteredSimilarArticle->add($element);
  543.         }
  544.     }
  545.     public function filterSameAccessories($filteredLineItemsIds$config)
  546.     {
  547.         $streamIds = array();
  548.         $names = array();
  549.         foreach ($this->filteredAccessories->getElements() as $index => $crossSellingElement) {
  550.             $crossSelling $crossSellingElement->getCrossSelling();
  551.             if ($crossSelling->getType() === 'productStream' && $crossSelling->getProductStreamId() !== null) {
  552.                 if (!in_array($crossSelling->getProductStreamId(), $streamIds)) {
  553.                     $streamIds[] = $crossSelling->getProductStreamId();
  554.                 } else {
  555.                     $this->filteredAccessories->remove($index);
  556.                 }
  557.             } else if ($crossSelling->getType() === 'productList') {
  558.                 // Abgleich per Name
  559.                 if (!in_array($crossSelling->getTranslated()['name'], $names)) {
  560.                     $names[] = $crossSelling->getTranslated()['name'];
  561.                 } else {
  562.                     $this->filteredAccessories->remove($index);
  563.                 }
  564.             }
  565.         }
  566.         //Produkte schon in cart ausfiltern
  567.         if (!empty($config['accessoriesCartFilter']))
  568.         {
  569.             foreach ($this->filteredAccessories->getElements() as $index => $crossSellingElement)
  570.             {
  571.                 $assignedProducts $crossSellingElement->getProducts();
  572.                 $assignedProductIds $assignedProducts->getIds();
  573.                 foreach ($assignedProductIds as $productId)
  574.                 {
  575.                     if (in_array($productId$filteredLineItemsIds))
  576.                     {
  577.                         $assignedProducts->remove($productId);
  578.                     }
  579.                 }
  580.                 if ($assignedProducts->count() > 0)
  581.                 {
  582.                     $crossSellingElement->setProducts($assignedProducts);
  583.                 } else {
  584.                     $this->filteredAccessories->remove($index);
  585.                 }
  586.             }
  587.         }
  588.     }
  589. }