Browse Source

Add provider option to config for using a custom knp menu as part of the admin menu

Romain Mouillard 10 years ago
parent
commit
9e3a897105

+ 1 - 0
DependencyInjection/Configuration.php

@@ -102,6 +102,7 @@ class Configuration implements ConfigurationInterface
                                     ->scalarNode('label')->end()
                                     ->scalarNode('label_catalogue')->end()
                                     ->scalarNode('icon')->defaultValue('<i class="fa fa-folder"></i>')->end()
+                                    ->scalarNode('provider')->end()
                                     ->arrayNode('items')
                                         ->beforeNormalization()
                                             ->ifArray()

+ 1 - 0
Resources/config/twig.xml

@@ -10,6 +10,7 @@
 
             <argument type="service" id="sonata.admin.pool" />
             <argument type="service" id="router" />
+            <argument type="service" id="knp_menu.helper" />
             <argument type="service" id="logger" on-invalid="ignore" />
         </service>
     </services>

+ 52 - 18
Resources/doc/cookbook/recipe_knp_menu.rst

@@ -1,35 +1,39 @@
 KnpMenu
 =======
 
-The admin comes with `KnpMenu <https://github.com/KnpLabs/KnpMenu>`_ integration
-It integrates a menu with the KnpMenu library. This menu can be a SonataAdmin service or a route of a custom controller.
+The admin comes with `KnpMenu <https://github.com/KnpLabs/KnpMenu>`_ integration.
+It integrates a menu with the KnpMenu library. This menu can be a SonataAdmin service, a menu created with a Knp menu provider or a route of a custom controller.
 
 Add a custom controller entry in the menu
 -----------------------------------------
 
 To add a custom controller entry in the admin menu:
 
-Create your controller
+Create your controller:
 
 .. code-block:: php
 
-    /**
-     * @Route("/blog", name="blog_home")
-     */
-    public function blogAction()
+    class BlogController 
     {
-        // ...
-    }
+        /**
+         * @Route("/blog", name="blog_home")
+         */
+        public function blogAction()
+        {
+            // ...
+        }
 
-    /**
-     * @Route("/blog/article/{articleId}", name="blog_article")
-     */
-    public function ArticleAction($articleId)
-    {
-        // ...
+        /**
+         * @Route("/blog/article/{articleId}", name="blog_article")
+         */
+        public function ArticleAction($articleId)
+        {
+            // ...
+        }
     }
 
-Add the controller route as an item of the menu
+
+Add the controller route as an item of the menu:
 
 .. code-block:: yaml
 
@@ -49,7 +53,7 @@ Add the controller route as an item of the menu
                           label:        Article
                     ...
 
-Also you can override the template of knp_menu used by sonata. The default one is `SonataAdminBundle:Menu:sonata_menu.html.twig`:
+You can also override the template of knp_menu used by sonata. The default one is `SonataAdminBundle:Menu:sonata_menu.html.twig`:
 
 .. code-block:: yaml
 
@@ -59,4 +63,34 @@ Also you can override the template of knp_menu used by sonata. The default one i
             knp_menu_template:           ApplicationAdminBundle:Menu:custom_knp_menu.html.twig
         ...
 
-And voilà, now you have a new menu group which contains an entry to sonata_admin_id, to your blog and to a specific article.
+And voilà, now you have a menu group which contains a link to a sonata admin via its id, to your blog and to a specific article.
+
+Using a menu provider
+---------------------
+
+As seen above, the main way to declare your menu is by declaring items in your sonata admin config file. In some case you may have to create a more complexe menu depending on your business logic. This is possible by using a menu provider to populate a whole menu group. This is done with the ``provider`` config value.
+
+Tthe following configuration uses a menu provider to populate the menu group ``my_group``:
+
+.. code-block:: yaml
+
+    sonata_admin:
+        dashboard:
+            groups:
+                my_group:
+                    provider:        'MyBundle:MyMenuProvider:getMyMenu'
+                    icon:            '<i class="fa fa-edit"></i>'
+
+With KnpMenuBundle you can create a custom menu by using a builder class or by declaring it as a service. Please see the `Knp documentation <http://symfony.com/doc/current/bundles/KnpMenuBundle/index.html#create-your-first-menu>`_ for further information. 
+
+In sonata, whatever the implementation you choose, you only have to provide the menu alias to the provider config key:
+
+* If you are using a builder class, your menu alias should be something like ``MyBundle:MyMenuProvider:getMyMenu``.
+* If you are using a service, your menu alias is the alias set in the ``knp_menu.menu`` tag. In the following example this is ``my_menu_alias``:
+    .. code-block:: xml
+
+        <service id="my_menu_provider" class="MyBundle/MyDirectory/MyMenuProvider">
+            <tag name="knp_menu.menu" alias="my_menu_alias" />
+        </service>
+
+Please note that when using the provider option, you can't set the menu label via the configuration. It is done in your custom menu.

+ 1 - 1
Resources/views/Menu/sonata_menu.html.twig

@@ -31,7 +31,7 @@
             {%- endfor %}
         {%- endif %}
 
-        {%- if item.level == 1%}
+        {%- if item.hasChildren %}
             {%- do item.setAttribute('class', (item.attribute('class')~' treeview')|trim) %}
         {%- endif %}
         {%- if active %}

+ 27 - 4
Twig/Extension/SonataAdminExtension.php

@@ -14,6 +14,7 @@ namespace Sonata\AdminBundle\Twig\Extension;
 use Doctrine\Common\Util\ClassUtils;
 use Knp\Menu\MenuFactory;
 use Knp\Menu\ItemInterface;
+use Knp\Menu\Twig\Helper;
 use Psr\Log\LoggerInterface;
 use Sonata\AdminBundle\Admin\AdminInterface;
 use Sonata\AdminBundle\Admin\FieldDescriptionInterface;
@@ -40,6 +41,11 @@ class SonataAdminExtension extends \Twig_Extension
      */
     protected $router;
 
+    /**
+     * @var Helper
+     */
+    protected $knpHelper;
+
     /**
      * @var LoggerInterface
      */
@@ -49,11 +55,12 @@ class SonataAdminExtension extends \Twig_Extension
      * @param Pool            $pool
      * @param LoggerInterface $logger
      */
-    public function __construct(Pool $pool, RouterInterface $router, LoggerInterface $logger = null)
+    public function __construct(Pool $pool, RouterInterface $router, Helper $knpHelper, LoggerInterface $logger = null)
     {
-        $this->pool   = $pool;
-        $this->logger = $logger;
-        $this->router = $router;
+        $this->pool      = $pool;
+        $this->logger    = $logger;
+        $this->router    = $router;
+        $this->knpHelper = $knpHelper;
     }
 
     /**
@@ -379,6 +386,22 @@ class SonataAdminExtension extends \Twig_Extension
         ;
 
         foreach ($this->pool->getAdminGroups() as $name => $group) {
+
+            // Check if the menu group is built by a menu provider
+            if (isset($group['provider'])) {
+                $subMenu = $this->knpHelper->get($group['provider']);
+
+                $menu->addChild($subMenu)
+                    ->setAttributes(array(
+                        'icon'            => $group['icon'],
+                        'label_catalogue' => $group['label_catalogue']
+                    ))
+                    ->setExtra('roles', $group['roles']);
+
+                continue;
+            }
+
+            // The menu group is built by config
             $menu
                 ->addChild($name, array('label' => $group['label']))
                 ->setAttributes(