Skip to content

Commit

Permalink
bug #6500 Fix the priority/order of the generated routes (javiereguiluz)
Browse files Browse the repository at this point in the history
This PR was squashed before being merged into the 4.x branch.

Discussion
----------

Fix the priority/order of the generated routes

This is needed when using custom actions via the `#[AdminAction]` attribute.

Commits
-------

25bf21d Fix the priority/order of the generated routes
  • Loading branch information
javiereguiluz committed Nov 4, 2024
2 parents 9e0ef39 + 25bf21d commit e1025aa
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 21 deletions.
15 changes: 12 additions & 3 deletions src/Router/AdminRouteGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@
*/
final class AdminRouteGenerator implements AdminRouteGeneratorInterface
{
// the order in which routes are defined here is important because routes
// are added to the application in the same order and e.g. the path of the
// 'detail' route collides with the 'new' route and must be defined after it
private const DEFAULT_ROUTES_CONFIG = [
'index' => [
'routePath' => '/',
Expand Down Expand Up @@ -92,6 +89,18 @@ public function generateAll(): RouteCollection

$crudControllerRouteConfig = $this->getCrudControllerRouteConfig($crudControllerFqcn);
$actionsRouteConfig = array_replace_recursive($defaultRoutesConfig, $this->getCustomActionsConfig($crudControllerFqcn));
// by default, the 'detail' route uses a catch-all route pattern (/{entityId});
// so, if the user hasn't customized the 'detail' route path, we need to sort the actions
// to make sure that the 'detail' action is always the last one
if ('/{entityId}' === $actionsRouteConfig['detail']['routePath']) {
uasort($actionsRouteConfig, static function ($a, $b) {
return match (true) {
'detail' === $a['routeName'] => 1,
'detail' === $b['routeName'] => -1,
default => 0,
};
});
}

foreach (array_keys($actionsRouteConfig) as $actionName) {
$actionRouteConfig = $actionsRouteConfig[$actionName];
Expand Down
36 changes: 18 additions & 18 deletions tests/Controller/PrettyUrls/PrettyUrlsControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,44 +17,47 @@ public static function getKernelClass(): string

public function testGeneratedRoutes()
{
// the generated routes are:
// * `admin_pretty_*`: the default routes of DashboardController (which doesn't customize anything about them)
// * `admin_pretty_external_user_editor_*`: these are the routes related to the User entity; this is not used by DashboardController, but they are created
// anyways because EasyAdmin creates routes for all dashboards + CRUD controllers by default (this can be avoided
// by setting the 'allowedControllers' option in the #[AdminDashboard] attribute)
// * `second_dashboard_*`: the fully-customized routes of the SecondDashboardController; EasyAdmin only generates routes for the User
// entity because it's the only one allowed by the 'allowedControllers' option in the #[AdminDashboard] attribute
// note: don't sort or reorder these routes in any way; this is the expected order in which
// they are generated by EasyAdmin and it's important to test that too
$expectedRoutes = [];
// the default routes of DashboardController (which doesn't customize anything about them)
$expectedRoutes['admin_pretty'] = '/admin/pretty/urls';
$expectedRoutes['second_dashboard'] = '/second/dashboard';
$expectedRoutes['admin_pretty_blog_post_index'] = '/admin/pretty/urls/blog_post/';
$expectedRoutes['admin_pretty_blog_post_detail'] = '/admin/pretty/urls/blog_post/{entityId}';
$expectedRoutes['admin_pretty_blog_post_new'] = '/admin/pretty/urls/blog_post/new';
$expectedRoutes['admin_pretty_blog_post_edit'] = '/admin/pretty/urls/blog_post/{entityId}/edit';
$expectedRoutes['admin_pretty_blog_post_delete'] = '/admin/pretty/urls/blog_post/{entityId}/delete';
$expectedRoutes['admin_pretty_blog_post_batchDelete'] = '/admin/pretty/urls/blog_post/batchDelete';
$expectedRoutes['admin_pretty_blog_post_autocomplete'] = '/admin/pretty/urls/blog_post/autocomplete';
$expectedRoutes['admin_pretty_blog_post_edit'] = '/admin/pretty/urls/blog_post/{entityId}/edit';
$expectedRoutes['admin_pretty_blog_post_delete'] = '/admin/pretty/urls/blog_post/{entityId}/delete';
$expectedRoutes['admin_pretty_blog_post_detail'] = '/admin/pretty/urls/blog_post/{entityId}';
$expectedRoutes['admin_pretty_category_index'] = '/admin/pretty/urls/category/';
$expectedRoutes['admin_pretty_category_detail'] = '/admin/pretty/urls/category/{entityId}';
$expectedRoutes['admin_pretty_category_new'] = '/admin/pretty/urls/category/new';
$expectedRoutes['admin_pretty_category_edit'] = '/admin/pretty/urls/category/{entityId}/edit';
$expectedRoutes['admin_pretty_category_delete'] = '/admin/pretty/urls/category/{entityId}/delete';
$expectedRoutes['admin_pretty_category_batchDelete'] = '/admin/pretty/urls/category/batchDelete';
$expectedRoutes['admin_pretty_category_autocomplete'] = '/admin/pretty/urls/category/autocomplete';
// these are the routes related to the User entity; this is not used by DashboardController, but they are created
// anyways because EasyAdmin creates routes for all dashboards + CRUD controllers by default (this can be avoided
// by setting the 'allowedControllers' option in the #[AdminDashboard] attribute)
$expectedRoutes['admin_pretty_category_edit'] = '/admin/pretty/urls/category/{entityId}/edit';
$expectedRoutes['admin_pretty_category_delete'] = '/admin/pretty/urls/category/{entityId}/delete';
$expectedRoutes['admin_pretty_category_detail'] = '/admin/pretty/urls/category/{entityId}';
$expectedRoutes['admin_pretty_external_user_editor_custom_route_for_index'] = '/admin/pretty/urls/user-editor/custom/path-for-index';
$expectedRoutes['admin_pretty_external_user_editor_custom_route_for_new'] = '/admin/pretty/urls/user-editor/new';
$expectedRoutes['admin_pretty_external_user_editor_batchDelete'] = '/admin/pretty/urls/user-editor/batchDelete';
$expectedRoutes['admin_pretty_external_user_editor_autocomplete'] = '/admin/pretty/urls/user-editor/autocomplete';
$expectedRoutes['admin_pretty_external_user_editor_edit'] = '/admin/pretty/urls/user-editor/{entityId}/edit';
$expectedRoutes['admin_pretty_external_user_editor_delete'] = '/admin/pretty/urls/user-editor/{entityId}/delete';
$expectedRoutes['admin_pretty_external_user_editor_detail'] = '/admin/pretty/urls/user-editor/custom/path-for-detail/{entityId}';
// the fully-customized routes of the SecondDashboardController; EasyAdmin only generates routes for the User
// entity because it's the only one allowed by the 'allowedControllers' option in the #[AdminDashboard] attribute
$expectedRoutes['second_dashboard'] = '/second/dashboard';
$expectedRoutes['admin_pretty_external_user_editor_foobar'] = '/admin/pretty/urls/user-editor/bar/foo';
$expectedRoutes['second_dashboard_external_user_editor_custom_route_for_index'] = '/second/dashboard/user-editor/custom/path-for-index';
$expectedRoutes['second_dashboard_external_user_editor_custom_route_for_new'] = '/second/dashboard/user-editor/add-new';
$expectedRoutes['second_dashboard_external_user_editor_batchDelete'] = '/second/dashboard/user-editor/batchDelete';
$expectedRoutes['second_dashboard_external_user_editor_autocomplete'] = '/second/dashboard/user-editor/autocomplete';
$expectedRoutes['second_dashboard_external_user_editor_change'] = '/second/dashboard/user-editor/edit/---{entityId}---';
$expectedRoutes['second_dashboard_external_user_editor_delete_this_now'] = '/second/dashboard/user-editor/{entityId}/delete';
$expectedRoutes['second_dashboard_external_user_editor_detail'] = '/second/dashboard/user-editor/custom/path-for-detail/{entityId}';
$expectedRoutes['admin_pretty_external_user_editor_foobar'] = '/admin/pretty/urls/user-editor/bar/foo';
$expectedRoutes['second_dashboard_external_user_editor_foobar'] = '/second/dashboard/user-editor/bar/foo';

self::bootKernel();
Expand All @@ -65,10 +68,7 @@ public function testGeneratedRoutes()
$generatedRoutes[$name] = $route->getPath();
}

ksort($generatedRoutes);
ksort($expectedRoutes);

$this->assertEquals($expectedRoutes, $generatedRoutes);
$this->assertSame($expectedRoutes, $generatedRoutes);
}

public function testDefaultWelcomePage()
Expand Down

0 comments on commit e1025aa

Please sign in to comment.