vendor/shopware/storefront/Controller/StorefrontController.php line 216

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Storefront\Controller;
  3. use Shopware\Core\Checkout\Cart\Cart;
  4. use Shopware\Core\Checkout\Cart\Error\Error;
  5. use Shopware\Core\Checkout\Cart\Error\ErrorRoute;
  6. use Shopware\Core\Content\Seo\SeoUrlPlaceholderHandlerInterface;
  7. use Shopware\Core\Framework\Adapter\Twig\TemplateFinder;
  8. use Shopware\Core\Framework\Feature;
  9. use Shopware\Core\Framework\Routing\RequestTransformerInterface;
  10. use Shopware\Core\Framework\Script\Execution\Hook;
  11. use Shopware\Core\Framework\Script\Execution\ScriptExecutor;
  12. use Shopware\Core\PlatformRequest;
  13. use Shopware\Storefront\Event\StorefrontRenderEvent;
  14. use Shopware\Storefront\Framework\Routing\RequestTransformer;
  15. use Shopware\Storefront\Framework\Routing\Router;
  16. use Shopware\Storefront\Framework\Routing\StorefrontResponse;
  17. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  18. use Symfony\Component\HttpFoundation\Request;
  19. use Symfony\Component\HttpFoundation\Response;
  20. use Symfony\Component\HttpKernel\EventListener\AbstractSessionListener;
  21. use Twig\Environment;
  22. abstract class StorefrontController extends AbstractController
  23. {
  24.     public const SUCCESS = 'success';
  25.     public const DANGER = 'danger';
  26.     public const INFO = 'info';
  27.     public const WARNING = 'warning';
  28.     private Environment $twig;
  29.     public function setTwig(Environment $twig): void
  30.     {
  31.         $this->twig = $twig;
  32.     }
  33.     protected function renderStorefront(string $view, array $parameters = []): Response
  34.     {
  35.         $request = $this->container->get('request_stack')->getCurrentRequest();
  36.         if ($request === null) {
  37.             $request = new Request();
  38.         }
  39.         $salesChannelContext = $request->attributes->get(PlatformRequest::ATTRIBUTE_SALES_CHANNEL_CONTEXT_OBJECT);
  40.         /* @feature-deprecated $view will be original template in StorefrontRenderEvent from 6.5.0.0 */
  41.         if (Feature::isActive('FEATURE_NEXT_17275')) {
  42.             $event = new StorefrontRenderEvent($view, $parameters, $request, $salesChannelContext);
  43.         } else {
  44.             $inheritedView = $this->getTemplateFinder()->find($view);
  45.             $event = new StorefrontRenderEvent($inheritedView, $parameters, $request, $salesChannelContext);
  46.         }
  47.         $this->container->get('event_dispatcher')->dispatch($event);
  48.         $response = $this->render($view, $event->getParameters(), new StorefrontResponse());
  49.         if (!$response instanceof StorefrontResponse) {
  50.             throw new \RuntimeException('Symfony render implementation changed. Providing a response is no longer supported');
  51.         }
  52.         $host = $request->attributes->get(RequestTransformer::STOREFRONT_URL);
  53.         $seoUrlReplacer = $this->container->get(SeoUrlPlaceholderHandlerInterface::class);
  54.         $content = $response->getContent();
  55.         if ($content !== false) {
  56.             $response->setContent(
  57.                 $seoUrlReplacer->replace($content, $host, $salesChannelContext)
  58.             );
  59.         }
  60.         $response->setData($parameters);
  61.         $response->setContext($salesChannelContext);
  62.         $response->headers->set(AbstractSessionListener::NO_AUTO_CACHE_CONTROL_HEADER, '1');
  63.         $response->headers->set('Content-Type', 'text/html');
  64.         return $response;
  65.     }
  66.     protected function trans(string $snippet, array $parameters = []): string
  67.     {
  68.         return $this->container
  69.             ->get('translator')
  70.             ->trans($snippet, $parameters);
  71.     }
  72.     protected function createActionResponse(Request $request): Response
  73.     {
  74.         if ($request->get('redirectTo') || $request->get('redirectTo') === '') {
  75.             $params = $this->decodeParam($request, 'redirectParameters');
  76.             $redirectTo = $request->get('redirectTo');
  77.             if ($redirectTo) {
  78.                 return $this->redirectToRoute($redirectTo, $params);
  79.             }
  80.             return $this->redirectToRoute('frontend.home.page', $params);
  81.         }
  82.         if ($request->get('forwardTo')) {
  83.             $params = $this->decodeParam($request, 'forwardParameters');
  84.             return $this->forwardToRoute($request->get('forwardTo'), [], $params);
  85.         }
  86.         return new Response();
  87.     }
  88.     protected function forwardToRoute(string $routeName, array $attributes = [], array $routeParameters = []): Response
  89.     {
  90.         $router = $this->container->get('router');
  91.         $url = $this->generateUrl($routeName, $routeParameters, Router::PATH_INFO);
  92.         // for the route matching the request method is set to "GET" because
  93.         // this method is not ought to be used as a post passthrough
  94.         // rather it shall return templates or redirects to display results of the request ahead
  95.         $method = $router->getContext()->getMethod();
  96.         $router->getContext()->setMethod(Request::METHOD_GET);
  97.         $route = $router->match($url);
  98.         $router->getContext()->setMethod($method);
  99.         $request = $this->container->get('request_stack')->getCurrentRequest();
  100.         if ($request === null) {
  101.             $request = new Request();
  102.         }
  103.         $attributes = array_merge(
  104.             $this->container->get(RequestTransformerInterface::class)->extractInheritableAttributes($request),
  105.             $route,
  106.             $attributes,
  107.             ['_route_params' => $routeParameters]
  108.         );
  109.         return $this->forward($route['_controller'], $attributes, $routeParameters);
  110.     }
  111.     protected function decodeParam(Request $request, string $param): array
  112.     {
  113.         $params = $request->get($param);
  114.         if (\is_string($params)) {
  115.             $params = json_decode($params, true);
  116.         }
  117.         if (empty($params)) {
  118.             $params = [];
  119.         }
  120.         return $params;
  121.     }
  122.     protected function addCartErrors(Cart $cart, ?\Closure $filter = null): void
  123.     {
  124.         $errors = $cart->getErrors();
  125.         if ($filter !== null) {
  126.             $errors = $errors->filter($filter);
  127.         }
  128.         $groups = [
  129.             'info' => $errors->getNotices(),
  130.             'warning' => $errors->getWarnings(),
  131.             'danger' => $errors->getErrors(),
  132.         ];
  133.         $request = $this->container->get('request_stack')->getMainRequest();
  134.         $exists = [];
  135.         if ($request && $request->hasSession() && method_exists($session = $request->getSession(), 'getFlashBag')) {
  136.             $exists = $session->getFlashBag()->peekAll();
  137.         }
  138.         $flat = [];
  139.         foreach ($exists as $messages) {
  140.             $flat = array_merge($flat, $messages);
  141.         }
  142.         /** @var array<string, Error[]> $groups */
  143.         foreach ($groups as $type => $errors) {
  144.             foreach ($errors as $error) {
  145.                 $parameters = [];
  146.                 foreach ($error->getParameters() as $key => $value) {
  147.                     $parameters['%' . $key . '%'] = $value;
  148.                 }
  149.                 if ($error->getRoute() instanceof ErrorRoute) {
  150.                     $parameters['%url%'] = $this->generateUrl(
  151.                         $error->getRoute()->getKey(),
  152.                         $error->getRoute()->getParams()
  153.                     );
  154.                 }
  155.                 $message = $this->trans('checkout.' . $error->getMessageKey(), $parameters);
  156.                 if (\in_array($message, $flat, true)) {
  157.                     continue;
  158.                 }
  159.                 $this->addFlash($type, $message);
  160.             }
  161.         }
  162.     }
  163.     protected function renderView(string $view, array $parameters = []): string
  164.     {
  165.         $view = $this->getTemplateFinder()->find($view);
  166.         if (isset($this->twig)) {
  167.             return $this->twig->render($view, $parameters);
  168.         }
  169.         $message = sprintf('Class %s does not have twig injected. Add to your service definition a method call to setTwig with the twig instance', static::class);
  170.         if (Feature::isActive('FEATURE_NEXT_15687')) {
  171.             throw new \LogicException($message);
  172.         }
  173.         Feature::triggerDeprecated('FEATURE_NEXT_15687', '6.4.3.0', '6.5.0.0', $message);
  174.         return parent::renderView($view, $parameters);
  175.     }
  176.     protected function getTemplateFinder(): TemplateFinder
  177.     {
  178.         return $this->container->get(TemplateFinder::class);
  179.     }
  180.     protected function hook(Hook $hook): void
  181.     {
  182.         $this->container->get(ScriptExecutor::class)->execute($hook);
  183.     }
  184. }