custom/static-plugins/CioProductCustomerInputs/src/Storefront/Controller/CheckoutController.php line 130

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace CioProductCustomerInputs\Storefront\Controller;
  4. use Shopware\Core\Checkout\Cart\Cart;
  5. use Shopware\Core\Checkout\Cart\Error\Error;
  6. use Shopware\Core\Checkout\Cart\Error\ErrorCollection;
  7. use Shopware\Core\Checkout\Cart\Exception\InvalidCartException;
  8. use Shopware\Core\Checkout\Cart\SalesChannel\CartService;
  9. use Shopware\Core\Checkout\Customer\SalesChannel\AbstractLogoutRoute;
  10. use Shopware\Core\Checkout\Order\Exception\EmptyCartException;
  11. use Shopware\Core\Checkout\Order\SalesChannel\OrderService;
  12. use Shopware\Core\Checkout\Payment\Exception\InvalidOrderException;
  13. use Shopware\Core\Checkout\Payment\Exception\PaymentProcessException;
  14. use Shopware\Core\Checkout\Payment\Exception\UnknownPaymentMethodException;
  15. use Shopware\Core\Checkout\Payment\PaymentService;
  16. use Shopware\Core\Framework\Feature;
  17. use Shopware\Core\Framework\Log\Package;
  18. use Shopware\Core\Framework\Routing\Annotation\RouteScope;
  19. use Shopware\Core\Framework\Routing\Annotation\Since;
  20. use Shopware\Core\Framework\Validation\DataBag\RequestDataBag;
  21. use Shopware\Core\Framework\Validation\Exception\ConstraintViolationException;
  22. use Shopware\Core\Profiling\Profiler;
  23. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  24. use Shopware\Core\System\SystemConfig\SystemConfigService;
  25. use Shopware\Storefront\Checkout\Cart\Error\PaymentMethodChangedError;
  26. use Shopware\Storefront\Checkout\Cart\Error\ShippingMethodChangedError;
  27. use Shopware\Storefront\Controller\StorefrontController;
  28. use Shopware\Storefront\Framework\AffiliateTracking\AffiliateTrackingListener;
  29. use Shopware\Storefront\Framework\Routing\Annotation\NoStore;
  30. use Shopware\Storefront\Page\Checkout\Cart\CheckoutCartPageLoadedHook;
  31. use Shopware\Storefront\Page\Checkout\Cart\CheckoutCartPageLoader;
  32. use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedHook;
  33. use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoader;
  34. use Shopware\Storefront\Page\Checkout\Finish\CheckoutFinishPageLoadedHook;
  35. use Shopware\Storefront\Page\Checkout\Finish\CheckoutFinishPageLoader;
  36. use Shopware\Storefront\Page\Checkout\Offcanvas\CheckoutInfoWidgetLoadedHook;
  37. use Shopware\Storefront\Page\Checkout\Offcanvas\CheckoutOffcanvasWidgetLoadedHook;
  38. use Shopware\Storefront\Page\Checkout\Offcanvas\OffcanvasCartPageLoader;
  39. use Symfony\Component\HttpFoundation\RedirectResponse;
  40. use Symfony\Component\HttpFoundation\Request;
  41. use Symfony\Component\HttpFoundation\Response;
  42. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  43. use Symfony\Component\Routing\Annotation\Route;
  44. /**
  45.  * @Route(defaults={"_routeScope"={"storefront"}})
  46.  *
  47.  * @deprecated tag:v6.5.0 - reason:becomes-internal - Will be internal
  48.  */
  49. #[Package('storefront')]
  50. class CheckoutController extends StorefrontController
  51. {
  52.     private const REDIRECTED_FROM_SAME_ROUTE 'redirected';
  53.     private CartService $cartService;
  54.     private CheckoutCartPageLoader $cartPageLoader;
  55.     private CheckoutConfirmPageLoader $confirmPageLoader;
  56.     private CheckoutFinishPageLoader $finishPageLoader;
  57.     private OrderService $orderService;
  58.     private PaymentService $paymentService;
  59.     private OffcanvasCartPageLoader $offcanvasCartPageLoader;
  60.     private SystemConfigService $config;
  61.     private AbstractLogoutRoute $logoutRoute;
  62.     /**
  63.      * @internal
  64.      */
  65.     public function __construct(
  66.         CartService $cartService,
  67.         CheckoutCartPageLoader $cartPageLoader,
  68.         CheckoutConfirmPageLoader $confirmPageLoader,
  69.         CheckoutFinishPageLoader $finishPageLoader,
  70.         OrderService $orderService,
  71.         PaymentService $paymentService,
  72.         OffcanvasCartPageLoader $offcanvasCartPageLoader,
  73.         SystemConfigService $config,
  74.         AbstractLogoutRoute $logoutRoute
  75.     ) {
  76.         $this->cartService $cartService;
  77.         $this->cartPageLoader $cartPageLoader;
  78.         $this->confirmPageLoader $confirmPageLoader;
  79.         $this->finishPageLoader $finishPageLoader;
  80.         $this->orderService $orderService;
  81.         $this->paymentService $paymentService;
  82.         $this->offcanvasCartPageLoader $offcanvasCartPageLoader;
  83.         $this->config $config;
  84.         $this->logoutRoute $logoutRoute;
  85.     }
  86.     /**
  87.      * @Since("6.0.0.0")
  88.      * @NoStore
  89.      * @Route("/checkout/cart", name="frontend.checkout.cart.page", options={"seo"="false"}, methods={"GET"})
  90.      */
  91.     public function cartPage(Request $requestSalesChannelContext $context): Response
  92.     {
  93.         $page $this->cartPageLoader->load($request$context);
  94.         $cart $page->getCart();
  95.         $cartErrors $cart->getErrors();
  96.         $this->hook(new CheckoutCartPageLoadedHook($page$context));
  97.         $this->addCartErrors($cart);
  98.         if (!$request->query->getBoolean(self::REDIRECTED_FROM_SAME_ROUTE) && $this->routeNeedsReload($cartErrors)) {
  99.             $cartErrors->clear();
  100.             // To prevent redirect loops add the identifier that the request already got redirected from the same origin
  101.             return $this->redirectToRoute(
  102.                 'frontend.checkout.cart.page',
  103.                 \array_merge(
  104.                     $request->query->all(),
  105.                     [self::REDIRECTED_FROM_SAME_ROUTE => true]
  106.                 ),
  107.             );
  108.         }
  109.         $cartErrors->clear();
  110.         return $this->renderStorefront('@Storefront/storefront/page/checkout/cart/index.html.twig', ['page' => $page]);
  111.     }
  112.     /**
  113.      * @Since("6.0.0.0")
  114.      * @NoStore
  115.      * @Route("/checkout/confirm", name="frontend.checkout.confirm.page", options={"seo"="false"}, methods={"GET"}, defaults={"XmlHttpRequest"=true})
  116.      */
  117.     public function confirmPage(Request $requestSalesChannelContext $context): Response
  118.     {
  119.         if (!$context->getCustomer()) {
  120.             return $this->redirectToRoute('frontend.account.login.page');
  121.         }
  122.         if ($this->cartService->getCart($context->getToken(), $context)->getLineItems()->count() === 0) {
  123.             return $this->redirectToRoute('frontend.checkout.cart.page');
  124.         }
  125.         $page $this->confirmPageLoader->load($request$context);
  126.         $cart $page->getCart();
  127.         $cartErrors $cart->getErrors();
  128.         $this->hook(new CheckoutConfirmPageLoadedHook($page$context));
  129.         $this->addCartErrors($cart);
  130.         if (!$request->query->getBoolean(self::REDIRECTED_FROM_SAME_ROUTE) && $this->routeNeedsReload($cartErrors)) {
  131.             $cartErrors->clear();
  132.             // To prevent redirect loops add the identifier that the request already got redirected from the same origin
  133.             return $this->redirectToRoute(
  134.                 'frontend.checkout.confirm.page',
  135.                 \array_merge(
  136.                     $request->query->all(),
  137.                     [self::REDIRECTED_FROM_SAME_ROUTE => true]
  138.                 ),
  139.             );
  140.         }
  141.         return $this->renderStorefront('@Storefront/storefront/page/checkout/confirm/index.html.twig', ['page' => $page]);
  142.     }
  143.     /**
  144.      * @Since("6.0.0.0")
  145.      * @Route("/checkout/finish", name="frontend.checkout.finish.page", options={"seo"="false"}, methods={"GET"})
  146.      * @NoStore
  147.      */
  148.     public function finishPage(Request $requestSalesChannelContext $contextRequestDataBag $dataBag): Response
  149.     {
  150.         if ($context->getCustomer() === null) {
  151.             return $this->redirectToRoute('frontend.account.login.page');
  152.         }
  153.         $page $this->finishPageLoader->load($request$context);
  154.         $this->hook(new CheckoutFinishPageLoadedHook($page$context));
  155.         if ($page->isPaymentFailed() === true) {
  156.             return $this->redirectToRoute(
  157.                 'frontend.account.edit-order.page',
  158.                 [
  159.                     'orderId' => $request->get('orderId'),
  160.                     'error-code' => 'CHECKOUT__UNKNOWN_ERROR',
  161.                 ]
  162.             );
  163.         }
  164.         if ($context->getCustomer()->getGuest() && $this->config->get('core.cart.logoutGuestAfterCheckout'$context->getSalesChannelId())) {
  165.             $this->logoutRoute->logout($context$dataBag);
  166.         }
  167.         return $this->renderStorefront('@Storefront/storefront/page/checkout/finish/index.html.twig', ['page' => $page]);
  168.     }
  169.     /**
  170.      * @Since("6.0.0.0")
  171.      * @Route("/checkout/order", name="frontend.checkout.finish.order", options={"seo"="false"}, methods={"POST"})
  172.      */
  173.     public function order(RequestDataBag $dataSalesChannelContext $contextRequest $request): Response
  174.     {
  175.         if (!$context->getCustomer()) {
  176.             return $this->redirectToRoute('frontend.account.login.page');
  177.         }
  178.         try {
  179.             $this->addAffiliateTracking($data$request->getSession());
  180.             $orderId Profiler::trace('checkout-order', function () use ($data$context) {
  181.                 return $this->orderService->createOrder($data$context);
  182.             });
  183.         } catch (ConstraintViolationException $formViolations) {
  184.             return $this->forwardToRoute('frontend.checkout.confirm.page', ['formViolations' => $formViolations]);
  185.         } catch (InvalidCartException Error EmptyCartException $error) {
  186.             $this->addCartErrors(
  187.                 $this->cartService->getCart($context->getToken(), $context)
  188.             );
  189.             return $this->forwardToRoute('frontend.checkout.confirm.page');
  190.         }
  191.         try {
  192.             $finishUrl $this->generateUrl('frontend.checkout.finish.page', ['orderId' => $orderId]);
  193.             $errorUrl $this->generateUrl('frontend.account.edit-order.page', ['orderId' => $orderId]);
  194.             $response Profiler::trace('handle-payment', function () use ($orderId$data$context$finishUrl$errorUrl): ?RedirectResponse {
  195.                 return $this->paymentService->handlePaymentByOrder($orderId$data$context$finishUrl$errorUrl);
  196.             });
  197.             return $response ?? new RedirectResponse($finishUrl);
  198.         } catch (PaymentProcessException InvalidOrderException UnknownPaymentMethodException $e) {
  199.             return $this->forwardToRoute('frontend.checkout.finish.page', ['orderId' => $orderId'changedPayment' => false'paymentFailed' => true]);
  200.         }
  201.     }
  202.     /**
  203.      * @Since("6.0.0.0")
  204.      * @Route("/widgets/checkout/info", name="frontend.checkout.info", methods={"GET"}, defaults={"XmlHttpRequest"=true})
  205.      */
  206.     public function info(Request $requestSalesChannelContext $context): Response
  207.     {
  208.         $cart $this->cartService->getCart($context->getToken(), $context);
  209.         if ($cart->getLineItems()->count() <= 0
  210.             && (Feature::isActive('v6.5.0.0') || Feature::isActive('PERFORMANCE_TWEAKS'))
  211.         ) {
  212.             return new Response(nullResponse::HTTP_NO_CONTENT);
  213.         }
  214.         $page $this->offcanvasCartPageLoader->load($request$context);
  215.         $this->hook(new CheckoutInfoWidgetLoadedHook($page$context));
  216.         $response $this->renderStorefront('@Storefront/storefront/layout/header/actions/cart-widget.html.twig', ['page' => $page]);
  217.         $response->headers->set('x-robots-tag''noindex');
  218.         return $response;
  219.     }
  220.     /**
  221.      * @Since("6.0.0.0")
  222.      * @Route("/checkout/offcanvas", name="frontend.cart.offcanvas", options={"seo"="false"}, methods={"GET"}, defaults={"XmlHttpRequest"=true})
  223.      */
  224.     public function offcanvas(Request $requestSalesChannelContext $context): Response
  225.     {
  226.         $page $this->offcanvasCartPageLoader->load($request$context);
  227.         $this->hook(new CheckoutOffcanvasWidgetLoadedHook($page$context));
  228.         $cart $page->getCart();
  229.         $this->addCartErrors($cart);
  230.         $cartErrors $cart->getErrors();
  231.         if (!$request->query->getBoolean(self::REDIRECTED_FROM_SAME_ROUTE) && $this->routeNeedsReload($cartErrors)) {
  232.             $cartErrors->clear();
  233.             // To prevent redirect loops add the identifier that the request already got redirected from the same origin
  234.             return $this->redirectToRoute(
  235.                 'frontend.cart.offcanvas',
  236.                 \array_merge(
  237.                     $request->query->all(),
  238.                     [self::REDIRECTED_FROM_SAME_ROUTE => true]
  239.                 ),
  240.             );
  241.         }
  242.         $cartErrors->clear();
  243.         return $this->renderStorefront('@Storefront/storefront/component/checkout/offcanvas-cart.html.twig', ['page' => $page]);
  244.     }
  245.     private function addAffiliateTracking(RequestDataBag $dataBagSessionInterface $session): void
  246.     {
  247.         $affiliateCode $session->get(AffiliateTrackingListener::AFFILIATE_CODE_KEY);
  248.         $campaignCode $session->get(AffiliateTrackingListener::CAMPAIGN_CODE_KEY);
  249.         if ($affiliateCode) {
  250.             $dataBag->set(AffiliateTrackingListener::AFFILIATE_CODE_KEY$affiliateCode);
  251.         }
  252.         if ($campaignCode) {
  253.             $dataBag->set(AffiliateTrackingListener::CAMPAIGN_CODE_KEY$campaignCode);
  254.         }
  255.     }
  256.     private function routeNeedsReload(ErrorCollection $cartErrors): bool
  257.     {
  258.         foreach ($cartErrors as $error) {
  259.             if ($error instanceof ShippingMethodChangedError || $error instanceof PaymentMethodChangedError) {
  260.                 return true;
  261.             }
  262.         }
  263.         return false;
  264.     }
  265. }