custom/plugins/WbfkExtensions/src/Core/Content/ProductComparison/ProductComparisonService.php line 44

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace WbfkExtensions\Core\Content\ProductComparison;
  4. use Doctrine\DBAL\Connection;
  5. use Doctrine\DBAL\Driver\Exception;
  6. use Shopware\Core\Content\Cms\Aggregate\CmsSlot\CmsSlotCollection;
  7. use Shopware\Core\Content\Cms\Aggregate\CmsSlot\CmsSlotEntity;
  8. use Shopware\Core\Content\Cms\DataResolver\CmsSlotsDataResolver;
  9. use Shopware\Core\Content\Cms\DataResolver\ResolverContext\ResolverContext;
  10. use Shopware\Core\Content\Product\SalesChannel\SalesChannelProductEntity;
  11. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  12. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsAnyFilter;
  13. use Shopware\Core\Framework\Uuid\Uuid;
  14. use Shopware\Core\System\SalesChannel\Entity\SalesChannelRepository;
  15. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  16. use Shopware\Core\System\SystemConfig\SystemConfigService;
  17. use Symfony\Component\HttpFoundation\Request;
  18. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  19. class ProductComparisonService
  20. {
  21.     private ?ProductForComparisonCollection $productForComparisonCollection null;
  22.     public function __construct(
  23.         private readonly SalesChannelRepository $productRepository,
  24.         private readonly CmsSlotsDataResolver $cmsSlotsDataResolver,
  25.         private readonly Connection $connection,
  26.         private readonly SystemConfigService $systemConfigService
  27.     ) {
  28.     }
  29.     public function getComparisonList(
  30.         SessionInterface $session
  31.     ): ProductForComparisonCollection {
  32.         return $this->productForComparisonCollection ?? $this->loadProductForComparisonCollection($session);
  33.     }
  34.     private function loadProductForComparisonCollection(
  35.         SessionInterface $session
  36.     ): ProductForComparisonCollection {
  37.         $this->productForComparisonCollection $session->get(
  38.             'productIdsForComparison',
  39.             new ProductForComparisonCollection()
  40.         );
  41.         $session->set('productIdsForComparison'$this->productForComparisonCollection);
  42.         return $this->productForComparisonCollection;
  43.     }
  44.     public function addProduct(SessionInterface $sessionSalesChannelContext $contextstring $productId): void
  45.     {
  46.         $maximumProductsToCompare = (int)$this->systemConfigService->get(
  47.             'WbfkExtensions.config.maximumProductsToCompare'
  48.         );
  49.         if ($this->getComparisonList($session)->count() === $maximumProductsToCompare) {
  50.             throw new MaximumProductsToCompareReachedException($maximumProductsToCompare);
  51.         }
  52.         $criteria = new Criteria([$productId]);
  53.         $criteria->addAssociation('cover');
  54.         /** @var SalesChannelProductEntity $product */
  55.         $product $this->productRepository->search($criteria$context)->getEntities()->first();
  56.         $productForComparison = new ProductForComparison(
  57.             $product->getId(),
  58.             $product->getName(),
  59.             $product->getProductNumber(),
  60.             $product->getCover()?->getMedia()->getUrl()
  61.         );
  62.         $this->getComparisonList($session)->set(
  63.             $productForComparison->id,
  64.             $productForComparison
  65.         );
  66.     }
  67.     public function removeProduct(SessionInterface $sessionstring $productId): void
  68.     {
  69.         $this->getComparisonList($session)->remove($productId);
  70.     }
  71.     /**
  72.      * @throws Exception
  73.      * @throws \Doctrine\DBAL\Exception
  74.      */
  75.     public function getProductCmsSlotData(
  76.         Request $request,
  77.         SalesChannelContext $context
  78.     ) {
  79.         $productKeys $this->convertProductNumbersToIds($request->get('products'''), $context);
  80.         $cmsSlot = new CmsSlotEntity();
  81.         $cmsSlot->setId('manual-product-comparison');
  82.         $cmsSlot->setType('product-comparison');
  83.         $cmsSlot->setSlot('productCompare');
  84.         $cmsSlot->setBlockId('manual-product-comparison-block');
  85.         $cmsSlot->setConfig([
  86.             "productComparisonType" => [
  87.                 "source" => "static",
  88.                 "value" => "variants",
  89.             ],
  90.             "productAssignmentType" => [
  91.                 "source" => "static",
  92.                 "value" => "static",
  93.             ],
  94.             "products" => [
  95.                 "source" => "static",
  96.                 "value" => array_values($productKeys),
  97.             ],
  98.             "productStreamSorting" => [
  99.                 "source" => "static",
  100.                 "value" => "name:ASC",
  101.             ],
  102.             "productStreamLimit" => [
  103.                 "source" => "static",
  104.                 "value" => 10,
  105.             ],
  106.             "productProperties" => [
  107.                 "source" => "static",
  108.                 "value" => $this->getProductProperties($productKeys),
  109.             ],
  110.         ]);
  111.         $cmsSlot->setTranslated([
  112.             'config' => $cmsSlot->getConfig(),
  113.         ]);
  114.         $cmsSlotCollection = new CmsSlotCollection([$cmsSlot]);
  115.         $enrichedCmsSlotCollection $this->cmsSlotsDataResolver->resolve(
  116.             $cmsSlotCollection,
  117.             new ResolverContext($context$request)
  118.         );
  119.         return $enrichedCmsSlotCollection->first();
  120.     }
  121.     /**
  122.      * @throws Exception
  123.      * @throws \Doctrine\DBAL\Exception
  124.      */
  125.     private function getProductProperties(array $productKeys): array
  126.     {
  127.         foreach ($productKeys as $key => $value) {
  128.             $productKeys[$key] = Uuid::fromHexToBytes($value);
  129.         }
  130.         return $this->connection->executeQuery(
  131.             <<<SQL
  132.                 SELECT DISTINCT(LOWER(HEX(property_group.id))) AS id
  133.                 FROM property_group
  134.                          LEFT JOIN property_group_option ON property_group_option.property_group_id = property_group.id
  135.                          LEFT JOIN product_property ON product_property.property_group_option_id = property_group_option.id
  136.                 WHERE product_property.product_id IN (:productIds)
  137.             SQL,
  138.             [
  139.                 ':productIds' => $productKeys,
  140.             ],
  141.             [
  142.                 ':productIds' => Connection::PARAM_STR_ARRAY,
  143.             ]
  144.         )->fetchFirstColumn();
  145.     }
  146.     private function convertProductNumbersToIds(string $productNumbersCombinedSalesChannelContext $context): array
  147.     {
  148.         $productNumbers explode(','$productNumbersCombined);
  149.         $criteria = new Criteria();
  150.         $criteria->addFilter(new EqualsAnyFilter('productNumber'$productNumbers));
  151.         $productIds $this->productRepository->searchIds($criteria$context);
  152.         return $productIds->getIds();
  153.     }
  154. }