@@ -65,3 +65,99 @@ visible by use of the :doc:`publish workflow checker
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 to
87
+ true will prevent creation of item from the node and skip any child nodes.
88
+ **Note: ** If setSkipNode(true) is called for ``Menu `` the ``ContentAwareFactory ``
89
+ will still create an empty item for the menu. This is to prevent the KnpMenuBundle
90
+ code from throwing an Exception due to null being passed to a function to render a
91
+ menu.
92
+ * ``CreateMenuItemFromNodeEvent::setItem(ItemInterface $item|null) ``: A listener
93
+ can call setItem to provide a custom item to use for the given node. If an
94
+ item is set, the ``ContentAwareFactory `` will use it instead of creating one for
95
+ the node. The children of the node will still be processed by the
96
+ ``ContentAwareFactory `` and listeners will have an opportunity then to override
97
+ 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 Listener
103
+ ~~~~~~~~~~~~~~~~
104
+
105
+ Example PHP code for a listener that would replace nodes that implement
106
+ an interface ``MenuReferrerInterface `` with a menu generated by
107
+ a menu provider service.
108
+
109
+ .. code-block :: php
110
+
111
+ namespace Example\Menu;
112
+
113
+ interface MenuReferrerInterface
114
+ {
115
+ public function getMenuName();
116
+ public function getMenuOptions();
117
+ }
118
+
119
+ namespace Example\Event;
120
+
121
+ use Symfony\Cmf\Bundle\MenuBundle\Event\CreateMenuItemFromNodeEvent;
122
+ use Example\Menu\MenuReferrerInterface;
123
+ use Knp\Menu\Provider\MenuProviderInterface;
124
+
125
+ class CreateMenuItemFromNodeListener
126
+ {
127
+ protected $provider;
128
+
129
+ public function __construct(MenuProviderInterface $provider)
130
+ {
131
+ $this->provider = $provider;
132
+ }
133
+
134
+ public function onCreateMenuItemFromNode(CreateMenuItemFromNodeEvent $event)
135
+ {
136
+ $node = $event->getNode();
137
+
138
+ if ($node implements MenuReferrerInterface) {
139
+ $menuName = $node->getMenuName();
140
+ $menuOptions = $node->getMenuOptions();
141
+
142
+ if ( ! $this->provider->has($menuName)) {
143
+ return;
144
+ }
145
+
146
+ $menu = $this->provider->get($menuName, $menuOptions);
147
+ $event->setItem($menu);
148
+ }
149
+ }
150
+
151
+ }
152
+
153
+ Service definition
154
+
155
+ .. code-block :: xml
156
+
157
+ <service id =" cmf_menu.listener.menu_referrer_listener" class =" Example\Event\CreateMenuItemFromNodeListener" >
158
+ <argument type =" service" id =" knp_menu.menu_provider" />
159
+ <tag name =" kernel.event_listener" event =" cmf_menu.create_menu_item_from_node" method =" onCreateMenuItemFromNode" />
160
+ </service >
161
+
162
+ **Note ** In this case since the listener did not call ``$event->setSkipChildren(true) `` any nodes
163
+ that are children of the node being processed will still be added to the menu that is created.
0 commit comments