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

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