<?php
declare(strict_types=1);
namespace Bodymed\Webshop\StoreFront\Subscriber;
use Bodymed\Webshop\StoreFront\Controller\BodymedIDController;
use Shopware\Storefront\Event\StorefrontRenderEvent;
use Shopware\Storefront\Page\Account\Login\AccountLoginPage;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Routing\Exception\RouteNotFoundException;
use Symfony\Component\Routing\RouterInterface;
class StorefrontSubscriber implements EventSubscriberInterface
{
public function __construct(private RouterInterface $router)
{
}
public static function getSubscribedEvents(): array
{
return [
StorefrontRenderEvent::class => 'onStorefrontRender',
KernelEvents::RESPONSE => 'onBeforeSendResponse',
];
}
/**
* @see https://madcode.atlassian.net/browse/BODYMED-884
*
* Nach dem Logout wird der User auf die Startseite geleitet, statt auf die Login-Seite.
* Hierfür wird die TargetUrl der Response von \Shopware\Storefront\Controller\AuthController::logout
* ersetzt durch die Startseite als Ziel
*/
public function onBeforeSendResponse(ResponseEvent $event): void
{
if (!$event->isMainRequest()) {
return;
}
$request = $event->getRequest();
$response = $event->getResponse();
$route = $request->attributes->get('_route', null);
if ($route === 'frontend.account.logout.page' and $response instanceof RedirectResponse) {
$targetUrl = $this->router->generate('frontend.home.page');
$response->setTargetUrl($targetUrl);
}
}
/**
* @see https://madcode.atlassian.net/browse/BODYMED-737
*
* Prüft, ob der Query-Parameter *redirectTo* unerlaubte Zeichen hat,
* bevor diese auf der Login-Seite ausgegeben wird (XSS-Attacks verhindern)
* Anschließend wird versucht, aus dem bereinigten Parameter eine Route zu generieren.
*
* Wenn keine Route generiert werden kann, wird die Default-Route 'frontend.account.home.page'
* and die Seite durchgereicht.
*/
public function onStorefrontRender(StorefrontRenderEvent $event): void
{
$parameters = $event->getParameters();
if (isset($parameters['page'])) {
$page = $parameters['page'];
if ($page instanceof AccountLoginPage) {
if (isset($parameters['redirectTo'])) {
$redirectToRoute = \htmlspecialchars($parameters['redirectTo']);
$redirectParameters = [];
if (isset($parameters['redirectParameters'])) {
$redirectParameters = \json_decode($parameters['redirectParameters'], true);
}
try {
$this->router->generate($redirectToRoute, $redirectParameters);
} catch (RouteNotFoundException $routeNotFoundException) {
$redirectToRoute = BodymedIDController::REDIRECT_DEFAULT_ROUTE;
$event->setParameter('redirectTo', $redirectToRoute);
}
}
}
}
}
}