Skip to content

Commit

Permalink
Allow passing options from template to the MenuBuilder
Browse files Browse the repository at this point in the history
We were building a menu were we needed to pass some variables from our view to the knp_menu_render function. However in the builder for that menu, the $options array was always empty. With these changes the options successfully get passed through
  • Loading branch information
gnat42 committed Jun 8, 2024
1 parent c39403f commit a2e234c
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 11 deletions.
16 changes: 9 additions & 7 deletions src/Knp/Menu/Twig/Helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public function get($menu, array $path = [], array $options = []): ItemInterface
*/
public function render($menu, array $options = [], ?string $renderer = null): string
{
$menu = $this->castMenu($menu);
$menu = $this->castMenu($menu, $options);

return $this->rendererProvider->get($renderer)->render($menu, $options);
}
Expand Down Expand Up @@ -101,13 +101,13 @@ public function render($menu, array $options = [], ?string $renderer = null): st
*
* @phpstan-return list<array{label: string, uri: string|null, item: ItemInterface|null}>
*/
public function getBreadcrumbsArray($menu, $subItem = null): array
public function getBreadcrumbsArray($menu, $subItem = null, array $options = []): array
{
if (null === $this->menuManipulator) {
throw new \BadMethodCallException('The menu manipulator must be set to get the breadcrumbs array');
}

$menu = $this->castMenu($menu);
$menu = $this->castMenu($menu, $options);

return $this->menuManipulator->getBreadcrumbsArray($menu, $subItem);
}
Expand All @@ -116,18 +116,20 @@ public function getBreadcrumbsArray($menu, $subItem = null): array
* Returns the current item of a menu.
*
* @param ItemInterface|string|array<ItemInterface|string> $menu
* @param array<string, mixed> $options
*/
public function getCurrentItem($menu): ?ItemInterface
public function getCurrentItem($menu, array $options = []): ?ItemInterface
{
$menu = $this->castMenu($menu);
$menu = $this->castMenu($menu, $options);

return $this->retrieveCurrentItem($menu);
}

/**
* @param ItemInterface|string|array<ItemInterface|string> $menu
* @param array<string, mixed> $options
*/
private function castMenu($menu): ItemInterface
private function castMenu($menu, array $options = []): ItemInterface
{
if (!$menu instanceof ItemInterface) {
$path = [];
Expand All @@ -139,7 +141,7 @@ private function castMenu($menu): ItemInterface
$menu = \array_shift($path);
}

return $this->get($menu, $path);
return $this->get($menu, $path, $options);
}

return $menu;
Expand Down
10 changes: 6 additions & 4 deletions src/Knp/Menu/Twig/MenuExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,25 +78,27 @@ public function render($menu, array $options = [], ?string $renderer = null): st
*
* @param ItemInterface|string|array<ItemInterface|string> $menu
* @param string|array<string|null>|null $subItem
* @param array<string, mixed> $options
*
* @phpstan-param string|ItemInterface|array<int|string, string|int|float|null|array{label: string, url: string|null, item: ItemInterface|null}|ItemInterface>|\Traversable<string|int|float|null|array{label: string, url: string|null, item: ItemInterface|null}|ItemInterface> $subItem
*
* @return array<int, array<string, mixed>>
* @phpstan-return list<array{label: string, uri: string|null, item: ItemInterface|null}>
*/
public function getBreadcrumbsArray($menu, $subItem = null): array
public function getBreadcrumbsArray($menu, $subItem = null, array $options = []): array
{
return $this->helper->getBreadcrumbsArray($menu, $subItem);
return $this->helper->getBreadcrumbsArray($menu, $subItem, $options);
}

/**
* Returns the current item of a menu.
*
* @param ItemInterface|string $menu
* @param array<string, mixed> $options
*/
public function getCurrentItem($menu): ItemInterface
public function getCurrentItem($menu, array $options = []): ItemInterface
{
$rootItem = $this->get($menu);
$rootItem = $this->get($menu, [], $options);

$currentItem = $this->helper->getCurrentItem($rootItem);

Expand Down
73 changes: 73 additions & 0 deletions tests/Knp/Menu/Tests/Twig/HelperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,33 @@ public function testRenderMenuWithOptions(): void
$this->assertEquals('<p>foobar</p>', $helper->render($menu, ['firstClass' => 'test']));
}

public function testRenderMenuByNameWithOptions(): void
{
$menu = $this->getMockBuilder(ItemInterface::class)->getMock();
$renderer = $this->getMockBuilder(RendererInterface::class)->getMock();
$renderer->expects($this->once())
->method('render')
->with($menu, ['firstClass' => 'test'])
->willReturn('<p>foobar</p>')
;

$menuProvider = $this->createMock(MenuProviderInterface::class);
$menuProvider->expects($this->once())
->method('get')
->with('menu', ['firstClass' => 'test'])
->willReturn($menu);
$rendererProvider = $this->getMockBuilder(RendererProviderInterface::class)->getMock();
$rendererProvider->expects($this->once())
->method('get')
->with(null)
->willReturn($renderer)
;

$helper = new Helper($rendererProvider, $menuProvider);

$this->assertEquals('<p>foobar</p>', $helper->render('menu', ['firstClass' => 'test']));
}

public function testRenderMenuWithRenderer(): void
{
$menu = $this->getMockBuilder(ItemInterface::class)->getMock();
Expand Down Expand Up @@ -254,6 +281,27 @@ public function testBreadcrumbsArray(): void
$this->assertEquals(['A', 'B'], $helper->getBreadcrumbsArray($menu));
}

public function testBreadcrumbsArrayWithOptions(): void
{
$menu = $this->getMockBuilder(ItemInterface::class)->getMock();

$manipulator = $this->getMockBuilder(MenuManipulator::class)->getMock();
$manipulator->expects($this->once())
->method('getBreadcrumbsArray')
->with($menu)
->willReturn(['A', 'B']);

$menuProvider = $this->createMock(MenuProviderInterface::class);
$menuProvider->expects($this->once())
->method('get')
->with('menu', ['option' => 'value'])
->willReturn($menu);

$helper = new Helper($this->getMockBuilder(RendererProviderInterface::class)->getMock(), $menuProvider, $manipulator);

$this->assertEquals(['A', 'B'], $helper->getBreadcrumbsArray('menu', null, ['option'=>'value']));
}

public function testCurrentItemWithoutMatcher(): void
{
$this->expectException(\BadMethodCallException::class);
Expand All @@ -280,4 +328,29 @@ public function testCurrentItem(): void

$this->assertSame('c2_2_2', $helper->getCurrentItem($menu)->getName());
}

public function testCurrentItemWithOptions(): void
{
$matcher = new Matcher();

$menu = new MenuItem('root', new MenuFactory());
$menu->addChild('c1');
$menu['c1']->addChild('c1_1');
$menu->addChild('c2');
$menu['c2']->addChild('c2_1');
$menu['c2']->addChild('c2_2');
$menu['c2']['c2_2']->addChild('c2_2_1');
$menu['c2']['c2_2']->addChild('c2_2_2')->setCurrent(true);
$menu['c2']['c2_2']->addChild('c2_2_3');

$menuProvider = $this->createMock(MenuProviderInterface::class);
$menuProvider->expects($this->once())
->method('get')
->with('$menu', ['option' => 'value'])
->willReturn($menu);

$helper = new Helper($this->getMockBuilder(RendererProviderInterface::class)->getMock(), $menuProvider, null, $matcher);

$this->assertSame('c2_2_2', $helper->getCurrentItem('$menu', ['option'=>'value'])->getName());
}
}

0 comments on commit a2e234c

Please sign in to comment.