custom/plugins/phpSchmiedLastSeenProducts/src/Subscriber/lastSeenProducts.php line 81

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace phpSchmied\LastSeenProducts\Subscriber;
  3. use Shopware\Core\Content\Cms\Aggregate\CmsBlock\CmsBlockCollection;
  4. use Shopware\Core\Content\Cms\Aggregate\CmsBlock\CmsBlockEntity;
  5. use Shopware\Core\Content\Cms\Aggregate\CmsSection\CmsSectionEntity;
  6. use Shopware\Core\Content\Cms\Aggregate\CmsSlot\CmsSlotCollection;
  7. use Shopware\Core\Content\Cms\Aggregate\CmsSlot\CmsSlotEntity;
  8. use Shopware\Core\Content\Cms\SalesChannel\Struct\CrossSellingStruct;
  9. use Shopware\Core\Content\Product\Aggregate\ProductCrossSelling\ProductCrossSellingEntity;
  10. use Shopware\Core\Content\Product\ProductCollection;
  11. use Shopware\Core\Content\Product\ProductEntity;
  12. use Shopware\Core\Content\Product\SalesChannel\CrossSelling\CrossSellingElement;
  13. use Shopware\Core\Content\Product\SalesChannel\CrossSelling\CrossSellingElementCollection;
  14. use Shopware\Core\Content\Product\SalesChannel\Listing\Filter;
  15. use Shopware\Core\Framework\Context;
  16. use Shopware\Core\Framework\DataAbstractionLayer\EntityCollection;
  17. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
  18. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsAnyFilter;
  19. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  20. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\NotFilter;
  21. use Shopware\Core\Framework\DataAbstractionLayer\Search\Grouping\FieldGrouping;
  22. use Shopware\Core\Framework\Struct\Collection;
  23. use Shopware\Core\Framework\Uuid\Uuid;
  24. use Shopware\Core\System\Snippet\SnippetService;
  25. use Shopware\Core\Content\Product\SalesChannel\SalesChannelProductEntity;
  26. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  27. use Shopware\Core\System\SalesChannel\Entity\SalesChannelRepositoryInterface;
  28. use Shopware\Core\System\SystemConfig\SystemConfigService;
  29. use Shopware\Storefront\Page\Product\CrossSelling\CrossSellingLoaderResult;
  30. use Shopware\Storefront\Page\Product\ProductPageLoadedEvent;
  31. use Symfony\Component\DependencyInjection\Container;
  32. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  33. use Symfony\Component\HttpFoundation\Session\Session;
  34. class lastSeenProducts implements EventSubscriberInterface
  35. {
  36.     /**
  37.      * @var SystemConfigService
  38.      */
  39.     private $systemConfigService;
  40.     protected $container;
  41.     /**
  42.      * @var SalesChannelRepositoryInterface
  43.      */
  44.     private $productRepository;
  45.     /**
  46.      * @var SnippetService
  47.      */
  48.     private $snippetService;
  49.     public function __construct(
  50.         Container $container,
  51.         SalesChannelRepositoryInterface $entityRepository,
  52.         SystemConfigService $systemConfigService,
  53.         SnippetService $snippetService
  54.     )
  55.     {
  56.         $this->container $container;
  57.         $this->productRepository $entityRepository;
  58.         $this->systemConfigService $systemConfigService;
  59.         $this->snippetService $snippetService;
  60.     }
  61.     /**
  62.      * @inheritDoc
  63.      */
  64.     public static function getSubscribedEvents()
  65.     {
  66.         return [
  67.             ProductPageLoadedEvent::class => 'onLoadProduct',
  68.         ];
  69.     }
  70.     public function onLoadProduct(ProductPageLoadedEvent $event)
  71.     {
  72.         /**@var $product SalesChannelProductEntity */
  73.         $product $event->getPage()->getProduct();
  74.         $session = new Session();
  75.         $last_seen_products $session->get('last_seen_products');
  76.         if (is_array($last_seen_products)) {
  77.             $snippet $this->getSnippet($event);
  78.             $cross_selling = new CrossSellingElementCollection();
  79.             $product_collection = new ProductCollection();
  80.             $product_cross_selling_entity = new ProductCrossSellingEntity();
  81.             $product_cross_selling_entity->setId(Uuid::randomHex());
  82.             $product_cross_selling_entity->setActive(true);
  83.             $product_cross_selling_entity->setLimit((int)$this->systemConfigService->get('phpSchmiedLastSeenProducts.config.limit'));
  84.             $product_cross_selling_entity->setPosition(1);
  85.             $product_cross_selling_entity->setProductId($product->getId());
  86.             $product_cross_selling_entity->setType('productList');
  87.             $product_cross_selling_entity->setTranslated(['name' => $snippet['phpSchmied.lastseenproducts.headline']]);
  88.             $product_cross_selling_entity->setName($snippet['phpSchmied.lastseenproducts.headline']);
  89.             $products $this->getProducts($last_seen_products1, (int)$this->systemConfigService->get('phpSchmiedLastSeenProducts.config.limit'), $event);
  90.             foreach ($products->getElements() as $cross_sell_product) {
  91.                 if ($cross_sell_product->getId() !== $product->getId() && !$product_collection->has($cross_sell_product->getId())) {
  92.                     $show false;
  93.                     /**@var $cross_sell_product ProductEntity* */
  94.                     if(
  95.                         $this->systemConfigService->get('phpSchmiedLastSeenProducts.config.varianten') !== null &&
  96.                         $this->systemConfigService->get('phpSchmiedLastSeenProducts.config.varianten') === true &&
  97.                         $cross_sell_product->getParentId() !== null
  98.                     ) {
  99.                         if(!$product_collection->has($cross_sell_product->getParentId())) {
  100.                             $parent_products $this->getProducts([$cross_sell_product->getParentId()], 1, (int)$this->systemConfigService->get('phpSchmiedLastSeenProducts.config.limit'), $event);
  101.                             foreach ($parent_products->getElements() as $parentProduct) {
  102.                                 $cross_sell_product $parentProduct;
  103.                             }
  104.                         } else {
  105.                             continue;
  106.                         }
  107.                     }
  108.                     if(
  109.                         $this->systemConfigService->get('phpSchmiedLastSeenProducts.config.inactive') !== null &&
  110.                         $this->systemConfigService->get('phpSchmiedLastSeenProducts.config.inactive') === true &&
  111.                         !$cross_sell_product->getActive()
  112.                     ) {
  113.                         continue;
  114.                     }
  115.                     if(
  116.                         $this->systemConfigService->get('phpSchmiedLastSeenProducts.config.abverkauf') !== null &&
  117.                         $this->systemConfigService->get('phpSchmiedLastSeenProducts.config.abverkauf') === true &&
  118.                         !$cross_sell_product->getStock()
  119.                     ) {
  120.                         continue;
  121.                     }
  122.                     if (
  123.                         $this->systemConfigService->get('phpSchmiedLastSeenProducts.config.categories') !== null &&
  124.                         is_array($this->systemConfigService->get('phpSchmiedLastSeenProducts.config.categories')) &&
  125.                         count($this->systemConfigService->get('phpSchmiedLastSeenProducts.config.categories'))
  126.                     ) {
  127.                         foreach ($this->systemConfigService->get('phpSchmiedLastSeenProducts.config.categories') as $category_id) {
  128.                             if (in_array($category_id$cross_sell_product->getCategoryTree())) {
  129.                                 $show true;
  130.                             }
  131.                         }
  132.                     } else {
  133.                         $show true;
  134.                     }
  135.                     /**@var $cross_sell_product ProductEntity* */
  136.                     if (
  137.                         $this->systemConfigService->get('phpSchmiedLastSeenProducts.config.disabledCategories') !== null &&
  138.                         is_array($this->systemConfigService->get('phpSchmiedLastSeenProducts.config.disabledCategories')) &&
  139.                         count($this->systemConfigService->get('phpSchmiedLastSeenProducts.config.disabledCategories'))
  140.                     ) {
  141.                         foreach ($this->systemConfigService->get('phpSchmiedLastSeenProducts.config.disabledCategories') as $category_id) {
  142.                             if (in_array($category_id$cross_sell_product->getCategoryTree())) {
  143.                                 $show false;
  144.                             }
  145.                         }
  146.                     }
  147.                     if ($show) {
  148.                         $product_collection->add($cross_sell_product);
  149.                     }
  150.                 }
  151.             }
  152.             //Is any crossSelling element in use
  153.             if ($event->getPage()->getCmsPage() === null) {
  154.                 if ($event->getPage()->getCrossSellings() instanceof CrossSellingLoaderResult) {
  155.                     $cross_selling_element = new \Shopware\Storefront\Page\Product\CrossSelling\CrossSellingElement();
  156.                 } else {
  157.                     $cross_selling_element = new CrossSellingElement();
  158.                 }
  159.             } else {
  160.                 $cross_selling_element = new CrossSellingElement();
  161.             }
  162.             $cross_selling_element->setProducts($product_collection);
  163.             $cross_selling_element->setCrossSelling($product_cross_selling_entity);
  164.             $cross_selling->add($cross_selling_element);
  165.             $cross_selling_element->setTotal(count($last_seen_products));
  166.             //Is any crossSelling element in use
  167.             if ($event->getPage()->getCmsPage() !== null) {
  168.                 foreach ($event->getPage()->getCmsPage()->getSections()->getBlocks() as $block) {
  169.                     if ($block->getType() === 'cross-selling') {
  170.                         foreach ($block->getSlots() as $slot) {
  171.                             $cs $slot->getData()->getVars();
  172.                             if(isset($cs['crossSellings']) && $cs['crossSellings'] !== null) {
  173.                                 $cs['crossSellings']->add($cross_selling_element);
  174.                             } else {
  175.                                 $crossSellingStruct = new CrossSellingStruct();
  176.                                 $csCollection  = new CrossSellingElementCollection();
  177.                                 $csCollection->add($cross_selling_element);
  178.                                 $crossSellingStruct->setCrossSellings($csCollection);
  179.                                 $slot->setData($crossSellingStruct);
  180.                             }
  181.                         }
  182.                     }
  183.                 }
  184.             } else {
  185.                 if (count($product_collection->getElements())) {
  186.                     $event->getPage()->getCrossSellings()->add($cross_selling_element);
  187.                 }
  188.             }
  189.         }
  190.         //If is set a slider limit
  191.         $tmp_limit $this->systemConfigService->get('phpSchmiedLastSeenProducts.config.limit');
  192.         //validate the limit value
  193.         if ($tmp_limit !== null && $tmp_limit !== '' && is_int((int)$tmp_limit) && (int)$tmp_limit >= 0) {
  194.             if ((int)$tmp_limit <= 6) {
  195.                 $limit = (int)$tmp_limit;
  196.             } else {
  197.                 $limit 6;
  198.             }
  199.         } else {
  200.             $limit 0;
  201.         }
  202.         if (!is_array($last_seen_products)) {
  203.             $last_seen_products = [];
  204.         }
  205.         if (!in_array($product->getId(), $last_seen_products)) {
  206.             array_unshift($last_seen_products$product->getId());
  207.         }
  208.         if (count($last_seen_products) > $limit) {
  209.             $last_seen_products array_splice($last_seen_products0$limit);
  210.         }
  211.         $session->set('last_seen_products'$last_seen_products);
  212.     }
  213.     /**
  214.      * Loads the product by product id
  215.      * @param $products_array null|array
  216.      * @param ProductPageLoadedEvent $event
  217.      * @param int $limit
  218.      * @throws \Shopware\Core\Framework\DataAbstractionLayer\Exception\InconsistentCriteriaIdsException
  219.      */
  220.     private function getProductsBak(?array $products_arrayProductPageLoadedEvent $event)
  221.     {
  222.         $criteria = new Criteria($products_array);
  223.         $criteria->addAssociation('cover');
  224.         $criteria->addAssociation('manufaturer');
  225.         return $this->productRepository->search($criteria$event->getSalesChannelContext());
  226.     }
  227.     /**
  228.      * @param $seenProductIds
  229.      * @param $minimumItems
  230.      * @param $maximumItems
  231.      * @param $context
  232.      *
  233.      * @return \Shopware\Core\Framework\DataAbstractionLayer\EntityCollection
  234.      */
  235.     private function getProducts($seenProductIds$minimumItems$maximumItems$event)
  236.     {
  237.         if (!$seenProductIds) {
  238.             return new EntityCollection();
  239.         }
  240.         if (count($seenProductIds) < $minimumItems) {
  241.             return new EntityCollection();
  242.         }
  243.         $criteria = new Criteria();
  244.         $criteria->addAssociation('cover');
  245.         $criteria->addAssociation('manufacturer');
  246.         $criteria->setLimit($maximumItems);
  247.         $criteria->addFilter(new EqualsAnyFilter('id'$seenProductIds));
  248.         $criteria->addFilter(
  249.             new NotFilter(
  250.                 NotFilter::CONNECTION_AND,
  251.                 [new EqualsFilter('displayGroup'null)]
  252.             )
  253.         );
  254.         $criteria->addGroupField(new FieldGrouping('displayGroup'));
  255.         $products $this->productRepository->search($criteria$event->getSalesChannelContext())->getEntities();
  256.         return $products;
  257.     }
  258.     private function getSnippet(ProductPageLoadedEvent $event)
  259.     {
  260.         $languageId $event->getSalesChannelContext()->getSalesChannel()->getLanguageId();
  261.         /** @var EntityRepository $languageRepository */
  262.         $languageRepository $this->container->get('language.repository');
  263.         $criteria = new Criteria();
  264.         $criteria->addFilter(new EqualsFilter('id'$languageId));
  265.         $language $languageRepository->search($criteria$event->getContext())->first();
  266.         /** @var EntityRepository $localeRepository */
  267.         $localeRepository $this->container->get('locale.repository');
  268.         $criteria = new Criteria();
  269.         $criteria->addFilter(new EqualsFilter('id'$language->getLocaleId()));
  270.         $locale $localeRepository->search($criteria$event->getContext())->first();
  271.         $snippet_sets $this->snippetService->getSnippetSet(
  272.             $event->getSalesChannelContext()->getSalesChannel()->getId(),
  273.             $event->getSalesChannelContext()->getSalesChannel()->getLanguageId(),
  274.             $locale->getCode(),
  275.             $event->getContext()
  276.         );
  277.         $translator $this->container->get('translator');
  278.         $catalog $translator->getCatalogue($locale->getCode());
  279.         $snippet $this->snippetService->getStorefrontSnippets(
  280.             $catalog,
  281.             $snippet_sets->getId()
  282.         );
  283.         return $snippet;
  284.     }
  285. }