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

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