From 57a24f31976af3d33114f53e10b4b6930ad06e92 Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Sun, 10 Jul 2022 12:50:51 +0200 Subject: [PATCH 1/3] Allow to configure routeName and routePattern dynamically --- src/Admin/AbstractAdmin.php | 141 ++++++++++++++++++++---------------- 1 file changed, 77 insertions(+), 64 deletions(-) diff --git a/src/Admin/AbstractAdmin.php b/src/Admin/AbstractAdmin.php index 89efcfc14c..9f52a9d691 100644 --- a/src/Admin/AbstractAdmin.php +++ b/src/Admin/AbstractAdmin.php @@ -105,6 +105,8 @@ abstract class AbstractAdmin extends AbstractTaggedAdmin implements AdminInterfa private const DEFAULT_LIST_PER_PAGE_OPTIONS = [10, 25, 50, 100, 250]; /** + * @deprecated since sonata-project/admin-bundle 4.x, will be removed in 5.0. + * * The base route name used to generate the routing information. * * @var string|null @@ -112,6 +114,8 @@ abstract class AbstractAdmin extends AbstractTaggedAdmin implements AdminInterfa protected $baseRouteName; /** + * @deprecated since sonata-project/admin-bundle 4.x, will be removed in 5.0. + * * The base route pattern used to generate the routing information. * * @var string|null @@ -539,43 +543,14 @@ final public function getBaseRoutePattern(): string } if ($this->isChild()) { // the admin class is a child, prefix it with the parent route pattern - $baseRoutePattern = $this->baseRoutePattern; - if (null === $baseRoutePattern) { - preg_match(self::CLASS_REGEX, $this->getModelClass(), $matches); - - if (!$matches) { - throw new \LogicException(sprintf( - 'Please define a default `baseRoutePattern` value for the admin class `%s`', - static::class - )); - } - $baseRoutePattern = $this->urlize($matches[5], '-'); - } - $this->cachedBaseRoutePattern = sprintf( '%s/%s/%s', $this->getParent()->getBaseRoutePattern(), $this->getParent()->getRouterIdParameter(), - $baseRoutePattern + $this->generateBaseRoutePattern(true) ); - } elseif (null !== $this->baseRoutePattern) { - $this->cachedBaseRoutePattern = $this->baseRoutePattern; } else { - preg_match(self::CLASS_REGEX, $this->getModelClass(), $matches); - - if (!$matches) { - throw new \LogicException(sprintf( - 'Please define a default `baseRoutePattern` value for the admin class `%s`', - static::class - )); - } - - $this->cachedBaseRoutePattern = sprintf( - '/%s%s/%s', - '' === $matches[1] ? '' : $this->urlize($matches[1], '-').'/', - $this->urlize($matches[3], '-'), - $this->urlize($matches[5], '-') - ); + $this->cachedBaseRoutePattern = $this->generateBaseRoutePattern(); } return $this->cachedBaseRoutePattern; @@ -593,44 +568,13 @@ final public function getBaseRouteName(): string } if ($this->isChild()) { // the admin class is a child, prefix it with the parent route name - $baseRouteName = $this->baseRouteName; - if (null === $baseRouteName) { - preg_match(self::CLASS_REGEX, $this->getModelClass(), $matches); - - if (!$matches) { - throw new \LogicException(sprintf( - 'Cannot automatically determine base route name,' - .' please define a default `baseRouteName` value for the admin class `%s`', - static::class - )); - } - $baseRouteName = $this->urlize($matches[5]); - } - $this->cachedBaseRouteName = sprintf( '%s_%s', $this->getParent()->getBaseRouteName(), - $baseRouteName + $this->generateBaseRouteName(true) ); - } elseif (null !== $this->baseRouteName) { - $this->cachedBaseRouteName = $this->baseRouteName; } else { - preg_match(self::CLASS_REGEX, $this->getModelClass(), $matches); - - if (!$matches) { - throw new \LogicException(sprintf( - 'Cannot automatically determine base route name,' - .' please define a default `baseRouteName` value for the admin class `%s`', - static::class - )); - } - - $this->cachedBaseRouteName = sprintf( - 'admin_%s%s_%s', - '' === $matches[1] ? '' : $this->urlize($matches[1]).'_', - $this->urlize($matches[3]), - $this->urlize($matches[5]) - ); + $this->cachedBaseRouteName = $this->generateBaseRouteName(); } return $this->cachedBaseRouteName; @@ -1856,6 +1800,75 @@ protected function configure(): void { } + protected function generateBaseRoutePattern(bool $isChildAdmin = false): string + { + // NEXT_MAJOR: Remove this code + if (null !== $this->baseRoutePattern) { + @trigger_error(sprintf( + 'Overriding the baseRoutePattern property is deprecated since sonata-project/admin-bundle 4.x.' + .' You MUST override the method %s() instead.', + __METHOD__ + ), \E_USER_DEPRECATED); + + return $this->baseRoutePattern; + } + + preg_match(self::CLASS_REGEX, $this->getModelClass(), $matches); + + if (!$matches) { + throw new \LogicException(sprintf( + 'Please define a default `baseRoutePattern` value for the admin class `%s`', + static::class + )); + } + + if ($isChildAdmin) { + return $this->urlize($matches[5]); + } + + return $this->cachedBaseRoutePattern = sprintf( + '/%s%s/%s', + '' === $matches[1] ? '' : $this->urlize($matches[1], '-').'/', + $this->urlize($matches[3], '-'), + $this->urlize($matches[5], '-') + ); + } + + protected function generateBaseRouteName(bool $isChildAdmin = false): string + { + // NEXT_MAJOR: Remove this code + if (null !== $this->baseRouteName) { + @trigger_error(sprintf( + 'Overriding the baseRouteName property is deprecated since sonata-project/admin-bundle 4.x.' + .' You MUST override the method %s() instead.', + __METHOD__ + ), \E_USER_DEPRECATED); + + return $this->baseRouteName; + } + + preg_match(self::CLASS_REGEX, $this->getModelClass(), $matches); + + if (!$matches) { + throw new \LogicException(sprintf( + 'Cannot automatically determine base route name,' + .' please define a default `baseRouteName` value for the admin class `%s`', + static::class + )); + } + + if ($isChildAdmin) { + return $this->urlize($matches[5]); + } + + return sprintf( + 'admin_%s%s_%s', + '' === $matches[1] ? '' : $this->urlize($matches[1]).'_', + $this->urlize($matches[3]), + $this->urlize($matches[5]) + ); + } + /** * @phpstan-return T */ From 4d6368117e40d9f8aa0866e02f9e290ecf28adde Mon Sep 17 00:00:00 2001 From: Jordi Sala Morales Date: Thu, 14 Jul 2022 22:46:37 +0200 Subject: [PATCH 2/3] Apply suggestions from code review --- src/Admin/AbstractAdmin.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Admin/AbstractAdmin.php b/src/Admin/AbstractAdmin.php index 9f52a9d691..b8fc155492 100644 --- a/src/Admin/AbstractAdmin.php +++ b/src/Admin/AbstractAdmin.php @@ -1823,10 +1823,10 @@ protected function generateBaseRoutePattern(bool $isChildAdmin = false): string } if ($isChildAdmin) { - return $this->urlize($matches[5]); + return $this->urlize($matches[5], '-'); } - return $this->cachedBaseRoutePattern = sprintf( + return sprintf( '/%s%s/%s', '' === $matches[1] ? '' : $this->urlize($matches[1], '-').'/', $this->urlize($matches[3], '-'), From e46cfdedbacec182955977acca66028acb394e5f Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Wed, 20 Jul 2022 13:05:17 +0200 Subject: [PATCH 3/3] Fix tests and docs --- docs/reference/routing.rst | 41 ++++++++++++++----- tests/App/Admin/AdminAsParameterAdmin.php | 11 ++++- tests/App/Admin/EmptyAdmin.php | 11 ++++- .../Admin/FooAdminWithCustomController.php | 11 ++++- .../Admin/CommentWithCustomRouteAdmin.php | 11 ++++- .../Admin/PostWithCustomRouteAdmin.php | 11 ++++- 6 files changed, 75 insertions(+), 21 deletions(-) diff --git a/docs/reference/routing.rst b/docs/reference/routing.rst index f7a93c7a96..5779f8a320 100644 --- a/docs/reference/routing.rst +++ b/docs/reference/routing.rst @@ -15,15 +15,19 @@ Routing Definition Route names ^^^^^^^^^^^ -You can set a ``baseRouteName`` property inside your ``Admin`` class. This -represents the route prefix, to which an underscore and the action name will +You can override the ``generateBaseRouteName()`` method inside your ``Admin`` class. +This represents the route prefix, to which an underscore and the action name will be added to generate the actual route names:: // src/Admin/PostAdmin.php final class PostAdmin extends AbstractAdmin { - protected $baseRouteName = 'sonata_post'; + protected function generateBaseRouteName(bool $isChildAdmin = false): string + { + return 'sonata_post'; + } + // will result in routes named: // sonata_post_list // sonata_post_create @@ -36,8 +40,8 @@ be added to generate the actual route names:: This is the internal *name* given to a route (it has nothing to do with the route's visible *URL*). -If no ``baseRouteName`` is defined then the Admin will generate one for you, -based on the following format: 'admin_vendor_bundlename_entityname' so you will have +By default the Admin will generate the route name for you, based on +the following format: 'admin_vendor_bundlename_entityname' so you will have route names for your actions like 'admin_vendor_bundlename_entityname_list'. If the Admin fails to find a baseRouteName for your Admin class a ``RuntimeException`` @@ -51,7 +55,10 @@ be prefixed by the parent route name, example:: // The parent admin class final class PostAdmin extends AbstractAdmin { - protected $baseRouteName = 'sonata_post'; + protected function generateBaseRouteName(bool $isChildAdmin = false): string + { + return 'sonata_post'; + } } .. code-block:: php @@ -61,7 +68,10 @@ be prefixed by the parent route name, example:: // The child admin class final class CommentAdmin extends AbstractAdmin { - protected $baseRouteName = 'comment' + protected function generateBaseRouteName(bool $isChildAdmin = false): string + { + return 'comment'; + } // will result in routes named : // sonata_post_comment_list // sonata_post_comment_create @@ -73,7 +83,7 @@ be prefixed by the parent route name, example:: Route patterns (URLs) ^^^^^^^^^^^^^^^^^^^^^ -You can use ``baseRoutePattern`` to set a custom URL for a given ``Admin`` class. +You can override the ``generateBaseRoutePattern()`` method to set a custom URL for a given ``Admin`` class. For example, to use ``http://yourdomain.com/admin/foo`` as the base URL for the ``FooAdmin`` class (instead of the default of ``http://yourdomain.com/admin/vendor/bundle/foo``) @@ -83,7 +93,10 @@ use the following code:: final class FooAdmin extends AbstractAdmin { - protected $baseRoutePattern = 'foo'; + protected function generateBaseRoutePattern(bool $isChildAdmin = false): string + { + return 'foo'; + } } You will then have route URLs like ``http://yourdomain.com/admin/foo/list`` and @@ -97,7 +110,10 @@ be prefixed by the parent route pattern, example:: // The parent admin class final class PostAdmin extends AbstractAdmin { - protected $baseRoutePattern = 'post'; + protected function generateBaseRoutePattern(bool $isChildAdmin = false): string + { + return 'post'; + } // ... } @@ -108,7 +124,10 @@ be prefixed by the parent route pattern, example:: // The child admin class final class CommentAdmin extends AbstractAdmin { - protected $baseRoutePattern = 'comment' + protected function generateBaseRoutePattern(bool $isChildAdmin = false): string + { + return 'comment'; + } // ... } diff --git a/tests/App/Admin/AdminAsParameterAdmin.php b/tests/App/Admin/AdminAsParameterAdmin.php index 2895db84c0..4d7cc167b3 100644 --- a/tests/App/Admin/AdminAsParameterAdmin.php +++ b/tests/App/Admin/AdminAsParameterAdmin.php @@ -22,8 +22,15 @@ */ final class AdminAsParameterAdmin extends AbstractAdmin { - protected $baseRoutePattern = 'tests/app/admin-as-parameter'; - protected $baseRouteName = 'admin_admin_as_parameter'; + protected function generateBaseRoutePattern(bool $isChildAdmin = false): string + { + return 'tests/app/admin-as-parameter'; + } + + protected function generateBaseRouteName(bool $isChildAdmin = false): string + { + return 'admin_admin_as_parameter'; + } protected function configureRoutes(RouteCollectionInterface $collection): void { diff --git a/tests/App/Admin/EmptyAdmin.php b/tests/App/Admin/EmptyAdmin.php index 42d176bf6b..4c034c39ee 100644 --- a/tests/App/Admin/EmptyAdmin.php +++ b/tests/App/Admin/EmptyAdmin.php @@ -23,8 +23,15 @@ */ final class EmptyAdmin extends AbstractAdmin { - protected $baseRoutePattern = 'empty'; - protected $baseRouteName = 'admin_empty'; + protected function generateBaseRoutePattern(bool $isChildAdmin = false): string + { + return 'empty'; + } + + protected function generateBaseRouteName(bool $isChildAdmin = false): string + { + return 'admin_empty'; + } protected function configureListFields(ListMapper $list): void { diff --git a/tests/App/Admin/FooAdminWithCustomController.php b/tests/App/Admin/FooAdminWithCustomController.php index 5bfbe55f51..3ca7cfc70f 100644 --- a/tests/App/Admin/FooAdminWithCustomController.php +++ b/tests/App/Admin/FooAdminWithCustomController.php @@ -15,6 +15,13 @@ final class FooAdminWithCustomController extends FooAdmin { - protected $baseRoutePattern = 'tests/app/foo-with-custom-controller'; - protected $baseRouteName = 'admin_foo_with_custom_controller'; + protected function generateBaseRoutePattern(bool $isChildAdmin = false): string + { + return 'tests/app/foo-with-custom-controller'; + } + + protected function generateBaseRouteName(bool $isChildAdmin = false): string + { + return 'admin_foo_with_custom_controller'; + } } diff --git a/tests/Fixtures/Admin/CommentWithCustomRouteAdmin.php b/tests/Fixtures/Admin/CommentWithCustomRouteAdmin.php index db8fb12b30..dbb5f9d9df 100644 --- a/tests/Fixtures/Admin/CommentWithCustomRouteAdmin.php +++ b/tests/Fixtures/Admin/CommentWithCustomRouteAdmin.php @@ -15,6 +15,13 @@ final class CommentWithCustomRouteAdmin extends CommentAdmin { - protected $baseRoutePattern = 'comment-custom'; - protected $baseRouteName = 'comment_custom'; + protected function generateBaseRoutePattern(bool $isChildAdmin = false): string + { + return 'comment-custom'; + } + + protected function generateBaseRouteName(bool $isChildAdmin = false): string + { + return 'comment_custom'; + } } diff --git a/tests/Fixtures/Admin/PostWithCustomRouteAdmin.php b/tests/Fixtures/Admin/PostWithCustomRouteAdmin.php index 53d2fdb925..606ee8ff44 100644 --- a/tests/Fixtures/Admin/PostWithCustomRouteAdmin.php +++ b/tests/Fixtures/Admin/PostWithCustomRouteAdmin.php @@ -15,6 +15,13 @@ final class PostWithCustomRouteAdmin extends PostAdmin { - protected $baseRoutePattern = '/post-custom'; - protected $baseRouteName = 'post_custom'; + protected function generateBaseRoutePattern(bool $isChildAdmin = false): string + { + return '/post-custom'; + } + + protected function generateBaseRouteName(bool $isChildAdmin = false): string + { + return 'post_custom'; + } }