vendor/dvdw/platform-choice/src/Framework/Routing/StorefrontSubscriber.php line 44

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Dvdw\PlatformChoice\Framework\Routing;
  3. use Dvdw\PlatformChoice\Framework\Util\TokenEncoder;
  4. use Shopware\Core\Framework\Util\Random;
  5. use Shopware\Core\PlatformRequest;
  6. use Shopware\Core\SalesChannelRequest;
  7. use Shopware\Core\System\SalesChannel\Context\SalesChannelContextPersister;
  8. use Shopware\Storefront\Framework\Routing\RequestTransformer;
  9. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  10. use Symfony\Component\HttpFoundation\RedirectResponse;
  11. use Symfony\Component\HttpFoundation\Request;
  12. use Symfony\Component\HttpFoundation\RequestStack;
  13. use Symfony\Component\HttpKernel\Event\RequestEvent;
  14. use Symfony\Component\HttpKernel\KernelEvents;
  15. class StorefrontSubscriber implements EventSubscriberInterface
  16. {
  17.     public CONST TOKEN_NAME 'sw-identifier';
  18.     public CONST NONCE 'nonce';
  19.     public CONST NONCE_LENGTH 16;
  20.     private RequestStack $requestStack;
  21.     private SalesChannelContextPersister $contextPersister;
  22.     public function __construct(
  23.         RequestStack $requestStack,
  24.         SalesChannelContextPersister $contextPersister
  25.     )
  26.     {
  27.         $this->requestStack $requestStack;
  28.         $this->contextPersister $contextPersister;
  29.     }
  30.     public static function getSubscribedEvents(): iterable
  31.     {
  32.         return [KernelEvents::REQUEST => ['setContextToken'100]];
  33.     }
  34.     public function setContextToken(RequestEvent $event): void
  35.     {
  36.         $master $this->requestStack->getMainRequest();
  37.         if ($master === null) {
  38.             return;
  39.         }
  40.         $cookieToken $master->cookies->get(self::TOKEN_NAME);
  41.         $queryToken $master->query->get(self::TOKEN_NAME);
  42.         $queryNonce $master->query->get(self::NONCE);
  43.         if ($master->attributes->get(SalesChannelRequest::ATTRIBUTE_IS_SALES_CHANNEL_REQUEST) === null
  44.             || !$master->hasSession()
  45.             || ($cookieToken === null && $queryToken === null)
  46.             || ($queryToken !== null && $queryNonce === null)
  47.         )
  48.         {
  49.             return;
  50.         }
  51.         $session $master->getSession();
  52.         if (!$session->isStarted()) {
  53.             $session->setName('session-');
  54.             $session->start();
  55.             $session->set('sessionId'$session->getId());
  56.         }
  57.         if ($queryToken !== null) {
  58.             $this->setCleanedUrl($event$master);
  59.             $token TokenEncoder::decodeToken($queryToken);
  60.             $this->verifyAndSetCookie($token$queryNonce$queryToken$master);
  61.         } else {
  62.             $token TokenEncoder::decodeToken($cookieToken);
  63.         }
  64.         $session->set(PlatformRequest::HEADER_CONTEXT_TOKEN$token);
  65.         $master->headers->set(
  66.             PlatformRequest::HEADER_CONTEXT_TOKEN,
  67.             $session->get(PlatformRequest::HEADER_CONTEXT_TOKEN)
  68.         );
  69.     }
  70.     private function getDomain(Request $request): string
  71.     {
  72.         $split array_reverse(explode('.'$request->getHost()));
  73.         return sprintf('.%s.%s'$split[1], $split[0]);
  74.     }
  75.     private function setCleanedUrl(RequestEvent $eventRequest $request): void
  76.     {
  77.         $url $request->attributes->get(RequestTransformer::SALES_CHANNEL_ABSOLUTE_BASE_URL)
  78.             . $request->attributes->get(RequestTransformer::ORIGINAL_REQUEST_URI);
  79.         if (empty($url)) {
  80.             return;
  81.         }
  82.         $url $this->removeFromUrl($url);
  83.         $event->setResponse(new RedirectResponse($url));
  84.     }
  85.     private function removeFromUrl(string $url): string
  86.     {
  87.         $parsedUrl parse_url($url);
  88.         $query = [];
  89.         if (isset($parsedUrl['query'])) {
  90.             parse_str($parsedUrl['query'], $query);
  91.             unset($query[self::TOKEN_NAME]);
  92.             unset($query[self::NONCE]);
  93.         }
  94.         $path $parsedUrl['path'] ?? '';
  95.         $query = !empty($query) ? '?'http_build_query($query) : '';
  96.         return $parsedUrl['scheme']. '://'$parsedUrl['host']. $path$query;
  97.     }
  98.     private function verifyAndSetCookie(string $tokenstring $queryNoncestring $queryTokenRequest $request): void
  99.     {
  100.         $context $this->contextPersister->load($token'');
  101.         $nonce $context[self::NONCE] ?? null;
  102.         if ($nonce !== $queryNonce) {
  103.             return;
  104.         }
  105.         $this->contextPersister->save(
  106.             $token,
  107.             [self::NONCE => Random::getAlphanumericString(self::NONCE_LENGTH)],
  108.             ''
  109.         );
  110.         setcookie(
  111.             self::TOKEN_NAME,
  112.             $queryToken,
  113.             (new \DateTime())->modify('+1 year')->getTimestamp(),
  114.             '/',
  115.             $this->getDomain($request)
  116.         );
  117.     }
  118. }