@@ -19,7 +19,7 @@ A menu item should have a URL associated with it. The CMF provides the
19
19
``MenuFactory ``.
20
20
21
21
* The ``MenuFactory `` only supports using the ``uri `` option to specify the
22
- menu items link.
22
+ menu items link.
23
23
* The ``RouterAwareFactory `` adds support for for generating a URL from the
24
24
``route `` and ``routeParameters `` options.
25
25
* The CMF adds the ``ContentAwareFactory `` which supports generating the URL
@@ -44,7 +44,7 @@ of the three URL generation techniques to use.
44
44
The values for this options can be one of the following:
45
45
46
46
* ``null ``: If the value is ``null `` (or the options is not set) then the link
47
- type is determined automatically by looking at each of the ``uri ``, ``route `` and
47
+ type is determined automatically by looking at each of the ``uri ``, ``route `` and
48
48
``content `` options and using the first one which is non-null.
49
49
* **uri **: Use the URI provided by the ``uri `` option.
50
50
* **route **: Generate a URL using the route named by the ``route `` option
@@ -62,6 +62,135 @@ visible by use of the :doc:`publish workflow checker
62
62
63
63
.. versionadded :: 1.1
64
64
The ``MenuContentVoter `` was added in CmfMenuBundle 1.1.
65
-
65
+
66
66
The ``MenuContentVoter `` decides that a menu node is not published if the
67
67
content it is pointing to is not published.
68
+
69
+ Customizing Menus using Events
70
+ ------------------------------
71
+
72
+ The CMF menu factory dispatches a ``cmf_menu.create_menu_item_from_node `` event
73
+ during the process of creating a ``MenuItem `` from a class implementing
74
+ ``NodeInterface ``. You can use this event to control the ``MenuItem `` that is
75
+ created. The ``CreateMenuItemFromNodeEvent `` provides access to the
76
+ ``NodeInterface `` and ``ContentAwareFactory ``, which can be used to create a
77
+ custom ``MenuItem ``, or to tell the factory to ignore the current node or its
78
+ children. For example, this event is used by the
79
+ :doc: `publish workflow checker <../core/publish_workflow >` to skip
80
+ ``MenuItem `` generation for unpublished nodes.
81
+
82
+ The ``CreateMenuItemFromNodeEvent `` which is dispatched includes the following
83
+ methods which can be used to customize the creation of the ``MenuItem `` for a
84
+ ``NodeInterface ``.
85
+
86
+ * ``CreateMenuItemFromNodeEvent::setSkipNode(true|false) ``: Setting skipNode
87
+ to true will prevent creation of item from the node and skip any child nodes.
88
+ **Note: ** If setSkipNode(true) is called for ``Menu `` the
89
+ ``ContentAwareFactory `` will still create an empty item for the menu. This is
90
+ to prevent the KnpMenuBundle code from throwing an exception due to ``null ``
91
+ being passed to a function to render a menu;
92
+ * ``CreateMenuItemFromNodeEvent::setItem(ItemInterface $item|null) ``: A
93
+ listener can call setItem to provide a custom item to use for the given node.
94
+ If an item is set, the ``ContentAwareFactory `` will use it instead of
95
+ creating one for the node. The children of the node will still be processed
96
+ by the ``ContentAwareFactory `` and listeners will have an opportunity then to
97
+ override their items using this method;
98
+ * ``CreateMenuItemFromNodeEvent::setSkipChildren(true|false) ``: Listeners can
99
+ set this to true and the ``ContentAwareFactory `` will skip processing of the
100
+ children of the current node.
101
+
102
+ Example Menu Listener
103
+ ~~~~~~~~~~~~~~~~~~~~~
104
+
105
+ This listener handles menu nodes that point to a different menu by implementing
106
+ the ``MenuReferrerInterface ``::
107
+
108
+ namespace Acme\DemoBundle;
109
+
110
+ interface MenuReferrerInterface
111
+ {
112
+ public function getMenuName();
113
+ public function getMenuOptions();
114
+ }
115
+
116
+ namespace Acme\DemoBundle\EventListener;
117
+
118
+ use Symfony\Cmf\Bundle\MenuBundle\Event\CreateMenuItemFromNodeEvent;
119
+ use Acme\DemoBundle\MenuReferrerInterface;
120
+ use Knp\Menu\Provider\MenuProviderInterface;
121
+
122
+ class CreateMenuItemFromNodeListener
123
+ {
124
+ protected $provider;
125
+
126
+ public function __construct(MenuProviderInterface $provider)
127
+ {
128
+ $this->provider = $provider;
129
+ }
130
+
131
+ public function onCreateMenuItemFromNode(CreateMenuItemFromNodeEvent $event)
132
+ {
133
+ $node = $event->getNode();
134
+
135
+ if ($node implements MenuReferrerInterface) {
136
+ $menuName = $node->getMenuName();
137
+ $menuOptions = $node->getMenuOptions();
138
+
139
+ if (!$this->provider->has($menuName)) {
140
+ return;
141
+ }
142
+
143
+ $menu = $this->provider->get($menuName, $menuOptions);
144
+ $event->setItem($menu);
145
+
146
+ // as this does not call $event->setSkipChildren(true),
147
+ // children of $node will be rendered as children items of $menu.
148
+ }
149
+ }
150
+
151
+ }
152
+
153
+ The service needs to be tagged as event listener:
154
+
155
+ .. configuration-block ::
156
+
157
+ .. code-block :: yaml
158
+
159
+ services :
160
+ acme_demo.listener.menu_referrer_listener :
161
+ class : Acme\DemoBundle\EventListener\CreateMenuItemFromNodeListener
162
+ arguments :
163
+ - @knp_menu.menu_provider
164
+ tags :
165
+ -
166
+ name : kernel.event_listener
167
+ event : cmf_menu.create_menu_item_from_node
168
+ method : onCreateMenuItemFromNode
169
+
170
+ .. code-block :: xml
171
+
172
+ <?xml version =" 1.0" encoding =" UTF-8" ?>
173
+ <container xmlns =" http://symfony.com/schema/dic/services" >
174
+ <service id =" acme_demo.listener.menu_referrer_listener" class =" Acme\DemoBundle\EventListener\CreateMenuItemFromNodeListener" >
175
+ <argument type =" service" id =" knp_menu.menu_provider" />
176
+ <tag name =" kernel.event_listener"
177
+ event =" cmf_menu.create_menu_item_from_node"
178
+ method =" onCreateMenuItemFromNode"
179
+ />
180
+ </service >
181
+ </container >
182
+
183
+ .. code-block :: php
184
+
185
+ use Symfony\Component\DependencyInjection\Definition;
186
+ use Symfony\Component\DependencyInjection\Reference;
187
+
188
+ $definition = new Definition('Acme\DemoBundle\EventListener\CreateMenuItemFromNodeListener', array(
189
+ new Reference('knp_menu.menu_provider'),
190
+ ));
191
+ $definition->addTag('kernel.event_listener', array(
192
+ 'event' => 'cmf_menu.create_menu_item_from_node',
193
+ 'method' => 'onCreateMenuItemFromNode',
194
+ ));
195
+
196
+ $container->setDefinition('acme_demo.listener.menu_referrer_listener', $definition);
0 commit comments