Allowing Raw HTML in KNP Menu Labels

KNP Menu is a library by the guys at KNP Labs for building menus with php. The KNP menu library offers great features like automatically adding branch classes, marking the first and last item in a menu, and provides features for to automatically figure out the current menu item. Adding raw html into a label (eg <br>) can be a bit of a pain, however.

The KNP menu library offers all the necessary tooling to add raw html into the labels out of the box. There are, however, no examples on the doc pages. Firstly, the menu renderer needs to be told that the menu can have raw html in the labels. Secondly, the menu label needs to be identified as a safe label before the renderer will allow raw html.

To tell the renderer that the menu can contain raw html, or safe labels as the KNP menu library prefers to call it, the allow_safe_labels renderer option needs to be set to true.

To set the allow_safe_labels option using the KNPMenu Library:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<?php

use Knp\Menu\Matcher\Matcher;
use Knp\Menu\MenuFactory;
use Knp\Menu\Renderer\ListRenderer;

// Create the new menu
$factory = new MenuFactory();
$menu = $factory->createItem('My menu');
$menu->addChild('Home', array('uri' => '/'));
$menu->addChild('Comments', array('uri' => '#comments'));
$menu->addChild('Symfony2', array('uri' => 'http://symfony-reloaded.org/'));

// Render the menu with the necessary renderer options
$rendererOptions = ['allow_safe_labels' => true];
$renderer = new ListRenderer(new Matcher(), $rendererOptions);
echo $renderer->render($menu);

Because rendering a menu is done differently using the KNPMenuBundle, the allow_safe_labels option is a is set quite differently:

{% raw %}
{{ knp_menu_render('primary_menu', {'allow_safe_labels': true}) }}
{% endraw %}

To tell the renderer that menu item contains a safe label, and can thereby be rendered unescaped, an extra parameter needs to be passed.

1
2
3
4
5
<?php

$menu
    ->addChild('Foo<br>Bar', array('uri' => '/'))
    ->setExtra('safe_label', true);

Options set via the setExtra() method end up as options on the menu item, accessible by a getExtra() method. The default twig template for KNPMenuBundle takes advantage of this parameter out of the box.

In summary, rendering menus using the KNP menu library with raw html in the label is possible without much work. I hope these examples help should you ever find yourself trying put raw html in a label in the future. Know that the barriers are in place for good reason, however, as allowing raw html in your labels could allow some XSS holes to pop up in your application should the menu labels be created by a user.