custom/plugins/XantenLastSeenProduct/src/Controller/LastSeenProductController.php line 52

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace XantenLastSeenProduct\Controller;
  4. use Shopware\Core\Content\Product\SalesChannel\SalesChannelProductEntity;
  5. use Shopware\Core\Framework\DataAbstractionLayer\EntityCollection;
  6. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  7. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsAnyFilter;
  8. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  9. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\NotFilter;
  10. use Shopware\Core\Framework\DataAbstractionLayer\Search\Grouping\FieldGrouping;
  11. use Shopware\Core\Framework\Routing\Annotation\RouteScope;
  12. use Shopware\Core\System\SalesChannel\Entity\SalesChannelRepositoryInterface;
  13. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  14. use Shopware\Core\System\SystemConfig\SystemConfigService;
  15. use Shopware\Storefront\Controller\StorefrontController;
  16. use Symfony\Component\HttpFoundation\JsonResponse;
  17. use Symfony\Component\HttpFoundation\Request;
  18. use Symfony\Component\Routing\Annotation\Route;
  19. /**
  20.  * @RouteScope(scopes={"storefront"})
  21.  */
  22. class LastSeenProductController extends StorefrontController
  23. {
  24.     public const LAST_SEEN_PRODUCTS 'seen-products';
  25.     /**
  26.      * @var SalesChannelRepositoryInterface
  27.      */
  28.     private $productRepository;
  29.     /**
  30.      * @var SystemConfigService
  31.      */
  32.     private $systemConfigService;
  33.     /**
  34.      * LastSeenProductController constructor.
  35.      */
  36.     public function __construct(SalesChannelRepositoryInterface $productRepositorySystemConfigService $systemConfigService)
  37.     {
  38.         $this->productRepository $productRepository;
  39.         $this->systemConfigService $systemConfigService;
  40.     }
  41.     /**
  42.      * @Route("/lastseen-product/add", name="frontend.last.seen.product.add", methods={"POST"}, defaults={"csrf_protected"=false, "XmlHttpRequest"=true})
  43.      */
  44.     public function addLastSeenProduct(Request $requestSalesChannelContext $context)
  45.     {
  46.         $productId $request->request->get('productId');
  47.         if (!$productId) {
  48.             return new JsonResponse([], 400);
  49.         }
  50.         $seenProductIds $request->getSession()->get(self::LAST_SEEN_PRODUCTSnull);
  51.         if (!$seenProductIds) {
  52.             $seenProductIds $productId;
  53.         } else {
  54.             $maxProducts $this->systemConfigService->get('XantenLastSeenProduct.config.maxProducts');
  55.             $seenProductIds explode('|'$seenProductIds);
  56.             $added array_search($productId$seenProductIds);
  57.             if (false !== $added) {
  58.                 unset($seenProductIds[$added]);
  59.             }
  60.             array_unshift($seenProductIds$productId);
  61.             $seenProductIds array_slice($seenProductIds0$maxProducts);
  62.             $seenProductIds implode('|'$seenProductIds);
  63.         }
  64.         $request->getSession()->set(self::LAST_SEEN_PRODUCTS$seenProductIds);
  65.         return new JsonResponse();
  66.     }
  67.     /**
  68.      * @Route("/widgets/lastseen-product", name="frontend.last.seen.product.page", options={"seo"="false"}, methods={"GET"}, defaults={"XmlHttpRequest"=true})
  69.      */
  70.     public function index(Request $requestSalesChannelContext $context)
  71.     {
  72.         $seenProductIds $request->getSession()->get(self::LAST_SEEN_PRODUCTS);
  73.         $minimumItems = (int) $request->get('minItems'4);
  74.         $maximumItems = (int) $request->get('maxItems'16);
  75.         $layout $request->get('layout''standard');
  76.         $displayMode $request->get('displayMode''standard');
  77.         $skipProductId $request->get('skipProductId');
  78.         $result $this->getProducts($seenProductIds$skipProductId$minimumItems$maximumItems$context);
  79.         $products $result->getElements();
  80.         if ($result->count()) {
  81.             $seenProductIds explode('|'$seenProductIds);
  82.             $products array_merge(array_flip($seenProductIds), $products);
  83.             $products array_filter($products, function ($product) {
  84.                 return $product instanceof SalesChannelProductEntity;
  85.             });
  86.         }
  87.         return $this->renderStorefront(
  88.             '@XantenLastSeenProduct/storefront/component/product-slider.html.twig',
  89.             [
  90.                 'products' => $products,
  91.                 'layout' => $layout,
  92.                 'displayMode' => $displayMode
  93.             ]
  94.         );
  95.     }
  96.     /**
  97.      * @param  string|null  $seenProductIds
  98.      * @param  string|null  $skipProductId
  99.      * @param  int  $minimumItems
  100.      * @param  int  $maximumItems
  101.      * @param  SalesChannelContext $context
  102.      *
  103.      * @return \Shopware\Core\Framework\DataAbstractionLayer\EntityCollection
  104.      */
  105.     private function getProducts($seenProductIds$skipProductId$minimumItems$maximumItems$context)
  106.     {
  107.         if (!$seenProductIds) {
  108.             return new EntityCollection();
  109.         }
  110.         $seenProductIds explode('|'$seenProductIds);
  111.         if (count($seenProductIds) < $minimumItems) {
  112.             return new EntityCollection();
  113.         }
  114.         $criteria = new Criteria($seenProductIds);
  115.         $criteria->addAssociation('cover');
  116.         $criteria->setLimit($maximumItems);
  117.         if ($skipProductId) {
  118.             $criteria->addFilter(new NotFilter(NotFilter::CONNECTION_AND, [
  119.                 new EqualsFilter('id'$skipProductId)
  120.             ]));
  121.         }
  122.         $criteria->addFilter(
  123.             new NotFilter(
  124.                 NotFilter::CONNECTION_AND,
  125.                 [new EqualsFilter('displayGroup'null)]
  126.             )
  127.         );
  128.         $criteria->addGroupField(new FieldGrouping('displayGroup'));
  129.         return $this->productRepository->search($criteria$context)->getEntities();
  130.     }
  131. }