vendor/ibexa/product-catalog/src/bundle/EventSubscriber/PageBuilder/CatalogBlockSubscriber.php line 69

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\Core\Repository\Exceptions\NotFoundException;
  9. use Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException;
  10. use Ibexa\Contracts\FieldTypePage\FieldType\LandingPage\Model\BlockValue;
  11. use Ibexa\Contracts\ProductCatalog\CatalogServiceInterface;
  12. use Ibexa\Contracts\ProductCatalog\CustomerGroupResolverInterface;
  13. use Ibexa\Contracts\ProductCatalog\ProductServiceInterface;
  14. use Ibexa\Contracts\ProductCatalog\Values\CatalogInterface;
  15. use Ibexa\Contracts\ProductCatalog\Values\CustomerGroupInterface;
  16. use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery;
  17. use Ibexa\Contracts\ProductCatalog\Values\Product\Query\CriterionInterface;
  18. use Ibexa\FieldTypePage\FieldType\Page\Block\Renderer\BlockRenderEvents;
  19. use Ibexa\FieldTypePage\FieldType\Page\Block\Renderer\Event\PreRenderEvent;
  20. use Ibexa\ProductCatalog\Pagerfanta\Adapter\ProductListAdapter;
  21. use Pagerfanta\Pagerfanta;
  22. use Psr\Log\LoggerAwareInterface;
  23. use Psr\Log\LoggerAwareTrait;
  24. use Psr\Log\LoggerInterface;
  25. use Psr\Log\NullLogger;
  26. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  27. use Symfony\Component\HttpFoundation\RequestStack;
  28. final class CatalogBlockSubscriber implements EventSubscriberInterfaceLoggerAwareInterface
  29. {
  30.     private const BLOCK_IDENTIFIER 'catalog';
  31.     private const PAGE_PARAM 'page_';
  32.     private const DEFAULT_CURRENT_PAGE 1;
  33.     use LoggerAwareTrait;
  34.     private CatalogServiceInterface $catalogService;
  35.     private CustomerGroupResolverInterface $customerGroupResolver;
  36.     private ProductServiceInterface $productService;
  37.     private RequestStack $requestStack;
  38.     public function __construct(
  39.         CatalogServiceInterface $catalogService,
  40.         CustomerGroupResolverInterface $customerGroupResolver,
  41.         ProductServiceInterface $productService,
  42.         RequestStack $requestStack,
  43.         ?LoggerInterface $logger null
  44.     ) {
  45.         $this->catalogService $catalogService;
  46.         $this->customerGroupResolver $customerGroupResolver;
  47.         $this->productService $productService;
  48.         $this->requestStack $requestStack;
  49.         $this->logger $logger ?? new NullLogger();
  50.     }
  51.     public static function getSubscribedEvents(): array
  52.     {
  53.         return [
  54.             BlockRenderEvents::getBlockPreRenderEventName(self::BLOCK_IDENTIFIER) => 'onBlockPreRender',
  55.         ];
  56.     }
  57.     public function onBlockPreRender(PreRenderEvent $event): void
  58.     {
  59.         /** @var \Ibexa\FieldTypePage\FieldType\Page\Block\Renderer\Twig\TwigRenderRequest $renderRequest */
  60.         $renderRequest $event->getRenderRequest();
  61.         $parameters $renderRequest->getParameters();
  62.         $blockValue $event->getBlockValue();
  63.         $catalog $this->getMappedCatalog($blockValue) ?? $this->getDefaultCatalog($blockValue);
  64.         $products = [];
  65.         if (null !== $catalog) {
  66.             $products $this->getProductList(
  67.                 $catalog->getQuery(),
  68.                 (int) $parameters['limit'],
  69.                 $this->getCurrentPage(self::PAGE_PARAM $blockValue->getId())
  70.             );
  71.         }
  72.         $parameters['products'] = $products;
  73.         unset($parameters['default_catalog'], $parameters['catalog_map']);
  74.         $renderRequest->setParameters($parameters);
  75.     }
  76.     private function getMappedCatalog(BlockValue $blockValue): ?CatalogInterface
  77.     {
  78.         $catalogMap $this->getCatalogMap($blockValue);
  79.         $customerGroup $this->resolveCustomerGroup();
  80.         if (
  81.             !empty($catalogMap)
  82.             && null !== $customerGroup
  83.         ) {
  84.             foreach ($catalogMap as $data) {
  85.                 if ($customerGroup->getId() === $data['customer_group']) {
  86.                     return $this->getCatalog((int) $data['catalog']);
  87.                 }
  88.             }
  89.         }
  90.         return null;
  91.     }
  92.     /**
  93.      * @return \Pagerfanta\Pagerfanta<\Ibexa\Contracts\ProductCatalog\Values\ProductInterface>
  94.      */
  95.     private function getProductList(
  96.         CriterionInterface $criterion,
  97.         int $limit,
  98.         int $currentPage
  99.     ): Pagerfanta {
  100.         $products = new Pagerfanta(
  101.             new ProductListAdapter(
  102.                 $this->productService,
  103.                 new ProductQuery($criterion)
  104.             )
  105.         );
  106.         $products->setMaxPerPage($limit);
  107.         $products->setCurrentPage($currentPage);
  108.         return $products;
  109.     }
  110.     private function resolveCustomerGroup(): ?CustomerGroupInterface
  111.     {
  112.         try {
  113.             return $this->customerGroupResolver->resolveCustomerGroup();
  114.         } catch (NotFoundException UnauthorizedException $exception) {
  115.             $this->logger->warning($exception->getMessage());
  116.             return null;
  117.         }
  118.     }
  119.     private function getCatalog(int $id): ?CatalogInterface
  120.     {
  121.         try {
  122.             return $this->catalogService->getCatalog($id);
  123.         } catch (NotFoundException UnauthorizedException $exception) {
  124.             $this->logger->warning($exception->getMessage());
  125.             return null;
  126.         }
  127.     }
  128.     private function getDefaultCatalog(BlockValue $blockValue): ?CatalogInterface
  129.     {
  130.         $catalog $blockValue->getAttribute('default_catalog');
  131.         if (null === $catalog) {
  132.             return null;
  133.         }
  134.         return $this->getCatalog((int) $catalog->getValue());
  135.     }
  136.     /**
  137.      * @return array<array{
  138.      *     'customer_group': int,
  139.      *     'catalog': int,
  140.      * }>
  141.      *
  142.      * @throws \JsonException
  143.      */
  144.     private function getCatalogMap(BlockValue $blockValue): array
  145.     {
  146.         $catalogMapAttribute $blockValue->getAttribute('catalog_map');
  147.         if (null === $catalogMapAttribute) {
  148.             return [];
  149.         }
  150.         return json_decode(
  151.             $catalogMapAttribute->getValue(),
  152.             true,
  153.             512,
  154.             JSON_THROW_ON_ERROR
  155.         );
  156.     }
  157.     private function getCurrentPage(string $pageParam): int
  158.     {
  159.         $request $this->requestStack->getMainRequest();
  160.         if (null === $request) {
  161.             return self::DEFAULT_CURRENT_PAGE;
  162.         }
  163.         return $request->query->getInt($pageParamself::DEFAULT_CURRENT_PAGE);
  164.     }
  165. }