diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index f6ad9b3b..e2f35917 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -62,7 +62,7 @@ jobs: with: php-version: ${{ matrix.php }} - run: | - sed -ri 's/"symfony\/(.+)": "(.+)"/"symfony\/\1": "'${{ matrix.symfony }}'"/' composer.json; + sed -ri '/symfony\/deprecation-contracts/! s/"symfony\/(.+)": "(.+)"/"symfony\/\1": "'${{ matrix.symfony }}'"/' composer.json; if: matrix.symfony - run: composer config minimum-stability dev && composer config prefer-stable true if: matrix.dev diff --git a/composer.json b/composer.json index cf611f96..696e1b7f 100644 --- a/composer.json +++ b/composer.json @@ -20,7 +20,8 @@ } ], "require": { - "php": "^7.3 || ^8.0" + "php": "^7.3 || ^8.0", + "symfony/deprecation-contracts": "^2.4" }, "conflict": { "twig/twig": "<1.40 || >=2,<2.9" diff --git a/doc/01-Basic-Menus.md b/doc/01-Basic-Menus.md index 2714e366..7aee7e8d 100644 --- a/doc/01-Basic-Menus.md +++ b/doc/01-Basic-Menus.md @@ -238,7 +238,7 @@ the second argument to the `render()` method: is an ancestor of the current item. * `currentAsLink` (default: `true`): Whether to render the "current" menu item as link or as span. * `currentClass` (default: `current`) -* `ancestorClass` (default: `current_ancestor`) +* `ancestor_class` (default: `current_ancestor`) (alias: ancestorClass, currently deprecated) * `firstClass` (default: `first`) * `lastClass` (default: `last`) * `compressed` (default: `false`) diff --git a/doc/examples/01_apply_active_class_to_whole_tree.md b/doc/examples/01_apply_active_class_to_whole_tree.md index 15071685..598b4858 100644 --- a/doc/examples/01_apply_active_class_to_whole_tree.md +++ b/doc/examples/01_apply_active_class_to_whole_tree.md @@ -7,12 +7,12 @@ render method of your used renderer: ```php render($item, ['currentClass' => 'active', 'ancestorClass' => 'active']); +$renderer->render($item, ['currentClass' => 'active', 'ancestor_class' => 'active']); ``` or pass it as argument to the constructor of the used renderer: ```php 'active', 'ancestorClass' => 'active']); +$renderer = new Renderer($matcher, ['currentClass' => 'active', 'ancestor_class' => 'active']); ``` diff --git a/src/Knp/Menu/Renderer/ListRenderer.php b/src/Knp/Menu/Renderer/ListRenderer.php index 36068f84..c02a9086 100644 --- a/src/Knp/Menu/Renderer/ListRenderer.php +++ b/src/Knp/Menu/Renderer/ListRenderer.php @@ -31,7 +31,7 @@ public function __construct(MatcherInterface $matcher, array $defaultOptions = [ 'matchingDepth' => null, 'currentAsLink' => true, 'currentClass' => 'current', - 'ancestorClass' => 'current_ancestor', + 'ancestor_class' => 'current_ancestor', 'firstClass' => 'first', 'lastClass' => 'last', 'compressed' => false, @@ -48,6 +48,13 @@ public function render(ItemInterface $item, array $options = []): string { $options = \array_merge($this->defaultOptions, $options); + // Avoid duplication of current_ancestor class. Overwrite value in old config to new one + if (isset($options['ancestorClass'])) { + $options['ancestor_class'] = $options['ancestorClass']; + unset($options['ancestorClass']); + trigger_deprecation('knplabs/knp-menu', '3.3', 'Using "%s" option is deprecated, use "%s" instead.', 'ancestorClass', 'ancestor_class'); + } + $html = $this->renderList($item, $item->getChildrenAttributes(), $options); if ($options['clear_matcher']) { @@ -130,7 +137,11 @@ protected function renderItem(ItemInterface $item, array $options): string if ($this->matcher->isCurrent($item)) { $class[] = $options['currentClass']; } elseif ($this->matcher->isAncestor($item, $options['matchingDepth'])) { - $class[] = $options['ancestorClass']; + if (isset($options['ancestorClass'])) { // Deprecated: it will be removed in future (@see: ancestor_class) + trigger_deprecation('knplabs/knp-menu', '3.3', 'Using "%s" option is deprecated, use "%s" instead.', 'ancestorClass', 'ancestor_class'); + $options['ancestor_class'] = $options['ancestorClass']; + } + $class[] = $options['ancestor_class']; } if ($item->actsLikeFirst()) { diff --git a/src/Knp/Menu/Renderer/RendererInterface.php b/src/Knp/Menu/Renderer/RendererInterface.php index 1855c463..70ee352d 100644 --- a/src/Knp/Menu/Renderer/RendererInterface.php +++ b/src/Knp/Menu/Renderer/RendererInterface.php @@ -16,7 +16,7 @@ interface RendererInterface * 1: only direct children * - currentAsLink: whether the current item should be a link * - currentClass: class added to the current item - * - ancestorClass: class added to the ancestors of the current item + * - ancestor_class: class added to the ancestors of the current item (alias: ancestorClass, deprecated in a future) * - firstClass: class added to the first child * - lastClass: class added to the last child * diff --git a/src/Knp/Menu/Renderer/TwigRenderer.php b/src/Knp/Menu/Renderer/TwigRenderer.php index 9c9f88bf..ed00254d 100644 --- a/src/Knp/Menu/Renderer/TwigRenderer.php +++ b/src/Knp/Menu/Renderer/TwigRenderer.php @@ -39,7 +39,7 @@ public function __construct( 'matchingDepth' => null, 'currentAsLink' => true, 'currentClass' => 'current', - 'ancestorClass' => 'current_ancestor', + 'ancestor_class' => 'current_ancestor', 'firstClass' => 'first', 'lastClass' => 'last', 'template' => $template, @@ -55,6 +55,13 @@ public function render(ItemInterface $item, array $options = []): string { $options = \array_merge($this->defaultOptions, $options); + // Avoid duplication of current_ancestor class. Overwrite value in old config to new one + if (isset($options['ancestorClass'])) { + $options['ancestor_class'] = $options['ancestorClass']; + unset($options['ancestorClass']); + trigger_deprecation('knplabs/knp-menu', '3.3', 'Using "%s" option is deprecated, use "%s" instead.', 'ancestorClass', 'ancestor_class'); + } + $html = $this->environment->render($options['template'], ['item' => $item, 'options' => $options, 'matcher' => $this->matcher]); if ($options['clear_matcher']) { diff --git a/src/Knp/Menu/Resources/views/knp_menu.html.twig b/src/Knp/Menu/Resources/views/knp_menu.html.twig index 0ac53f64..7697b9c0 100644 --- a/src/Knp/Menu/Resources/views/knp_menu.html.twig +++ b/src/Knp/Menu/Resources/views/knp_menu.html.twig @@ -55,7 +55,11 @@ {%- if matcher.isCurrent(item) %} {%- set classes = classes|merge([options.currentClass]) %} {%- elseif matcher.isAncestor(item, options.matchingDepth) %} - {%- set classes = classes|merge([options.ancestorClass]) %} + {%- set classes = classes|merge([options.ancestor_class]) %} + {%- if options.ancestorClass is not empty %} + {% deprecated 'knplabs/knp-menu 3.3: Using "ancestorClass" option is deprecated, use "ancestor_class" instead.' %} + {%- set classes = classes|merge([options.ancestorClass]) %} + {%- endif %} {%- endif %} {%- if item.actsLikeFirst %} {%- set classes = classes|merge([options.firstClass]) %} diff --git a/src/Knp/Menu/Twig/MenuExtension.php b/src/Knp/Menu/Twig/MenuExtension.php index b5e749bf..b0b022ed 100644 --- a/src/Knp/Menu/Twig/MenuExtension.php +++ b/src/Knp/Menu/Twig/MenuExtension.php @@ -77,6 +77,13 @@ public function getTests(): array */ public function get($menu, array $path = [], array $options = []): ItemInterface { + // Avoid duplication of current_ancestor class. Overwrite value in old config to new one + if (isset($options['ancestorClass'])) { + $options['ancestor_class'] = $options['ancestorClass']; + unset($options['ancestorClass']); + trigger_deprecation('knplabs/knp-menu', '3.3', 'Using "%s" option is deprecated, use "%s" instead.', 'ancestorClass', 'ancestor_class'); + } + return $this->helper->get($menu, $path, $options); } @@ -88,6 +95,13 @@ public function get($menu, array $path = [], array $options = []): ItemInterface */ public function render($menu, array $options = [], ?string $renderer = null): string { + // Avoid duplication of current_ancestor class. Overwrite value in old config to new one + if (isset($options['ancestorClass'])) { + $options['ancestor_class'] = $options['ancestorClass']; + unset($options['ancestorClass']); + trigger_deprecation('knplabs/knp-menu', '3.3', 'Using "%s" option is deprecated, use "%s" instead.', 'ancestorClass', 'ancestor_class'); + } + return $this->helper->render($menu, $options, $renderer); } diff --git a/tests/Knp/Menu/Tests/Renderer/AbstractRendererTest.php b/tests/Knp/Menu/Tests/Renderer/AbstractRendererTest.php index f936d627..0e1e6dbf 100644 --- a/tests/Knp/Menu/Tests/Renderer/AbstractRendererTest.php +++ b/tests/Knp/Menu/Tests/Renderer/AbstractRendererTest.php @@ -202,7 +202,7 @@ public function testRenderWithClassAndTitle(): void $this->assertEquals($rendered, $this->renderer->render($this->menu)); } - public function testRenderWithCurrentItem(): void + public function testLegacyRenderWithCurrentItem(): void { $this->ch2->setCurrent(true); $rendered = '
foobar
', $this->getTemplate('{{ knp_menu_render(menu, {"firstClass": "test"}) }}', $helper)->render(['menu' => $menu])); } + /** + * @group legacy + */ + public function testLegacyRenderMenuWithDeprecatedAncestorClass(): void + { + $menu = $this->getMockBuilder(ItemInterface::class)->getMock(); + $helper = $this->getHelperMock(['render']); + $helper->expects($this->once()) + ->method('render') + ->with($menu, ['ancestor_class' => 'test'], null) + ; + + $this->getTemplate('{{ knp_menu_render(menu, {"ancestorClass": "test"}) }}', $helper)->render(['menu' => $menu, 'ancestorClass' => 'test']); + + $this->expectDeprecation(''); + } + public function testRenderMenuWithRenderer(): void { $menu = $this->getMockBuilder(ItemInterface::class)->getMock();