Skip to content
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
7 changes: 6 additions & 1 deletion src/Menu/Provider/GroupMenuProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
Expand Down Expand Up @@ -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
Comment thread
phansys marked this conversation as resolved.
);
$options['extras'] = [
'label_catalogue' => $admin->getTranslationDomain(),
'admin' => $admin,
Expand Down
8 changes: 6 additions & 2 deletions src/Route/DefaultRouteGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -116,7 +120,7 @@ public function generateMenuUrl(
return [
'route' => $this->caches[$code],
'routeParameters' => $parameters,
'routeAbsolute' => $absolute,
'routeAbsolute' => UrlGeneratorInterface::ABSOLUTE_URL === $absolute,
Comment thread
greg0ire marked this conversation as resolved.
];
}

Expand Down
136 changes: 115 additions & 21 deletions tests/Menu/Provider/GroupMenuProviderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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']);
Expand Down Expand Up @@ -255,19 +271,22 @@ 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']);
$this->assertSame('foo_admin_label', $menu['foo_admin_label']->getLabel());

$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());
}

/**
Expand Down Expand Up @@ -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());
}

/**
Expand Down Expand Up @@ -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());
}

/**
Expand Down Expand Up @@ -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 [
[
Expand All @@ -392,6 +435,7 @@ public function getAdminGroups()
[
'admin' => 'sonata_admin_foo_service',
'label' => 'fooLabel',
'route' => 'FooServiceRoute',
'route_absolute' => true,
],
[
Expand All @@ -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'],
Expand All @@ -410,10 +462,7 @@ public function getAdminGroups()
];
}

/**
* @return array
*/
public function getAdminGroupsMultipleRoles()
public function getAdminGroupsMultipleRoles(): array
{
return [
[
Expand Down Expand Up @@ -506,10 +555,7 @@ public function getAdminGroupsMultipleRoles()
];
}

/**
* @return array
*/
public function getAdminGroupsMultipleRolesOnTop()
public function getAdminGroupsMultipleRolesOnTop(): array
{
return [
[
Expand Down Expand Up @@ -570,10 +616,7 @@ public function getAdminGroupsMultipleRolesOnTop()
];
}

/**
* @return array
*/
public function getAdminGroupsWithOnTopOption()
public function getAdminGroupsWithOnTopOption(): array
{
return [
[
Expand All @@ -597,6 +640,47 @@ public function getAdminGroupsWithOnTopOption()
];
}

public function getRootMenuItemWithDifferentUrlTypes(): iterable
{
yield 'absolute_url' => [
'http://sonata-project/list',
[
'label' => 'foo',
'icon' => '<i class="fa fa-edit"></i>',
'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' => '<i class="fa fa-edit"></i>',
'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);
Expand All @@ -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')
Expand Down
26 changes: 20 additions & 6 deletions tests/Route/DefaultRouteGeneratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@

class DefaultRouteGeneratorTest extends TestCase
{
private const ROUTER_DOMAIN = 'http://sonata-project';

protected $cacheTempFolder;

public function setUp(): void
Expand All @@ -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');

Expand All @@ -74,32 +80,40 @@ 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;
}
});

$cache = new RoutesCache($this->cacheTempFolder, true);

$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
{
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,
],
];
}

Expand Down