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

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\Product\Aggregate\ProductMedia\ProductMediaCollection;
  5. use Shopware\Core\Content\Product\Aggregate\ProductMedia\ProductMediaEntity;
  6. use Shopware\Core\Content\Product\Exception\ProductNotFoundException;
  7. use Shopware\Core\Content\Product\SalesChannel\CrossSelling\AbstractProductCrossSellingRoute;
  8. use Shopware\Core\Content\Product\SalesChannel\Detail\AbstractProductDetailRoute;
  9. use Shopware\Core\Content\Product\SalesChannel\SalesChannelProductEntity;
  10. use Shopware\Core\Content\Property\Aggregate\PropertyGroupOption\PropertyGroupOptionCollection;
  11. use Shopware\Core\Content\Property\PropertyGroupCollection;
  12. use Shopware\Core\Framework\DataAbstractionLayer\Exception\InconsistentCriteriaIdsException;
  13. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  14. use Shopware\Core\Framework\Feature;
  15. use Shopware\Core\Framework\Log\Package;
  16. use Shopware\Core\Framework\Routing\Exception\MissingRequestParameterException;
  17. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  18. use Shopware\Storefront\Page\GenericPageLoaderInterface;
  19. use Shopware\Storefront\Page\Product\Review\ProductReviewLoader;
  20. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  21. use Symfony\Component\HttpFoundation\Request;
  22. #[Package('storefront')]
  23. class ProductPageLoader
  24. {
  25.     private GenericPageLoaderInterface $genericLoader;
  26.     private EventDispatcherInterface $eventDispatcher;
  27.     private AbstractProductDetailRoute $productDetailRoute;
  28.     private ProductReviewLoader $productReviewLoader;
  29.     private AbstractProductCrossSellingRoute $crossSellingRoute;
  30.     /**
  31.      * @internal
  32.      */
  33.     public function __construct(
  34.         GenericPageLoaderInterface $genericLoader,
  35.         EventDispatcherInterface $eventDispatcher,
  36.         AbstractProductDetailRoute $productDetailRoute,
  37.         ProductReviewLoader $productReviewLoader,
  38.         AbstractProductCrossSellingRoute $crossSellingRoute
  39.     ) {
  40.         $this->genericLoader $genericLoader;
  41.         $this->eventDispatcher $eventDispatcher;
  42.         $this->productDetailRoute $productDetailRoute;
  43.         $this->productReviewLoader $productReviewLoader;
  44.         $this->crossSellingRoute $crossSellingRoute;
  45.     }
  46.     /**
  47.      * @throws CategoryNotFoundException
  48.      * @throws InconsistentCriteriaIdsException
  49.      * @throws MissingRequestParameterException
  50.      * @throws ProductNotFoundException
  51.      */
  52.     public function load(Request $requestSalesChannelContext $context): ProductPage
  53.     {
  54.         $productId $request->attributes->get('productId');
  55.         if (!$productId) {
  56.             throw new MissingRequestParameterException('productId''/productId');
  57.         }
  58.         $criteria = (new Criteria())
  59.             ->addAssociation('manufacturer.media')
  60.             ->addAssociation('options.group')
  61.             ->addAssociation('properties.group')
  62.             ->addAssociation('mainCategories.category')
  63.             ->addAssociation('media');
  64.         $this->eventDispatcher->dispatch(new ProductPageCriteriaEvent($productId$criteria$context));
  65.         $result $this->productDetailRoute->load($productId$request$context$criteria);
  66.         $product $result->getProduct();
  67.         if ($product->getMedia()) {
  68.             $product->getMedia()->sort(function (ProductMediaEntity $aProductMediaEntity $b) {
  69.                 return $a->getPosition() <=> $b->getPosition();
  70.             });
  71.         }
  72.         if ($product->getMedia() && $product->getCover()) {
  73.             $product->setMedia(new ProductMediaCollection(array_merge(
  74.                 [$product->getCover()->getId() => $product->getCover()],
  75.                 $product->getMedia()->getElements()
  76.             )));
  77.         }
  78.         if ($category $product->getSeoCategory()) {
  79.             $request->request->set('navigationId'$category->getId());
  80.         }
  81.         $page $this->genericLoader->load($request$context);
  82.         /** @var ProductPage $page */
  83.         $page ProductPage::createFrom($page);
  84.         $page->setProduct($product);
  85.         $page->setConfiguratorSettings($result->getConfigurator() ?? new PropertyGroupCollection());
  86.         $page->setNavigationId($product->getId());
  87.         if (!Feature::isActive('v6.5.0.0')) {
  88.             $this->loadDefaultAdditions($product$page$request$context);
  89.         } elseif ($cmsPage $product->getCmsPage()) {
  90.             $page->setCmsPage($cmsPage);
  91.         }
  92.         $this->loadOptions($page);
  93.         $this->loadMetaData($page);
  94.         $this->eventDispatcher->dispatch(
  95.             new ProductPageLoadedEvent($page$context$request)
  96.         );
  97.         return $page;
  98.     }
  99.     private function loadOptions(ProductPage $page): void
  100.     {
  101.         $options = new PropertyGroupOptionCollection();
  102.         if (($optionIds $page->getProduct()->getOptionIds()) === null) {
  103.             $page->setSelectedOptions($options);
  104.             return;
  105.         }
  106.         foreach ($page->getConfiguratorSettings() as $group) {
  107.             $groupOptions $group->getOptions();
  108.             if ($groupOptions === null) {
  109.                 continue;
  110.             }
  111.             foreach ($optionIds as $optionId) {
  112.                 $groupOption $groupOptions->get($optionId);
  113.                 if ($groupOption !== null) {
  114.                     $options->add($groupOption);
  115.                 }
  116.             }
  117.         }
  118.         $page->setSelectedOptions($options);
  119.     }
  120.     private function loadMetaData(ProductPage $page): void
  121.     {
  122.         $metaInformation $page->getMetaInformation();
  123.         if (!$metaInformation) {
  124.             return;
  125.         }
  126.         $metaDescription $page->getProduct()->getTranslation('metaDescription')
  127.             ?? $page->getProduct()->getTranslation('description');
  128.         $metaInformation->setMetaDescription((string) $metaDescription);
  129.         $metaInformation->setMetaKeywords((string) $page->getProduct()->getTranslation('keywords'));
  130.         if ((string) $page->getProduct()->getTranslation('metaTitle') !== '') {
  131.             $metaInformation->setMetaTitle((string) $page->getProduct()->getTranslation('metaTitle'));
  132.             return;
  133.         }
  134.         $metaTitleParts = [$page->getProduct()->getTranslation('name')];
  135.         foreach ($page->getSelectedOptions() as $option) {
  136.             $metaTitleParts[] = $option->getTranslation('name');
  137.         }
  138.         $metaTitleParts[] = $page->getProduct()->getProductNumber();
  139.         $metaInformation->setMetaTitle(implode(' | '$metaTitleParts));
  140.     }
  141.     /**
  142.      * @@deprecated tag:v6.5.0 - will be removed because cms page id will always be set
  143.      */
  144.     private function loadDefaultAdditions(SalesChannelProductEntity $productProductPage $pageRequest $requestSalesChannelContext $context): void
  145.     {
  146.         if ($cmsPage $product->getCmsPage()) {
  147.             $page->setCmsPage($cmsPage);
  148.             return;
  149.         }
  150.         $request->request->set('parentId'$product->getParentId());
  151.         $reviews $this->productReviewLoader->load($request$context);
  152.         $reviews->setParentId($product->getParentId() ?? $product->getId());
  153.         $page->setReviews($reviews);
  154.         $crossSellings $this->crossSellingRoute->load($product->getId(), new Request(), $context, new Criteria());
  155.         $page->setCrossSellings($crossSellings->getResult());
  156.     }
  157. }