vendor/ibexa/product-catalog/src/bundle/EventSubscriber/PageBuilder/ProductCollectionBlockSubscriber.php line 49

Open in your IDE?
  1. <?php
  2. /**
  3.  * @copyright Copyright (C) Ibexa AS. All rights reserved.
  4.  * @license For full copyright and license information view LICENSE file distributed with this source code.
  5.  */
  6. declare(strict_types=1);
  7. namespace Ibexa\Bundle\ProductCatalog\EventSubscriber\PageBuilder;
  8. use Ibexa\Contracts\FieldTypePage\FieldType\LandingPage\Model\BlockValue;
  9. use Ibexa\Contracts\ProductCatalog\ProductServiceInterface;
  10. use Ibexa\Contracts\ProductCatalog\Values\Product\ProductListInterface;
  11. use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery;
  12. use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion\LogicalAnd;
  13. use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion\ProductCode;
  14. use Ibexa\FieldTypePage\FieldType\Page\Block\Renderer\BlockRenderEvents;
  15. use Ibexa\FieldTypePage\FieldType\Page\Block\Renderer\Event\PreRenderEvent;
  16. use Pagerfanta\Adapter\ArrayAdapter;
  17. use Pagerfanta\Pagerfanta;
  18. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  19. use Symfony\Component\HttpFoundation\RequestStack;
  20. final class ProductCollectionBlockSubscriber implements EventSubscriberInterface
  21. {
  22.     private const BLOCK_IDENTIFIER 'product_collection';
  23.     private const PAGE_PARAM 'page_';
  24.     private const DEFAULT_CURRENT_PAGE 1;
  25.     private ProductServiceInterface $productService;
  26.     private RequestStack $requestStack;
  27.     public function __construct(
  28.         ProductServiceInterface $productService,
  29.         RequestStack $requestStack
  30.     ) {
  31.         $this->productService $productService;
  32.         $this->requestStack $requestStack;
  33.     }
  34.     public static function getSubscribedEvents(): array
  35.     {
  36.         return [
  37.             BlockRenderEvents::getBlockPreRenderEventName(self::BLOCK_IDENTIFIER) => 'onBlockPreRender',
  38.         ];
  39.     }
  40.     public function onBlockPreRender(PreRenderEvent $event): void
  41.     {
  42.         /** @var \Ibexa\FieldTypePage\FieldType\Page\Block\Renderer\Twig\TwigRenderRequest $renderRequest */
  43.         $renderRequest $event->getRenderRequest();
  44.         $parameters $renderRequest->getParameters();
  45.         $blockValue $event->getBlockValue();
  46.         $codes $this->getProductsCodes($blockValue);
  47.         $query $this->getProductQuery($codes);
  48.         $products $this->sortByProductCodes(
  49.             $this->getProductList($query),
  50.             array_flip($codes)
  51.         );
  52.         $parameters['products'] = $this->getPagerfanta(
  53.             $products,
  54.             $query->getLimit(),
  55.             $this->getCurrentPage(self::PAGE_PARAM $blockValue->getId())
  56.         );
  57.         $renderRequest->setParameters($parameters);
  58.     }
  59.     /**
  60.      * @param array<string> $codes
  61.      */
  62.     private function getProductQuery(array $codes): ProductQuery
  63.     {
  64.         return new ProductQuery(
  65.             new LogicalAnd(
  66.                 [
  67.                     new ProductCode($codes),
  68.                 ]
  69.             )
  70.         );
  71.     }
  72.     /**
  73.      * @return array<string>
  74.      */
  75.     private function getProductsCodes(BlockValue $blockValue): array
  76.     {
  77.         $blockAttribute $blockValue->getAttribute('products');
  78.         if (null === $blockAttribute) {
  79.             return [];
  80.         }
  81.         return explode(','$blockAttribute->getValue());
  82.     }
  83.     private function getProductList(ProductQuery $query): ProductListInterface
  84.     {
  85.         return $this->productService->findProducts($query);
  86.     }
  87.     /**
  88.      * @param array<\Ibexa\Contracts\ProductCatalog\Values\ProductInterface> $products
  89.      *
  90.      * @return \Pagerfanta\Pagerfanta<\Ibexa\Contracts\ProductCatalog\Values\ProductInterface>
  91.      */
  92.     private function getPagerfanta(
  93.         array $products,
  94.         int $limit,
  95.         int $currentPage
  96.     ): Pagerfanta {
  97.         $pagerfanta = new Pagerfanta(new ArrayAdapter($products));
  98.         $pagerfanta->setMaxPerPage($limit);
  99.         $pagerfanta->setCurrentPage($currentPage);
  100.         return $pagerfanta;
  101.     }
  102.     /**
  103.      * @param array<string, int> $codes
  104.      *
  105.      * @return array<\Ibexa\Contracts\ProductCatalog\Values\ProductInterface>
  106.      */
  107.     private function sortByProductCodes(
  108.         ProductListInterface $products,
  109.         array $codes
  110.     ): array {
  111.         $results = [];
  112.         foreach ($products as $product) {
  113.             if (isset($codes[$product->getCode()])) {
  114.                 $results[$codes[$product->getCode()]] = $product;
  115.             }
  116.         }
  117.         ksort($results);
  118.         return $results;
  119.     }
  120.     private function getCurrentPage(string $pageParam): int
  121.     {
  122.         $request $this->requestStack->getMainRequest();
  123.         if (null === $request) {
  124.             return self::DEFAULT_CURRENT_PAGE;
  125.         }
  126.         return $request->query->getInt($pageParamself::DEFAULT_CURRENT_PAGE);
  127.     }
  128. }