<?php declare(strict_types=1);namespace KielCodingPlatformTrailingSlash\TrailingSlash;use Shopware\Core\SalesChannelRequest;use Shopware\Core\System\SystemConfig\SystemConfigService;use Symfony\Component\EventDispatcher\EventSubscriberInterface;use Symfony\Component\HttpFoundation\RedirectResponse;use Symfony\Component\HttpFoundation\Request;use Symfony\Component\HttpKernel\Event\RequestEvent;use Symfony\Component\HttpKernel\KernelEvents;class RequestSubscriber implements EventSubscriberInterface{ private const ATTRIBUTE_SALES_CHANNEL_BASE_URL = 'sw-sales-channel-base-url'; private const ROUTE_NAME_HOME = 'frontend.home.page'; private const ROUTE_NAME_NAVIGATION = 'frontend.navigation.page'; private SystemConfigService $systemConfigService; public function __construct(SystemConfigService $systemConfigService) { $this->systemConfigService = $systemConfigService; } public static function getSubscribedEvents(): array { return [ KernelEvents::REQUEST => [ ['onRequest'], ], ]; } public function onRequest(RequestEvent $event): void { $request = $event->getRequest(); if (!$event->isMainRequest()) { return; } if (!$this->isHomeRequest($request) && !$this->isNavigationRequest($request)) { return; } if (!$this->shouldRedirect($request)) { return; } if ($this->isHomeRequest($request)) { // storefront pointing not on a sub folder if ($request->attributes->get(self::ATTRIBUTE_SALES_CHANNEL_BASE_URL) == '') { return; } // storefront pointing on a sub folder if (!$request->attributes->has(SalesChannelRequest::ATTRIBUTE_STOREFRONT_URL)) { return; } // prevent homepage redirect if disabled via plugin config if ($this->preventHomepageRedirect($request)) { return; } $canonical = $request->attributes->get(SalesChannelRequest::ATTRIBUTE_STOREFRONT_URL); $current = $request->attributes->get(RequestTransformer::ATTRIBUTE_CURRENT_LINK); } elseif ($this->isNavigationRequest($request)) { if (!$request->attributes->has(SalesChannelRequest::ATTRIBUTE_CANONICAL_LINK)) { return; } $canonical = $request->attributes->get(SalesChannelRequest::ATTRIBUTE_CANONICAL_LINK); $current = $request->attributes->get(RequestTransformer::ATTRIBUTE_CURRENT_LINK); } else { return; } if ($canonical === $current) { // no redirect needed return; } if ($request->getQueryString()) { $canonical .= '?' . $request->getQueryString(); } $statusCode = $this->getStatusCode($request); $event->setResponse(new RedirectResponse($canonical, $statusCode)); } private function isHomeRequest(Request $request): bool { return $request->attributes->get('_route') == self::ROUTE_NAME_HOME; } private function isNavigationRequest(Request $request): bool { return $request->attributes->get('_route') == self::ROUTE_NAME_NAVIGATION; } private function preventHomepageRedirect(Request $request): bool { $salesChannelId = $request->attributes->get('sw-sales-channel-id'); return $this->systemConfigService->getBool('KielCodingPlatformTrailingSlash.config.preventHomepageRedirect', $salesChannelId); } private function shouldRedirect(Request $request): bool { $salesChannelId = $request->attributes->get('sw-sales-channel-id'); return $this->systemConfigService->getString('KielCodingPlatformTrailingSlash.config.method', $salesChannelId) === 'redirect'; } private function getStatusCode(Request $request): int { $salesChannelId = $request->attributes->get('sw-sales-channel-id'); return $this->systemConfigService->getInt('KielCodingPlatformTrailingSlash.config.redirectCode', $salesChannelId) ?: 301; }}