<?php declare(strict_types=1);namespace Shopware\Core\Framework\Routing;use Shopware\Core\Framework\Log\Package;use Shopware\Core\Framework\Routing\Annotation\RouteScope as RouteScopeAnnotation;use Shopware\Core\Framework\Routing\Exception\InvalidRouteScopeException;use Shopware\Core\PlatformRequest;use Symfony\Component\EventDispatcher\EventSubscriberInterface;use Symfony\Component\HttpFoundation\Request;use Symfony\Component\HttpFoundation\RequestStack;use Symfony\Component\HttpKernel\Event\ControllerEvent;use Symfony\Component\HttpKernel\KernelEvents;/** * @deprecated tag:v6.5.0 - reason:becomes-internal - EventSubscribers will become internal in v6.5.0 */#[Package('core')]class RouteScopeListener implements EventSubscriberInterface{ private RequestStack $requestStack; private RouteScopeRegistry $routeScopeRegistry; /** * @var RouteScopeWhitelistInterface[] */ private array $whitelists; /** * @internal * * @param iterable<RouteScopeWhitelistInterface> $whitelists */ public function __construct( RouteScopeRegistry $routeScopeRegistry, RequestStack $requestStack, iterable $whitelists ) { $this->routeScopeRegistry = $routeScopeRegistry; $this->requestStack = $requestStack; $this->whitelists = \is_array($whitelists) ? $whitelists : iterator_to_array($whitelists); } public static function getSubscribedEvents(): array { return [ KernelEvents::CONTROLLER => [ ['checkScope', KernelListenerPriorities::KERNEL_CONTROLLER_EVENT_SCOPE_VALIDATE], ], ]; } /** * Validate that any given controller invocation creates a valid scope with the original master request */ public function checkScope(ControllerEvent $event): void { if ($this->isWhitelistedController($event)) { return; } $scopes = $this->extractCurrentScopeAnnotation($event); $masterRequest = $this->getMainRequest(); foreach ($scopes as $routeScopeName) { $routeScope = $this->routeScopeRegistry->getRouteScope($routeScopeName); $pathAllowed = $routeScope->isAllowedPath($masterRequest->getPathInfo()); $requestAllowed = $routeScope->isAllowed($masterRequest); if ($pathAllowed && $requestAllowed) { return; } } throw new InvalidRouteScopeException($masterRequest->attributes->get('_route')); } private function extractControllerClass(ControllerEvent $event): ?string { $controllerCallable = \Closure::fromCallable($event->getController()); $controllerCallable = new \ReflectionFunction($controllerCallable); $controller = $controllerCallable->getClosureThis(); if (!$controller) { return null; } return \get_class($controller); } private function isWhitelistedController(ControllerEvent $event): bool { $controllerClass = $this->extractControllerClass($event); if (!$controllerClass) { return false; } foreach ($this->whitelists as $whitelist) { if ($whitelist->applies($controllerClass)) { return true; } } return false; } /** * @return list<string> */ private function extractCurrentScopeAnnotation(ControllerEvent $event): array { $currentRequest = $event->getRequest(); /** @var RouteScopeAnnotation|list<string> $scopes */ $scopes = $currentRequest->get(PlatformRequest::ATTRIBUTE_ROUTE_SCOPE, []); if ($scopes instanceof RouteScopeAnnotation) { return $scopes->getScopes(); } if ($scopes !== []) { return $scopes; } throw new InvalidRouteScopeException($currentRequest->attributes->get('_route')); } private function getMainRequest(): Request { $masterRequest = $this->requestStack->getMainRequest(); if (!$masterRequest) { throw new \InvalidArgumentException('Unable to check the request scope without master request'); } return $masterRequest; }}