custom/plugins/EmcgnStandardCmsPages/src/Core/Content/Product/EmcgnProductDetailRoute.php line 100

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace EmcgnStandardCmsPages\Core\Content\Product;
  3. use Shopware\Core\Content\Category\Service\CategoryBreadcrumbBuilder;
  4. use Shopware\Core\Content\Cms\DataResolver\ResolverContext\EntityResolverContext;
  5. use Shopware\Core\Content\Cms\SalesChannel\SalesChannelCmsPageLoaderInterface;
  6. use Shopware\Core\Content\Product\Aggregate\ProductVisibility\ProductVisibilityDefinition;
  7. use Shopware\Core\Content\Product\Exception\ProductNotFoundException;
  8. use Shopware\Core\Content\Product\SalesChannel\Detail\AbstractProductDetailRoute;
  9. use Shopware\Core\Content\Product\SalesChannel\Detail\ProductConfiguratorLoader;
  10. use Shopware\Core\Content\Product\SalesChannel\Detail\ProductDetailRouteResponse;
  11. use Shopware\Core\Content\Product\SalesChannel\ProductAvailableFilter;
  12. use Shopware\Core\Content\Product\SalesChannel\ProductCloseoutFilter;
  13. use Shopware\Core\Content\Product\SalesChannel\SalesChannelProductDefinition;
  14. use Shopware\Core\Content\Product\SalesChannel\SalesChannelProductEntity;
  15. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
  16. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  17. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsAnyFilter;
  18. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  19. use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting;
  20. use Shopware\Core\Framework\Plugin\Exception\DecorationPatternException;
  21. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  22. use Shopware\Core\System\SystemConfig\SystemConfigService;
  23. use Symfony\Component\DependencyInjection\Container;
  24. use Symfony\Component\HttpFoundation\Request;
  25. class EmcgnProductDetailRoute extends AbstractProductDetailRoute
  26. {
  27.     private Container $container;
  28.     private SystemConfigService $config;
  29.     private ProductConfiguratorLoader $configuratorLoader;
  30.     private CategoryBreadcrumbBuilder $breadcrumbBuilder;
  31.     private SalesChannelCmsPageLoaderInterface $cmsPageLoader;
  32.     private SalesChannelProductDefinition $productDefinition;
  33.     private EntityRepository $entityRepository;
  34.     public function __construct(
  35.         Container $container,
  36.         SystemConfigService $config,
  37.         ProductConfiguratorLoader $configuratorLoader,
  38.         CategoryBreadcrumbBuilder $breadcrumbBuilder,
  39.         SalesChannelCmsPageLoaderInterface $cmsPageLoader,
  40.         SalesChannelProductDefinition $productDefinition,
  41.         EntityRepository $entityRepository
  42.     ) {
  43.         $this->container $container;
  44.         $this->config $config;
  45.         $this->configuratorLoader $configuratorLoader;
  46.         $this->breadcrumbBuilder $breadcrumbBuilder;
  47.         $this->cmsPageLoader $cmsPageLoader;
  48.         $this->productDefinition $productDefinition;
  49.         $this->entityRepository $entityRepository;
  50.         $this->productRepository $this->container->get('sales_channel.product.repository');
  51.     }
  52.     public function getDecorated(): AbstractProductDetailRoute
  53.     {
  54.         throw new DecorationPatternException(self::class);
  55.     }
  56.     public function load(string $productIdRequest $requestSalesChannelContext $contextCriteria $criteria): ProductDetailRouteResponse
  57.     {
  58.         $productId $this->findBestVariant($productId$context);
  59.         $this->addFilters($context$criteria);
  60.         $criteria->setIds([$productId]);
  61.         $product $this->productRepository
  62.             ->search($criteria$context)
  63.             ->first();
  64.         if (!$product instanceof SalesChannelProductEntity) {
  65.             throw new ProductNotFoundException($productId);
  66.         }
  67.         $product->setSeoCategory(
  68.             $this->breadcrumbBuilder->getProductSeoCategory($product$context)
  69.         );
  70.         $configurator $this->configuratorLoader->load($product$context);
  71.         $pageId $product->getCmsPageId();
  72.         if ($pageId) {
  73.             $this->setCmsPage($request$pageId$context$product);
  74.         } else {
  75.             $pageId $this->config->get('EmcgnStandardCmsPages.config.selectedCmsProductPage');
  76.             if (!empty($pageId)) {
  77.                 $frameworkContext $context->getContext();
  78.                 $cmsPage $this->entityRepository->search(new Criteria([$pageId]), $frameworkContext)->first();
  79.                 if (!empty($cmsPage)) {
  80.                     $cmsType $cmsPage->getType();
  81.                     if($cmsType == 'product_detail') {
  82.                         $this->setCmsPage($request$pageId$context$product);
  83.                     }
  84.                 }
  85.             }
  86.         }
  87.         return new ProductDetailRouteResponse($product$configurator);
  88.     }
  89.     /**
  90.      * @param string $productId
  91.      * @param SalesChannelContext $context
  92.      * @return string
  93.      */
  94.     private function findBestVariant(string $productIdSalesChannelContext $context): string
  95.     {
  96.         $criteria = (new Criteria())
  97.             ->addFilter(new EqualsFilter('product.parentId'$productId))
  98.             ->addSorting(new FieldSorting('product.price'))
  99.             ->addSorting(new FieldSorting('product.available'))
  100.             ->setLimit(1);
  101.         $variantId $this->productRepository->searchIds($criteria$context);
  102.         return $variantId->firstId() ?? $productId;
  103.     }
  104.     /**
  105.      * @param SalesChannelContext $context
  106.      * @param Criteria $criteria
  107.      */
  108.     private function addFilters(SalesChannelContext $contextCriteria $criteria): void
  109.     {
  110.         $criteria->addFilter(
  111.             new ProductAvailableFilter($context->getSalesChannel()->getId(), ProductVisibilityDefinition::VISIBILITY_LINK)
  112.         );
  113.         $salesChannelId $context->getSalesChannel()->getId();
  114.         $hideCloseoutProductsWhenOutOfStock $this->config->get('core.listing.hideCloseoutProductsWhenOutOfStock'$salesChannelId);
  115.         if ($hideCloseoutProductsWhenOutOfStock) {
  116.             $filter = new ProductCloseoutFilter();
  117.             $filter->addQuery(new EqualsFilter('product.parentId'null));
  118.             $criteria->addFilter($filter);
  119.         }
  120.     }
  121.     /**
  122.      * @param $request
  123.      * @param $pageId
  124.      * @param $context
  125.      * @param $product
  126.      */
  127.     private function setCmsPage($request$pageId$context$product)
  128.     {
  129.         $resolverContext = new EntityResolverContext($context$request$this->productDefinition, clone $product);
  130.         $pages $this->cmsPageLoader->load(
  131.             $request,
  132.             $this->createCriteria($pageId$request),
  133.             $context,
  134.             $product->getTranslation('slotConfig'),
  135.             $resolverContext
  136.         );
  137.         if ($page $pages->first()) {
  138.             $product->setCmsPage($page);
  139.         }
  140.     }
  141.     /**
  142.      * @param string $pageId
  143.      * @param Request $request
  144.      * @return Criteria
  145.      */
  146.     private function createCriteria(string $pageIdRequest $request): Criteria
  147.     {
  148.         $criteria = new Criteria([$pageId]);
  149.         $criteria->setTitle('product::cms-page');
  150.         $slots $request->get('slots');
  151.         if (\is_string($slots)) {
  152.             $slots explode('|'$slots);
  153.         }
  154.         if (!empty($slots) && \is_array($slots)) {
  155.             $criteria
  156.                 ->getAssociation('sections.blocks')
  157.                 ->addFilter(new EqualsAnyFilter('slots.id'$slots));
  158.         }
  159.         return $criteria;
  160.     }
  161. }