diff --git a/src/Menu/Provider/GroupMenuProvider.php b/src/Menu/Provider/GroupMenuProvider.php
index 50405ccb5e..fe07cacd30 100644
--- a/src/Menu/Provider/GroupMenuProvider.php
+++ b/src/Menu/Provider/GroupMenuProvider.php
@@ -17,6 +17,7 @@
use Knp\Menu\ItemInterface;
use Knp\Menu\Provider\MenuProviderInterface;
use Sonata\AdminBundle\Admin\Pool;
+use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
/**
@@ -172,7 +173,11 @@ private function generateMenuItem(array $item, array $group): ItemInterface
if (isset($item['admin']) && !empty($item['admin'])) {
$admin = $this->pool->getInstance($item['admin']);
- $options = $admin->generateMenuUrl('list', [], $item['route_absolute']);
+ $options = $admin->generateMenuUrl(
+ 'list',
+ [],
+ $item['route_absolute'] ? UrlGeneratorInterface::ABSOLUTE_URL : UrlGeneratorInterface::ABSOLUTE_PATH
+ );
$options['extras'] = [
'label_catalogue' => $admin->getTranslationDomain(),
'admin' => $admin,
diff --git a/src/Route/DefaultRouteGenerator.php b/src/Route/DefaultRouteGenerator.php
index c6668ce8a5..edf666d856 100644
--- a/src/Route/DefaultRouteGenerator.php
+++ b/src/Route/DefaultRouteGenerator.php
@@ -63,7 +63,11 @@ public function generateUrl(
) {
$arrayRoute = $this->generateMenuUrl($admin, $name, $parameters, $absolute);
- return $this->router->generate($arrayRoute['route'], $arrayRoute['routeParameters'], $arrayRoute['routeAbsolute']);
+ return $this->router->generate(
+ $arrayRoute['route'],
+ $arrayRoute['routeParameters'],
+ $arrayRoute['routeAbsolute'] ? UrlGeneratorInterface::ABSOLUTE_URL : UrlGeneratorInterface::ABSOLUTE_PATH
+ );
}
public function generateMenuUrl(
@@ -116,7 +120,7 @@ public function generateMenuUrl(
return [
'route' => $this->caches[$code],
'routeParameters' => $parameters,
- 'routeAbsolute' => $absolute,
+ 'routeAbsolute' => UrlGeneratorInterface::ABSOLUTE_URL === $absolute,
];
}
diff --git a/tests/Menu/Provider/GroupMenuProviderTest.php b/tests/Menu/Provider/GroupMenuProviderTest.php
index 76c75c177e..43e242d242 100644
--- a/tests/Menu/Provider/GroupMenuProviderTest.php
+++ b/tests/Menu/Provider/GroupMenuProviderTest.php
@@ -14,6 +14,7 @@
namespace Sonata\AdminBundle\Tests\Menu\Provider;
use Knp\Menu\FactoryInterface;
+use Knp\Menu\Integration\Symfony\RoutingExtension;
use Knp\Menu\ItemInterface;
use Knp\Menu\MenuFactory;
use Knp\Menu\MenuItem;
@@ -23,6 +24,7 @@
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Admin\Pool;
use Sonata\AdminBundle\Menu\Provider\GroupMenuProvider;
+use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
class GroupMenuProviderTest extends TestCase
@@ -56,6 +58,20 @@ protected function setUp(): void
$this->factory = new MenuFactory();
+ $urlGenerator = $this->createStub(UrlGeneratorInterface::class);
+ $urlGenerator->method('generate')->willReturnCallback(static function (string $name, array $parameters = [], int $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH): string {
+ switch ($referenceType) {
+ case UrlGeneratorInterface::ABSOLUTE_URL:
+ return 'http://sonata-project/'.$name.($parameters ? '?'.http_build_query($parameters) : '');
+ case UrlGeneratorInterface::ABSOLUTE_PATH:
+ return '/'.$name.($parameters ? '?'.http_build_query($parameters) : '');
+ default:
+ throw new \InvalidArgumentException(sprintf('Dummy router does not support the reference type "%s".', $referenceType));
+ }
+ });
+
+ $this->factory->addExtension(new RoutingExtension($urlGenerator));
+
$this->provider = new GroupMenuProvider($this->factory, $this->pool, $this->checker);
}
@@ -92,7 +108,7 @@ public function testGroupMenuProviderWithoutChecker(array $adminGroups): void
$children = $menu->getChildren();
- $this->assertCount(2, $children);
+ $this->assertCount(3, $children);
$this->assertArrayHasKey('foo_admin_label', $children);
$this->assertArrayHasKey('route_label', $children);
$this->assertInstanceOf(MenuItem::class, $menu['foo_admin_label']);
@@ -255,7 +271,7 @@ public function testGetMenuProviderWithAdmin(array $adminGroups): void
$children = $menu->getChildren();
- $this->assertCount(2, $children);
+ $this->assertCount(3, $children);
$this->assertArrayHasKey('foo_admin_label', $children);
$this->assertArrayHasKey('route_label', $children);
$this->assertInstanceOf(MenuItem::class, $menu['foo_admin_label']);
@@ -263,11 +279,14 @@ public function testGetMenuProviderWithAdmin(array $adminGroups): void
$extras = $menu['foo_admin_label']->getExtras();
$this->assertArrayHasKey('label_catalogue', $extras);
- $this->assertSame($extras['label_catalogue'], 'SonataAdminBundle');
+ $this->assertSame('SonataAdminBundle', $extras['label_catalogue']);
$extras = $menu['route_label']->getExtras();
$this->assertArrayHasKey('label_catalogue', $extras);
- $this->assertSame($extras['label_catalogue'], 'SonataAdminBundle');
+ $this->assertSame('SonataAdminBundle', $extras['label_catalogue']);
+
+ $this->assertSame('http://sonata-project/FooRoute?foo=bar', $menu['route_label']->getUri());
+ $this->assertSame('/FooRelativeRoute?baz=qux', $menu['relative_route']->getUri());
}
/**
@@ -295,7 +314,7 @@ public function testGetKnpMenuWithListRoute(array $adminGroups): void
$this->assertInstanceOf(ItemInterface::class, $menu);
$this->assertArrayNotHasKey('foo_admin_label', $menu->getChildren());
$this->assertArrayHasKey('route_label', $menu->getChildren());
- $this->assertCount(1, $menu->getChildren());
+ $this->assertCount(2, $menu->getChildren());
}
/**
@@ -323,7 +342,7 @@ public function testGetKnpMenuWithGrantedList(array $adminGroups): void
$this->assertInstanceOf(ItemInterface::class, $menu);
$this->assertArrayNotHasKey('foo_admin_label', $menu->getChildren());
$this->assertArrayHasKey('route_label', $menu->getChildren());
- $this->assertCount(1, $menu->getChildren());
+ $this->assertCount(2, $menu->getChildren());
}
/**
@@ -378,9 +397,33 @@ public function testGetMenuProviderKeepOpenOption(array $adminGroups): void
}
/**
- * @return array
+ * @dataProvider getRootMenuItemWithDifferentUrlTypes
*/
- public function getAdminGroups()
+ public function testRootMenuItemUrl(string $expectedUrl, array $item): void
+ {
+ $this->pool
+ ->method('getInstance')
+ ->with($this->equalTo('sonata_admin_absolute_url'))
+ ->willReturn($this->getAdminMock());
+
+ $this->checker
+ ->method('isGranted')
+ ->willReturn(true);
+
+ $menu = $this->provider->get(
+ 'providerFoo',
+ [
+ 'name' => 'foo',
+ 'group' => $item,
+ ]
+ );
+
+ $this->assertInstanceOf(ItemInterface::class, $menu);
+ $this->assertSame('foo', $menu->getName());
+ $this->assertSame($expectedUrl, $menu['foo_admin_label']->getUri());
+ }
+
+ public function getAdminGroups(): array
{
return [
[
@@ -392,6 +435,7 @@ public function getAdminGroups()
[
'admin' => 'sonata_admin_foo_service',
'label' => 'fooLabel',
+ 'route' => 'FooServiceRoute',
'route_absolute' => true,
],
[
@@ -402,6 +446,14 @@ public function getAdminGroups()
'route_absolute' => true,
'roles' => [],
],
+ [
+ 'admin' => '',
+ 'label' => 'relative_route',
+ 'route' => 'FooRelativeRoute',
+ 'route_params' => ['baz' => 'qux'],
+ 'route_absolute' => false,
+ 'roles' => [],
+ ],
],
'item_adds' => [],
'roles' => ['foo'],
@@ -410,10 +462,7 @@ public function getAdminGroups()
];
}
- /**
- * @return array
- */
- public function getAdminGroupsMultipleRoles()
+ public function getAdminGroupsMultipleRoles(): array
{
return [
[
@@ -506,10 +555,7 @@ public function getAdminGroupsMultipleRoles()
];
}
- /**
- * @return array
- */
- public function getAdminGroupsMultipleRolesOnTop()
+ public function getAdminGroupsMultipleRolesOnTop(): array
{
return [
[
@@ -570,10 +616,7 @@ public function getAdminGroupsMultipleRolesOnTop()
];
}
- /**
- * @return array
- */
- public function getAdminGroupsWithOnTopOption()
+ public function getAdminGroupsWithOnTopOption(): array
{
return [
[
@@ -597,6 +640,47 @@ public function getAdminGroupsWithOnTopOption()
];
}
+ public function getRootMenuItemWithDifferentUrlTypes(): iterable
+ {
+ yield 'absolute_url' => [
+ 'http://sonata-project/list',
+ [
+ 'label' => 'foo',
+ 'icon' => '',
+ 'label_catalogue' => 'SonataAdminBundle',
+ 'items' => [
+ [
+ 'admin' => 'sonata_admin_absolute_url',
+ 'label' => 'fooLabel',
+ 'route' => 'FooAbsoulteRoute',
+ 'route_absolute' => true,
+ ],
+ ],
+ 'item_adds' => [],
+ 'roles' => ['foo'],
+ ],
+ ];
+
+ yield 'absolute_path' => [
+ '/list',
+ [
+ 'label' => 'foo',
+ 'icon' => '',
+ 'label_catalogue' => 'SonataAdminBundle',
+ 'items' => [
+ [
+ 'admin' => 'sonata_admin_absolute_url',
+ 'label' => 'fooLabel',
+ 'route' => 'FooAbsolutePath',
+ 'route_absolute' => false,
+ ],
+ ],
+ 'item_adds' => [],
+ 'roles' => ['foo'],
+ ],
+ ];
+ }
+
private function getAdminMock(bool $hasRoute = true, bool $isGranted = true): AbstractAdmin
{
$admin = $this->createMock(AbstractAdmin::class);
@@ -616,7 +700,17 @@ private function getAdminMock(bool $hasRoute = true, bool $isGranted = true): Ab
$admin
->method('generateMenuUrl')
- ->willReturn([]);
+ ->willReturnCallback(static function (string $name, array $parameters = [], int $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH): array {
+ if (!\in_array($referenceType, [UrlGeneratorInterface::ABSOLUTE_URL, UrlGeneratorInterface::ABSOLUTE_PATH], true)) {
+ throw new \InvalidArgumentException(sprintf('Dummy router does not support the reference type "%s".', $referenceType));
+ }
+
+ return [
+ 'route' => $name,
+ 'routeParameters' => $parameters,
+ 'routeAbsolute' => UrlGeneratorInterface::ABSOLUTE_URL === $referenceType,
+ ];
+ });
$admin
->method('getTranslationDomain')
diff --git a/tests/Route/DefaultRouteGeneratorTest.php b/tests/Route/DefaultRouteGeneratorTest.php
index 7c01c59979..b166f91451 100644
--- a/tests/Route/DefaultRouteGeneratorTest.php
+++ b/tests/Route/DefaultRouteGeneratorTest.php
@@ -26,6 +26,8 @@
class DefaultRouteGeneratorTest extends TestCase
{
+ private const ROUTER_DOMAIN = 'http://sonata-project';
+
protected $cacheTempFolder;
public function setUp(): void
@@ -51,8 +53,12 @@ public function testGenerate(): void
/**
* @dataProvider getGenerateUrlTests
*/
- public function testGenerateUrl(string $expected, string $name, array $parameters): void
- {
+ public function testGenerateUrl(
+ string $expected,
+ string $name,
+ array $parameters,
+ int $referenceType = RouterInterface::ABSOLUTE_PATH
+ ): void {
$childCollection = new RouteCollection('base.Code.Foo|base.Code.Bar', 'admin_acme_child', '/foo/', 'BundleName:ControllerName');
$childCollection->add('bar');
@@ -74,17 +80,18 @@ public function testGenerateUrl(string $expected, string $name, array $parameter
$router = $this->getMockForAbstractClass(RouterInterface::class);
$router->expects($this->once())
->method('generate')
- ->willReturnCallback(static function (string $name, array $parameters = []): string {
+ ->willReturnCallback(static function (string $name, array $parameters = [], int $referenceType = RouterInterface::ABSOLUTE_PATH): string {
$params = '';
+ $domain = RouterInterface::ABSOLUTE_URL === $referenceType ? self::ROUTER_DOMAIN : '';
if (!empty($parameters)) {
$params .= '?'.http_build_query($parameters);
}
switch ($name) {
case 'admin_acme_foo':
- return '/foo'.$params;
+ return $domain.'/foo'.$params;
case 'admin_acme_child_bar':
- return '/foo/bar'.$params;
+ return $domain.'/foo/bar'.$params;
}
});
@@ -92,7 +99,7 @@ public function testGenerateUrl(string $expected, string $name, array $parameter
$generator = new DefaultRouteGenerator($router, $cache);
- $this->assertSame($expected, $generator->generateUrl($admin, $name, $parameters));
+ $this->assertSame($expected, $generator->generateUrl($admin, $name, $parameters, $referenceType));
}
public function getGenerateUrlTests(): array
@@ -100,6 +107,13 @@ public function getGenerateUrlTests(): array
return [
['/foo?abc=a123&efg=e456&default_param=default_val', 'foo', ['default_param' => 'default_val']],
['/foo/bar?abc=a123&efg=e456&default_param=default_val', 'base.Code.Bar.bar', ['default_param' => 'default_val']],
+ ['/foo/bar?abc=a123&efg=e456&default_param=default_val', 'base.Code.Bar.bar', ['default_param' => 'default_val'], RouterInterface::ABSOLUTE_PATH],
+ [
+ self::ROUTER_DOMAIN.'/foo/bar?abc=a123&efg=e456&default_param=default_val',
+ 'base.Code.Bar.bar',
+ ['default_param' => 'default_val'],
+ RouterInterface::ABSOLUTE_URL,
+ ],
];
}