custom/plugins/HyBuys/src/Controller/ProductController.php line 92

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace HyBuys\Main\Controller;
  3. use Shopware\Core\Content\Product\Exception\ProductNotFoundException;
  4. use Shopware\Core\Content\Product\Exception\ReviewNotActiveExeption;
  5. use Shopware\Core\Content\Product\Exception\VariantNotFoundException;
  6. use Shopware\Core\Content\Product\SalesChannel\FindVariant\FindProductVariantRoute;
  7. use Shopware\Core\Content\Product\SalesChannel\Review\AbstractProductReviewSaveRoute;
  8. use Shopware\Core\Content\Seo\SeoUrlPlaceholderHandlerInterface;
  9. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  10. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  11. use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting;
  12. use Shopware\Core\Framework\Feature;
  13. use Shopware\Core\Framework\Routing\Annotation\LoginRequired;
  14. use Shopware\Core\Framework\Routing\Annotation\RouteScope;
  15. use Shopware\Core\Framework\Routing\Annotation\Since;
  16. use Shopware\Core\Framework\Validation\DataBag\RequestDataBag;
  17. use Shopware\Core\Framework\Validation\Exception\ConstraintViolationException;
  18. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  19. use Shopware\Core\System\SystemConfig\SystemConfigService;
  20. use Shopware\Storefront\Controller\StorefrontController;
  21. use Shopware\Storefront\Framework\Cache\Annotation\HttpCache;
  22. use Shopware\Storefront\Framework\Routing\RequestTransformer;
  23. use Shopware\Storefront\Page\Product\Configurator\ProductCombinationFinder;
  24. use Shopware\Storefront\Page\Product\ProductPageLoadedHook;
  25. use Shopware\Storefront\Page\Product\ProductPageLoader;
  26. use Shopware\Storefront\Page\Product\QuickView\MinimalQuickViewPageLoader;
  27. use Shopware\Storefront\Page\Product\QuickView\ProductQuickViewWidgetLoadedHook;
  28. use Shopware\Storefront\Page\Product\Review\ProductReviewLoader;
  29. use Shopware\Storefront\Page\Product\Review\ProductReviewsWidgetLoadedHook;
  30. use Symfony\Component\HttpFoundation\JsonResponse;
  31. use Symfony\Component\HttpFoundation\Request;
  32. use Symfony\Component\HttpFoundation\Response;
  33. use Symfony\Component\HttpKernel\EventListener\AbstractSessionListener;
  34. use Symfony\Component\Routing\Annotation\Route;
  35. /**
  36.  * @Route(defaults={"_routeScope"={"storefront"}})
  37.  *
  38.  * @deprecated tag:v6.5.0 - reason:becomes-internal - Will be internal
  39.  */
  40. class ProductController extends StorefrontController
  41. {
  42.     private ProductPageLoader $productPageLoader;
  43.     private FindProductVariantRoute $findVariantRoute;
  44.     private MinimalQuickViewPageLoader $minimalQuickViewPageLoader;
  45.     private SeoUrlPlaceholderHandlerInterface $seoUrlPlaceholderHandler;
  46.     private ProductReviewLoader $productReviewLoader;
  47.     private SystemConfigService $systemConfigService;
  48.     private AbstractProductReviewSaveRoute $productReviewSaveRoute;
  49.     /**
  50.      * @deprecated tag:v6.5.0 - will be removed
  51.      */
  52.     private ProductCombinationFinder $productCombinationFinder;
  53.     /**
  54.      * @internal
  55.      */
  56.     public function __construct(
  57.         ProductPageLoader $productPageLoader,
  58.         ProductCombinationFinder $productCombinationFinder,
  59.         FindProductVariantRoute $findVariantRoute,
  60.         MinimalQuickViewPageLoader $minimalQuickViewPageLoader,
  61.         AbstractProductReviewSaveRoute $productReviewSaveRoute,
  62.         SeoUrlPlaceholderHandlerInterface $seoUrlPlaceholderHandler,
  63.         ProductReviewLoader $productReviewLoader,
  64.         SystemConfigService $systemConfigService
  65.     ) {
  66.         $this->productPageLoader $productPageLoader;
  67.         $this->findVariantRoute $findVariantRoute;
  68.         $this->minimalQuickViewPageLoader $minimalQuickViewPageLoader;
  69.         $this->seoUrlPlaceholderHandler $seoUrlPlaceholderHandler;
  70.         $this->productReviewLoader $productReviewLoader;
  71.         $this->systemConfigService $systemConfigService;
  72.         $this->productReviewSaveRoute $productReviewSaveRoute;
  73.         $this->productCombinationFinder $productCombinationFinder;
  74.     }
  75.     /**
  76.      * @Since("6.3.3.0")
  77.      * @HttpCache()
  78.      * @Route("/detail/{productId}", name="frontend.detail.page", methods={"GET"})
  79.      */
  80.     public function index(SalesChannelContext $contextRequest $request): Response
  81.     {
  82.         $page $this->productPageLoader->load($request$context);
  83.         $this->hook(new ProductPageLoadedHook($page$context));
  84.         $ratingSuccess $request->get('success');
  85.         $this->productsNew $this->container->get('sales_channel.product.repository');
  86.         $latest_products_criteria = new Criteria();
  87.         $latest_products_criteria->addFilter(new EqualsFilter('active'true));
  88.         $latest_products_criteria->addSorting(new FieldSorting('createdAt''DESC'));
  89.         $latest_products_criteria->setLimit(8);
  90.         $latest_products $this->productsNew->search(
  91.             $latest_products_criteria,
  92.             $context
  93.         );
  94.         /**
  95.          * @deprecated tag:v6.5.0 - remove complete if statement, cms page id is always set
  96.          *
  97.          * Fallback layout for non-assigned product layout
  98.          */
  99.         if (!$page->getCmsPage()) {
  100.             Feature::throwException('v6.5.0.0''Fallback will be removed because cms page is always set in subscriber.');
  101.             return $this->renderStorefront('@Storefront/storefront/page/product-detail/index.html.twig', [
  102.                 'page' => $page,
  103.                 'latest_products' => $latest_products,
  104.                 'ratingSuccess' => $ratingSuccess
  105.             ]);
  106.         }
  107.         return $this->renderStorefront('@Storefront/storefront/page/content/product-detail.html.twig', ['page' => $page]);
  108.     }
  109.     /**
  110.      * @Since("6.0.0.0")
  111.      * @HttpCache()
  112.      * @Route("/detail/{productId}/switch", name="frontend.detail.switch", methods={"GET"}, defaults={"XmlHttpRequest": true})
  113.      */
  114.     public function switch(string $productIdRequest $requestSalesChannelContext $salesChannelContext): JsonResponse
  115.     {
  116.         $switchedGroup $request->query->has('switched') ? (string) $request->query->get('switched') : null;
  117.         /** @var array<mixed>|null $options */
  118.         $options json_decode($request->query->get('options'''), true);
  119.         try {
  120.             if (Feature::isActive('v6.5.0.0')) {
  121.                 $variantResponse $this->findVariantRoute->load(
  122.                     $productId,
  123.                     new Request(
  124.                         [
  125.                             'switchedGroup' => $switchedGroup,
  126.                             'options' => $options ?? [],
  127.                         ]
  128.                     ),
  129.                     $salesChannelContext
  130.                 );
  131.                 $productId $variantResponse->getFoundCombination()->getVariantId();
  132.             } else {
  133.                 $finderResponse $this->productCombinationFinder->find(
  134.                     $productId,
  135.                     $switchedGroup,
  136.                     $options ?? [],
  137.                     $salesChannelContext
  138.                 );
  139.                 $productId $finderResponse->getVariantId();
  140.             }
  141.         } catch (VariantNotFoundException|ProductNotFoundException $productNotFoundException) {
  142.             //nth
  143.         }
  144.         $host $request->attributes->get(RequestTransformer::SALES_CHANNEL_ABSOLUTE_BASE_URL)
  145.             . $request->attributes->get(RequestTransformer::SALES_CHANNEL_BASE_URL);
  146.         $url $this->seoUrlPlaceholderHandler->replace(
  147.             $this->seoUrlPlaceholderHandler->generate(
  148.                 'frontend.detail.page',
  149.                 ['productId' => $productId]
  150.             ),
  151.             $host,
  152.             $salesChannelContext
  153.         );
  154.         $response = new JsonResponse([
  155.             'url' => $url,
  156.             'productId' => $productId,
  157.         ]);
  158.         $response->headers->set(AbstractSessionListener::NO_AUTO_CACHE_CONTROL_HEADER'1');
  159.         return $response;
  160.     }
  161.     /**
  162.      * @Since("6.0.0.0")
  163.      * @Route("/quickview/{productId}", name="widgets.quickview.minimal", methods={"GET"}, defaults={"XmlHttpRequest": true})
  164.      */
  165.     public function quickviewMinimal(Request $requestSalesChannelContext $context): Response
  166.     {
  167.         $page $this->minimalQuickViewPageLoader->load($request$context);
  168.         $this->hook(new ProductQuickViewWidgetLoadedHook($page$context));
  169.         return $this->renderStorefront('@Storefront/storefront/component/product/quickview/minimal.html.twig', ['page' => $page]);
  170.     }
  171.     /**
  172.      * @Since("6.0.0.0")
  173.      * @Route("/product/{productId}/rating", name="frontend.detail.review.save", methods={"POST"}, defaults={"XmlHttpRequest"=true, "_loginRequired"=true})
  174.      */
  175.     public function saveReview(string $productIdRequestDataBag $dataSalesChannelContext $context): Response
  176.     {
  177.         $this->checkReviewsActive($context);
  178.         try {
  179.             $this->productReviewSaveRoute->save($productId$data$context);
  180.         } catch (ConstraintViolationException $formViolations) {
  181.             return $this->forwardToRoute('frontend.product.reviews', [
  182.                 'productId' => $productId,
  183.                 'success' => -1,
  184.                 'formViolations' => $formViolations,
  185.                 'data' => $data,
  186.             ], ['productId' => $productId]);
  187.         }
  188.         $forwardParams = [
  189.             'productId' => $productId,
  190.             'success' => 1,
  191.             'data' => $data,
  192.             'parentId' => $data->get('parentId'),
  193.         ];
  194.         if ($data->has('id')) {
  195.             $forwardParams['success'] = 2;
  196.         }
  197.         return $this->forwardToRoute('frontend.product.reviews'$forwardParams, ['productId' => $productId]);
  198.     }
  199.     /**
  200.      * @Since("6.0.0.0")
  201.      * @Route("/product/{productId}/reviews", name="frontend.product.reviews", methods={"GET","POST"}, defaults={"XmlHttpRequest"=true})
  202.      */
  203.     public function loadReviews(Request $requestRequestDataBag $dataSalesChannelContext $context): Response
  204.     {
  205.         $this->checkReviewsActive($context);
  206.         $reviews $this->productReviewLoader->load($request$context);
  207.         $this->hook(new ProductReviewsWidgetLoadedHook($reviews$context));
  208.         return $this->renderStorefront('storefront/page/product-detail/review/review.html.twig', [
  209.             'reviews' => $reviews,
  210.             'ratingSuccess' => $request->get('success'),
  211.         ]);
  212.     }
  213.     /**
  214.      * @throws ReviewNotActiveExeption
  215.      */
  216.     private function checkReviewsActive(SalesChannelContext $context): void
  217.     {
  218.         $showReview $this->systemConfigService->get('core.listing.showReview'$context->getSalesChannel()->getId());
  219.         if (!$showReview) {
  220.             throw new ReviewNotActiveExeption();
  221.         }
  222.     }
  223. }