src/Core/Framework/Routing/SalesChannelRequestContextResolver.php line 77

  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Framework\Routing;
  3. use Shopware\Core\Checkout\Cart\CartException;
  4. use Shopware\Core\Framework\Log\Package;
  5. use Shopware\Core\Framework\Routing\Event\SalesChannelContextResolvedEvent;
  6. use Shopware\Core\Framework\Routing\Exception\MissingRequestParameterException;
  7. use Shopware\Core\Framework\Util\Random;
  8. use Shopware\Core\PlatformRequest;
  9. use Shopware\Core\SalesChannelRequest;
  10. use Shopware\Core\System\SalesChannel\Context\SalesChannelContextServiceInterface;
  11. use Shopware\Core\System\SalesChannel\Context\SalesChannelContextServiceParameters;
  12. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  13. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  14. use Symfony\Component\HttpFoundation\Request;
  15. use Symfony\Component\HttpFoundation\Request as SymfonyRequest;
  16. #[Package('core')]
  17. class SalesChannelRequestContextResolver implements RequestContextResolverInterface
  18. {
  19.     use RouteScopeCheckTrait;
  20.     /**
  21.      * @var SalesChannelContext[]
  22.      */
  23.     private array $cache = [];
  24.     /**
  25.      * @internal
  26.      */
  27.     public function __construct(
  28.         private readonly RequestContextResolverInterface $decorated,
  29.         private readonly SalesChannelContextServiceInterface $contextService,
  30.         private readonly EventDispatcherInterface $eventDispatcher,
  31.         private readonly RouteScopeRegistry $routeScopeRegistry
  32.     ) {
  33.     }
  34.     public function resolve(SymfonyRequest $request): void
  35.     {
  36.         if (!$request->attributes->has(PlatformRequest::ATTRIBUTE_SALES_CHANNEL_ID)) {
  37.             $this->decorated->resolve($request);
  38.             return;
  39.         }
  40.         if (!$this->isRequestScoped($requestSalesChannelContextRouteScopeDependant::class)) {
  41.             return;
  42.         }
  43.         if (
  44.             $this->contextTokenRequired($request) === true
  45.             && !$request->headers->has(PlatformRequest::HEADER_CONTEXT_TOKEN)
  46.         ) {
  47.             throw new MissingRequestParameterException(PlatformRequest::HEADER_CONTEXT_TOKEN);
  48.         }
  49.         if (
  50.             $this->contextTokenRequired($request) === false
  51.             && !$request->headers->has(PlatformRequest::HEADER_CONTEXT_TOKEN)
  52.         ) {
  53.             $request->headers->set(PlatformRequest::HEADER_CONTEXT_TOKENRandom::getAlphanumericString(32));
  54.         }
  55.         $contextToken $request->headers->get(PlatformRequest::HEADER_CONTEXT_TOKEN);
  56.         $salesChannelId $request->attributes->get(PlatformRequest::ATTRIBUTE_SALES_CHANNEL_ID);
  57.         $language $request->headers->get(PlatformRequest::HEADER_LANGUAGE_ID);
  58.         $currencyId $request->attributes->get(SalesChannelRequest::ATTRIBUTE_DOMAIN_CURRENCY_ID);
  59.         $domainId $request->attributes->get(SalesChannelRequest::ATTRIBUTE_DOMAIN_ID);
  60.         $cacheKey $salesChannelId $contextToken $language $currencyId $domainId;
  61.         if (!empty($this->cache[$cacheKey])) {
  62.             $context $this->cache[$cacheKey];
  63.         } else {
  64.             $context $this->contextService->get(
  65.                 new SalesChannelContextServiceParameters((string) $salesChannelId, (string) $contextToken$language$currencyId$domainId)
  66.             );
  67.             $request->headers->set(PlatformRequest::HEADER_CONTEXT_TOKEN$context->getToken());
  68.         }
  69.         $this->validateLogin($request$context);
  70.         $request->attributes->set(PlatformRequest::ATTRIBUTE_CONTEXT_OBJECT$context->getContext());
  71.         $request->attributes->set(PlatformRequest::ATTRIBUTE_SALES_CHANNEL_CONTEXT_OBJECT$context);
  72.         $request->headers->set(PlatformRequest::HEADER_CONTEXT_TOKEN$context->getToken());
  73.         $this->eventDispatcher->dispatch(
  74.             new SalesChannelContextResolvedEvent($context, (string) $contextToken)
  75.         );
  76.     }
  77.     public function handleSalesChannelContext(Request $requeststring $salesChannelIdstring $contextToken): void
  78.     {
  79.         $language $request->headers->get(PlatformRequest::HEADER_LANGUAGE_ID);
  80.         $currencyId $request->attributes->get(SalesChannelRequest::ATTRIBUTE_DOMAIN_CURRENCY_ID);
  81.         $context $this->contextService
  82.             ->get(new SalesChannelContextServiceParameters($salesChannelId$contextToken$language$currencyId));
  83.         $request->attributes->set(PlatformRequest::ATTRIBUTE_CONTEXT_OBJECT$context->getContext());
  84.         $request->attributes->set(PlatformRequest::ATTRIBUTE_SALES_CHANNEL_CONTEXT_OBJECT$context);
  85.     }
  86.     protected function getScopeRegistry(): RouteScopeRegistry
  87.     {
  88.         return $this->routeScopeRegistry;
  89.     }
  90.     private function contextTokenRequired(Request $request): bool
  91.     {
  92.         return $request->attributes->get(PlatformRequest::ATTRIBUTE_CONTEXT_TOKEN_REQUIREDfalse);
  93.     }
  94.     private function validateLogin(Request $requestSalesChannelContext $context): void
  95.     {
  96.         if (!$request->attributes->get(PlatformRequest::ATTRIBUTE_LOGIN_REQUIRED)) {
  97.             return;
  98.         }
  99.         if ($context->getCustomer() === null) {
  100.             throw CartException::customerNotLoggedIn();
  101.         }
  102.         if ($request->attributes->get(PlatformRequest::ATTRIBUTE_LOGIN_REQUIRED_ALLOW_GUESTfalse) === false && $context->getCustomer()->getGuest()) {
  103.             throw CartException::customerNotLoggedIn();
  104.         }
  105.     }
  106. }