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

Add ability to configure default menu options #278

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
@@ -1,3 +1,5 @@
* Added DefaultOptionsExtension

## 2.0.0 (2014-08-01)

* Updated to KnpMenu 2 stable
Expand Down
6 changes: 6 additions & 0 deletions DependencyInjection/Configuration.php
Expand Up @@ -24,6 +24,7 @@ public function getConfigTreeBuilder()

$rootNode
->fixXmlConfig('provider')
->fixXmlConfig('default_menu_option')
->children()
->arrayNode('providers')
->addDefaultsIfNotSet()
Expand All @@ -41,6 +42,11 @@ public function getConfigTreeBuilder()
->end()
->booleanNode('templating')->defaultFalse()->end()
->scalarNode('default_renderer')->cannotBeEmpty()->defaultValue('twig')->end()
->arrayNode('default_menu_options')
->useAttributeAsKey('name')
->normalizeKeys(false)
->prototype('scalar')->end()
->end()
->end();

return $treeBuilder;
Expand Down
5 changes: 5 additions & 0 deletions DependencyInjection/KnpMenuExtension.php
Expand Up @@ -38,6 +38,11 @@ public function load(array $configs, ContainerBuilder $container)
}

$container->setParameter('knp_menu.default_renderer', $config['default_renderer']);

if (isset($config['default_menu_options'])) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is always set (prototyped array nodes have a default value of empty array)

$loader->load('options_extension.xml');
$container->setParameter('knp_menu.default_menu_options', $config['default_menu_options']);
}
}

public function getNamespace()
Expand Down
39 changes: 39 additions & 0 deletions Extension/DefaultOptionsExtension.php
@@ -0,0 +1,39 @@
<?php

namespace Knp\Bundle\MenuBundle\Extension;

use Knp\Menu\Factory\ExtensionInterface;
use Knp\Menu\ItemInterface;

/**
* An extension to configure the default menu options.
*
* @author Wouter J <wouter@wouterj.nl>
*/
class DefaultOptionsExtension implements ExtensionInterface
{
/**
* @var array
*/
private $options;

public function __construct(array $options)
{
$this->options = $options;
}

/**
* {@inheritdoc}
*/
public function buildOptions(array $options = array())
{
return array_merge($this->options, $options);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

many options of the library are arrays. This makes them hard to use with your extension

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So you suggest using array_merge_recursive instead?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know what to use here. array_merge_recursive has a very weird behavior when associate arrays are involved, so it is not the solution either (it would be even worse). array_replace_recursive would already be a bit better as we mostly have associative arrays (but this one leads to an unexpected behavior when lists are merged together though, and this happens in extras, for instance for the list of matched routes)

}

/**
* {@inheritdoc}
*/
public function buildItem(ItemInterface $item, array $options)
{
}
}
14 changes: 14 additions & 0 deletions Resources/config/options_extension.xml
@@ -0,0 +1,14 @@
<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">

<services>
<service id="knp_menu.extension.default_options" class="Knp\Bundle\MenuBundle\Extension\DefaultOptionsExtension">
<tag name="knp_menu.factory_extension" />
<argument>%knp_menu.default_menu_options%</argument>
</service>
</services>

</container>
1 change: 1 addition & 0 deletions Resources/doc/index.rst
Expand Up @@ -302,6 +302,7 @@ More Advanced Stuff
* :doc:`Custom Menu Provider <custom_provider>`
* :doc:`I18n for your menu labels <i18n>`
* :doc:`Using events to allow extending the menu <events>`
* :doc:`Setting Default Menu Options <menu_options>`

.. _`installation chapter`: https://getcomposer.org/doc/00-intro.md
.. _`KnpMenu documentation`: https://github.com/KnpLabs/KnpMenu/blob/master/doc/01-Basic-Menus.markdown
45 changes: 45 additions & 0 deletions Resources/doc/menu_options.rst
@@ -0,0 +1,45 @@
Setting Default Menu Options
============================

When creating a menu, menu options are set by passing them to ``addChild()``.
When all menu items need the same option, adding the same options to each child
can be cumbersome.

In these cases, you can configure the menu options in the configuration file:

.. configuration-block::

.. code-block:: yaml

# app/config/config.yml
knp_menu:
default_menu_options:
class: menu-item
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is no class option in KnpMenu. Please use a real use case in the documentation (which will also help you see that the current implementation is not very usage)


.. code-block:: xml

<!-- app/config/config.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-Instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services
http://symfony.com/schema/dic/services/services-1.0.xsd">

<config xmlns="http://knplabs.com/schema/dic/menu">
<default-menu-option name="class">menu-item</default-menu-option>
</config>
</container>

.. code-block:: php

// app/config/config.php
$container->loadFromExtension('knp_menu', array(
'default_menu_options' => array(
'class' => 'menu-item',
),
));

These options are overriden by options that are explicitely passed to the menu item::

// ...
$menu->addChild('Home', array('class' => 'menu-item menu-item-home'));
9 changes: 9 additions & 0 deletions Tests/DependencyInjection/KnpMenuExtensionTest.php
Expand Up @@ -72,4 +72,13 @@ public function testDisableContainerAwareProvider()
$this->assertTrue($container->getDefinition('knp_menu.menu_provider.builder_alias')->hasTag('knp_menu.provider'), 'The BuilderAliasProvider is enabled');
$this->assertFalse($container->getDefinition('knp_menu.menu_provider.container_aware')->hasTag('knp_menu.provider'), 'The ContainerAwareProvider is disabled');
}

public function testConfigureDefaultMenuOptions()
{
$container = new ContainerBuilder();
$loader = new KnpMenuExtension();
$loader->load(array(array('default_menu_options' => array('displayChildren' => false))), $container);
$this->assertEquals(array('displayChildren' => false), $container->getParameter('knp_menu.default_menu_options'));
$this->assertTrue($container->hasDefinition('knp_menu.extension.default_options'));
}
}
34 changes: 34 additions & 0 deletions Tests/Extension/DefaultOptionsExtensionTest.php
@@ -0,0 +1,34 @@
<?php

namespace Knp\Bundle\MenuBundle\Tests\Extension;

use Knp\Bundle\MenuBundle\Extension\DefaultOptionsExtension;

class DefaultOptionsExtensionTest extends \PHPUnit_Framework_TestCase
{
public function testSetsDefaultOptions()
{
$extension = new DefaultOptionsExtension(array(
'attributes' => array('class' => 'menu-item'),
'displayChildren' => false,
));

$this->assertEquals(array(
'attributes' => array('class' => 'menu-item'),
'displayChildren' => false,
), $extension->buildOptions());
}

public function testExplicitelyPassedOptionsOverwriteConfiguredDefaults()
{
$extension = new DefaultOptionsExtension(array(
'attributes' => array('class' => 'menu-item'),
'displayChildren' => false,
));

$this->assertEquals(array(
'attributes' => array('class' => 'menu-item'),
'displayChildren' => true,
), $extension->buildOptions(array('displayChildren' => true)));
}
}