vendor/shopware/storefront/Page/Product/ProductPageLoader.php line 102

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Storefront\Page\Product;
  3. use Shopware\Core\Content\Category\Exception\CategoryNotFoundException;
  4. use Shopware\Core\Content\Cms\CmsPageEntity;
  5. use Shopware\Core\Content\Cms\DataResolver\CmsSlotsDataResolver;
  6. use Shopware\Core\Content\Cms\DataResolver\ResolverContext\EntityResolverContext;
  7. use Shopware\Core\Content\Cms\SalesChannel\SalesChannelCmsPageRepository;
  8. use Shopware\Core\Content\Product\Exception\ProductNotFoundException;
  9. use Shopware\Core\Content\Product\ProductDefinition;
  10. use Shopware\Core\Content\Product\SalesChannel\SalesChannelProductEntity;
  11. use Shopware\Core\Content\Property\Aggregate\PropertyGroupOption\PropertyGroupOptionCollection;
  12. use Shopware\Core\Framework\DataAbstractionLayer\Exception\InconsistentCriteriaIdsException;
  13. use Shopware\Core\Framework\Feature;
  14. use Shopware\Core\Framework\Routing\Exception\MissingRequestParameterException;
  15. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  16. use Shopware\Storefront\Page\GenericPageLoaderInterface;
  17. use Shopware\Storefront\Page\Product\CrossSelling\CrossSellingLoader;
  18. use Shopware\Storefront\Page\Product\Review\ProductReviewLoader;
  19. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  20. use Symfony\Component\HttpFoundation\Request;
  21. class ProductPageLoader
  22. {
  23.     /**
  24.      * @var GenericPageLoaderInterface
  25.      */
  26.     private $genericLoader;
  27.     /**
  28.      * @var EventDispatcherInterface
  29.      */
  30.     private $eventDispatcher;
  31.     /**
  32.      * @var SalesChannelCmsPageRepository
  33.      */
  34.     private $cmsPageRepository;
  35.     /**
  36.      * @var CmsSlotsDataResolver
  37.      */
  38.     private $slotDataResolver;
  39.     /**
  40.      * @var ProductDefinition
  41.      */
  42.     private $productDefinition;
  43.     /**
  44.      * @var ProductLoader
  45.      */
  46.     private $productLoader;
  47.     /**
  48.      * @var ProductReviewLoader
  49.      */
  50.     private $productReviewLoader;
  51.     /**
  52.      * @var CrossSellingLoader
  53.      */
  54.     private $crossSellingLoader;
  55.     public function __construct(
  56.         GenericPageLoaderInterface $genericLoader,
  57.         EventDispatcherInterface $eventDispatcher,
  58.         SalesChannelCmsPageRepository $cmsPageRepository,
  59.         CmsSlotsDataResolver $slotDataResolver,
  60.         ProductDefinition $productDefinition,
  61.         ProductLoader $productLoader,
  62.         ProductReviewLoader $productReviewLoader,
  63.         CrossSellingLoader $crossSellingLoader
  64.     ) {
  65.         $this->genericLoader $genericLoader;
  66.         $this->eventDispatcher $eventDispatcher;
  67.         $this->cmsPageRepository $cmsPageRepository;
  68.         $this->slotDataResolver $slotDataResolver;
  69.         $this->productDefinition $productDefinition;
  70.         $this->productLoader $productLoader;
  71.         $this->productReviewLoader $productReviewLoader;
  72.         $this->crossSellingLoader $crossSellingLoader;
  73.     }
  74.     /**
  75.      * @throws CategoryNotFoundException
  76.      * @throws InconsistentCriteriaIdsException
  77.      * @throws MissingRequestParameterException
  78.      * @throws ProductNotFoundException
  79.      */
  80.     public function load(Request $requestSalesChannelContext $salesChannelContext): ProductPage
  81.     {
  82.         $page $this->genericLoader->load($request$salesChannelContext);
  83.         $page ProductPage::createFrom($page);
  84.         $productId $request->attributes->get('productId');
  85.         if (!$productId) {
  86.             throw new MissingRequestParameterException('productId''/productId');
  87.         }
  88.         $product $this->productLoader->load($productId$salesChannelContextProductPageCriteriaEvent::class);
  89.         $page->setProduct($product);
  90.         $page->setConfiguratorSettings($product->getConfigurator());
  91.         $request->request->set('parentId'$product->getParentId());
  92.         $reviews $this->productReviewLoader->load($request$salesChannelContext);
  93.         $reviews->setParentId($product->getParentId() ?? $product->getId());
  94.         $page->setReviews($reviews);
  95.         $page->setCrossSellings(
  96.             $this->crossSellingLoader->load($product->getId(), $salesChannelContext)
  97.         );
  98.         /** @var string $cmsPageId */
  99.         $cmsPageId $product->getCmsPageId();
  100.         if (Feature::isActive('FEATURE_NEXT_10078') && $cmsPageId !== null && $cmsPage $this->getCmsPage($cmsPageId$salesChannelContext)) {
  101.             $this->loadSlotData($cmsPage$salesChannelContext$product$request);
  102.             $page->setCmsPage($cmsPage);
  103.         }
  104.         $this->loadOptions($page);
  105.         $this->loadMetaData($page);
  106.         $this->eventDispatcher->dispatch(
  107.             new ProductPageLoadedEvent($page$salesChannelContext$request)
  108.         );
  109.         return $page;
  110.     }
  111.     private function loadOptions(ProductPage $page): void
  112.     {
  113.         $options = new PropertyGroupOptionCollection();
  114.         $optionIds $page->getProduct()->getOptionIds();
  115.         foreach ($page->getConfiguratorSettings() as $group) {
  116.             $groupOptions $group->getOptions();
  117.             if ($groupOptions === null) {
  118.                 continue;
  119.             }
  120.             foreach ($optionIds as $optionId) {
  121.                 if ($groupOptions->has($optionId)) {
  122.                     $options->add($groupOptions->get($optionId));
  123.                 }
  124.             }
  125.         }
  126.         $page->setSelectedOptions($options);
  127.     }
  128.     private function loadMetaData(ProductPage $page): void
  129.     {
  130.         $metaInformation $page->getMetaInformation();
  131.         $metaDescription $page->getProduct()->getTranslation('metaDescription')
  132.             ?? $page->getProduct()->getTranslation('description');
  133.         $metaInformation->setMetaDescription((string) $metaDescription);
  134.         $metaInformation->setMetaKeywords((string) $page->getProduct()->getTranslation('keywords'));
  135.         if ((string) $page->getProduct()->getTranslation('metaTitle') !== '') {
  136.             $metaInformation->setMetaTitle((string) $page->getProduct()->getTranslation('metaTitle'));
  137.             return;
  138.         }
  139.         $metaTitleParts = [$page->getProduct()->getTranslation('name')];
  140.         foreach ($page->getSelectedOptions() as $option) {
  141.             $metaTitleParts[] = $option->getTranslation('name');
  142.         }
  143.         $metaTitleParts[] = $page->getProduct()->getProductNumber();
  144.         $metaInformation->setMetaTitle(implode(' | '$metaTitleParts));
  145.     }
  146.     private function loadSlotData(
  147.         CmsPageEntity $page,
  148.         SalesChannelContext $salesChannelContext,
  149.         SalesChannelProductEntity $product,
  150.         Request $request
  151.     ): void {
  152.         if (!$page->getSections()) {
  153.             return;
  154.         }
  155.         $resolverContext = new EntityResolverContext($salesChannelContext$request$this->productDefinition$product);
  156.         foreach ($page->getSections() as $section) {
  157.             $slots $this->slotDataResolver->resolve($section->getBlocks()->getSlots(), $resolverContext);
  158.             $section->getBlocks()->setSlots($slots);
  159.         }
  160.     }
  161.     private function getCmsPage(string $cmsPageIdSalesChannelContext $context): ?CmsPageEntity
  162.     {
  163.         $pages $this->cmsPageRepository->read([$cmsPageId], $context);
  164.         if ($pages->count() === 0) {
  165.             return null;
  166.         }
  167.         /** @var CmsPageEntity $page */
  168.         $page $pages->first();
  169.         return $page;
  170.     }
  171. }