Skip to content
This repository was archived by the owner on Sep 16, 2021. It is now read-only.

Commit 542c05c

Browse files
Bendbu
authored andcommitted
Add documentation for CreateMenuItemFromNodeEvent.
1 parent c2d5136 commit 542c05c

File tree

1 file changed

+96
-0
lines changed

1 file changed

+96
-0
lines changed

bundles/menu/menu_factory.rst

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,99 @@ visible by use of the :doc:`publish workflow checker
6565

6666
The ``MenuContentVoter`` decides that a menu node is not published if the
6767
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

Comments
 (0)