From 3fdfe9eb8d92cb1c5f205e0a02e82d1ff1d65142 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Thu, 9 Jan 2025 21:29:13 +0100 Subject: [PATCH] Fix an edge-case about pretty URLs and cache warm up --- config/services.php | 1 + src/EventListener/AdminRouterSubscriber.php | 29 +++++++++++---------- src/Router/AdminRouteGenerator.php | 12 ++++----- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/config/services.php b/config/services.php index 816d9d7e76..245f8bdf1e 100644 --- a/config/services.php +++ b/config/services.php @@ -171,6 +171,7 @@ ->arg(3, service('router')) ->arg(4, service('router')) ->arg(5, service('cache.easyadmin')) + ->arg(6, service(AdminRouteGenerator::class)) ->tag('kernel.event_subscriber') ->set(ControllerFactory::class) diff --git a/src/EventListener/AdminRouterSubscriber.php b/src/EventListener/AdminRouterSubscriber.php index 2c9bbcfc47..38ca534a75 100644 --- a/src/EventListener/AdminRouterSubscriber.php +++ b/src/EventListener/AdminRouterSubscriber.php @@ -5,6 +5,7 @@ use EasyCorp\Bundle\EasyAdminBundle\Config\Option\EA; use EasyCorp\Bundle\EasyAdminBundle\Contracts\Controller\CrudControllerInterface; use EasyCorp\Bundle\EasyAdminBundle\Contracts\Controller\DashboardControllerInterface; +use EasyCorp\Bundle\EasyAdminBundle\Contracts\Router\AdminRouteGeneratorInterface; use EasyCorp\Bundle\EasyAdminBundle\Factory\AdminContextFactory; use EasyCorp\Bundle\EasyAdminBundle\Factory\ControllerFactory; use EasyCorp\Bundle\EasyAdminBundle\Router\AdminRouteGenerator; @@ -38,8 +39,9 @@ class AdminRouterSubscriber implements EventSubscriberInterface private UrlGeneratorInterface $urlGenerator; private RequestMatcherInterface $requestMatcher; private CacheItemPoolInterface $cache; + private AdminRouteGeneratorInterface $adminRouteGenerator; - public function __construct(AdminContextFactory $adminContextFactory, ControllerFactory $controllerFactory, ControllerResolverInterface $controllerResolver, UrlGeneratorInterface $urlGenerator, RequestMatcherInterface $requestMatcher, CacheItemPoolInterface $cache) + public function __construct(AdminContextFactory $adminContextFactory, ControllerFactory $controllerFactory, ControllerResolverInterface $controllerResolver, UrlGeneratorInterface $urlGenerator, RequestMatcherInterface $requestMatcher, CacheItemPoolInterface $cache, AdminRouteGenerator $adminRouteGenerator) { $this->adminContextFactory = $adminContextFactory; $this->controllerFactory = $controllerFactory; @@ -47,6 +49,7 @@ public function __construct(AdminContextFactory $adminContextFactory, Controller $this->urlGenerator = $urlGenerator; $this->requestMatcher = $requestMatcher; $this->cache = $cache; + $this->adminRouteGenerator = $adminRouteGenerator; } public static function getSubscribedEvents(): array @@ -64,19 +67,21 @@ public static function getSubscribedEvents(): array public function onKernelRequestPrettyUrls(RequestEvent $event): void { $request = $event->getRequest(); - $routeName = $request->attributes->get('_route'); - if (null === $routeName) { + if (false === $request->attributes->has(EA::ROUTE_CREATED_BY_EASYADMIN)) { return; } + // edge-case: in some scenarios, admin routes are generated by the custom route loader + // and their information is cached but then removed from the cache (e.g. when running + // 'rm -fr var/cache/* && bin/console cache:clear'). If that's the case, regenerate the + // admin routes to force saving them in the cache again. + // see https://github.com/EasyCorp/EasyAdminBundle/issues/6680 $adminRoutes = $this->cache->getItem(AdminRouteGenerator::CACHE_KEY_ROUTE_TO_FQCN)->get(); - if (null === $adminRoutes || !\array_key_exists($routeName, $adminRoutes)) { - return; + if (null === $adminRoutes) { + $this->adminRouteGenerator->generateAll(); } - $request->attributes->set(EA::ROUTE_CREATED_BY_EASYADMIN, true); - - $dashboardControllerFqcn = $adminRoutes[$routeName][EA::DASHBOARD_CONTROLLER_FQCN]; + $dashboardControllerFqcn = $request->attributes->get(EA::DASHBOARD_CONTROLLER_FQCN); if (null === $dashboardControllerInstance = $this->getDashboardControllerInstance($dashboardControllerFqcn, $request)) { return; } @@ -84,12 +89,8 @@ public function onKernelRequestPrettyUrls(RequestEvent $event): void // creating the context is expensive, so it's created once and stored in the request // if the current request already has an AdminContext object, do nothing if (null === $adminContext = $request->attributes->get(EA::CONTEXT_REQUEST_ATTRIBUTE)) { - $crudControllerFqcn = $adminRoutes[$routeName][EA::CRUD_CONTROLLER_FQCN]; - $actionName = $adminRoutes[$routeName][EA::CRUD_ACTION]; - - $request->attributes->set(EA::DASHBOARD_CONTROLLER_FQCN, $dashboardControllerFqcn); - $request->attributes->set(EA::CRUD_CONTROLLER_FQCN, $crudControllerFqcn); - $request->attributes->set(EA::CRUD_ACTION, $actionName); + $crudControllerFqcn = $request->attributes->get(EA::CRUD_CONTROLLER_FQCN); + $actionName = $request->attributes->get(EA::CRUD_ACTION); $crudControllerInstance = $this->controllerFactory->getCrudControllerInstance($crudControllerFqcn, $actionName, $request); $adminContext = $this->adminContextFactory->create($request, $dashboardControllerInstance, $crudControllerInstance, $actionName); diff --git a/src/Router/AdminRouteGenerator.php b/src/Router/AdminRouteGenerator.php index de26d558e8..094ad95d90 100644 --- a/src/Router/AdminRouteGenerator.php +++ b/src/Router/AdminRouteGenerator.php @@ -151,15 +151,13 @@ private function generateAdminRoutes(): array $defaults = [ '_controller' => $crudControllerFqcn.'::'.$actionName, - ]; - $options = [ EA::ROUTE_CREATED_BY_EASYADMIN => true, EA::DASHBOARD_CONTROLLER_FQCN => $dashboardFqcn, EA::CRUD_CONTROLLER_FQCN => $crudControllerFqcn, EA::CRUD_ACTION => $actionName, ]; - $adminRoute = new Route($adminRoutePath, defaults: $defaults, options: $options, methods: $actionRouteConfig['methods']); + $adminRoute = new Route($adminRoutePath, defaults: $defaults, methods: $actionRouteConfig['methods']); $adminRoutes[$adminRouteName] = $adminRoute; $addedRouteNames[] = $adminRouteName; } @@ -397,12 +395,12 @@ private function saveAdminRoutesInCache(array $adminRoutes): void // then, add all the generated admin routes foreach ($adminRoutes as $routeName => $route) { $routeNameToFqcn[$routeName] = [ - EA::DASHBOARD_CONTROLLER_FQCN => $route->getOption(EA::DASHBOARD_CONTROLLER_FQCN), - EA::CRUD_CONTROLLER_FQCN => $route->getOption(EA::CRUD_CONTROLLER_FQCN), - EA::CRUD_ACTION => $route->getOption(EA::CRUD_ACTION), + EA::DASHBOARD_CONTROLLER_FQCN => $route->getDefault(EA::DASHBOARD_CONTROLLER_FQCN), + EA::CRUD_CONTROLLER_FQCN => $route->getDefault(EA::CRUD_CONTROLLER_FQCN), + EA::CRUD_ACTION => $route->getDefault(EA::CRUD_ACTION), ]; - $fqcnToRouteName[$route->getOption(EA::DASHBOARD_CONTROLLER_FQCN)][$route->getOption(EA::CRUD_CONTROLLER_FQCN)][$route->getOption(EA::CRUD_ACTION)] = $routeName; + $fqcnToRouteName[$route->getDefault(EA::DASHBOARD_CONTROLLER_FQCN)][$route->getDefault(EA::CRUD_CONTROLLER_FQCN)][$route->getDefault(EA::CRUD_ACTION)] = $routeName; } $routeNameToFqcnItem = $this->cache->getItem(self::CACHE_KEY_ROUTE_TO_FQCN);