Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow to configure routeName and routePattern dynamically #7867

Merged
merged 3 commits into from
Jul 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 30 additions & 11 deletions docs/reference/routing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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``
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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``)
Expand All @@ -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
Expand All @@ -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';
}
// ...
}

Expand All @@ -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';
}
// ...
}

Expand Down
141 changes: 77 additions & 64 deletions src/Admin/AbstractAdmin.php
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,17 @@ 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
*/
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
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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 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
*/
Expand Down
11 changes: 9 additions & 2 deletions tests/App/Admin/AdminAsParameterAdmin.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down
11 changes: 9 additions & 2 deletions tests/App/Admin/EmptyAdmin.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down
11 changes: 9 additions & 2 deletions tests/App/Admin/FooAdminWithCustomController.php
Original file line number Diff line number Diff line change
Expand Up @@ -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';
}
}
11 changes: 9 additions & 2 deletions tests/Fixtures/Admin/CommentWithCustomRouteAdmin.php
Original file line number Diff line number Diff line change
Expand Up @@ -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';
}
}
11 changes: 9 additions & 2 deletions tests/Fixtures/Admin/PostWithCustomRouteAdmin.php
Original file line number Diff line number Diff line change
Expand Up @@ -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';
}
}