src/Menu/Builder.php line 285

  1. <?php
  2. /**
  3.  * This file is part of the NautilePlus package.
  4.  *
  5.  * (c) Nicolas SOBOLEV <nicolas.sobolev@nautile.sarl>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. namespace App\Menu;
  11. use Knp\Menu\FactoryInterface;
  12. use Knp\Menu\ItemInterface;
  13. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  14. use Symfony\Bundle\SecurityBundle\Security;
  15. use Symfony\Contracts\Translation\TranslatorInterface;
  16. /**
  17.  * Menu builder engine.
  18.  *
  19.  * @see https://symfony.com/doc/current/bundles/KnpMenuBundle/menu_builder_service.html
  20.  *
  21.  * @author Nicolas SOBOLEV <nicolas.sobolev@nautile.sarl>
  22.  */
  23. class Builder
  24. {
  25.     /**
  26.      * Menu builder factory.
  27.      *
  28.      * @var FactoryInterface
  29.      */
  30.     private $factory;
  31.     /**
  32.      * Translation service.
  33.      *
  34.      * @var TranslatorInterface
  35.      */
  36.     private $translator;
  37.     /**
  38.      * Url generation service.
  39.      *
  40.      * @var UrlGeneratorInterface
  41.      */
  42.     private $urlGenerator;
  43.     /**
  44.      * Security service.
  45.      *
  46.      * @var Security
  47.      */
  48.     private $security;
  49.     /**
  50.      * Service constructor.
  51.      *
  52.      * @param FactoryInterface      $factory      Knp menu factory
  53.      * @param UrlGeneratorInterface $urlGenerator Url generation service
  54.      * @param TranslatorInterface   $translator   Translation service
  55.      * @param Security              $security     Security service
  56.      */
  57.     public function __construct(FactoryInterface $factoryUrlGeneratorInterface $urlGeneratorTranslatorInterface $translatorSecurity $security)
  58.     {
  59.         $this->factory $factory;
  60.         $this->urlGenerator $urlGenerator;
  61.         $this->translator $translator;
  62.         $this->security $security;
  63.     }
  64.     /**
  65.      * Parses and formats the menu attributes.
  66.      *
  67.      * @param array $menuItem Reference of menu item
  68.      *
  69.      * @return array Menu item attributes
  70.      */
  71.     private function prepareMenuAttributes(&$menuItem): array
  72.     {
  73.         $menuAttr = [
  74.             // default attribures here ...
  75.         ];
  76.         if (isset($menuItem['name'])) {
  77.             $menuAttr['name'] = $menuItem['name'];
  78.         }
  79.         // configured attributes
  80.         if (isset($menuItem['attributes']) && is_array($menuItem['attributes'])) {
  81.             foreach ($menuItem['attributes'] as $attrName => $attrValue) {
  82.                 $menuAttr[$attrName] = $attrValue;
  83.             }
  84.         }
  85.         return $menuAttr;
  86.     }
  87.     /**
  88.      * Creates child of menu object.
  89.      *
  90.      * @param ItemInterface $menu       Reference of the Menu object that is being generated
  91.      * @param array         $menuItem   Reference of the menu child item to be addad to the menu object
  92.      * @param array         $menuParams Reference of the parameter array of child menu item
  93.      *
  94.      * @return Builder Current menu builder instance
  95.      */
  96.     private function processNode(ItemInterface &$menu, &$menuItem, &$menuParams): self
  97.     {
  98.         if (isset($menuItem['children'])) {
  99.             $menuParams['extras']['expanded'] = true;
  100.             if (isset($menuItem['expanded'])) {
  101.                 $menuParams['extras']['expanded'] = $menuItem['expanded'];
  102.             }
  103.         }
  104.         $menu->addChild($menuItem['name'], $menuParams);
  105.         if (isset($menuItem['children'])) {
  106.             $this->fillMenuNodes($menu[$menuItem['name']], $menuItem['children']);
  107.         }
  108.         return $this;
  109.     }
  110.     /**
  111.      * Transforms the table representation of menu to the randerable object.
  112.      *
  113.      * @param ItemInterface $menu     Reference of the Menu object
  114.      * @param array         $menuData Reference of the table representation of the menu
  115.      *
  116.      * @return Builder Current menu builder instance
  117.      */
  118.     private function fillMenuNodes(ItemInterface &$menu, array &$menuData): self
  119.     {
  120.         $itemIndex 0;
  121.         foreach ($menuData as $menuItem) {
  122.             $menuParams = [];
  123.             // whether this item is activated
  124.             if (isset($menuItem['current'])) {
  125.                 $menuParams['current'] = $menuItem['current'];
  126.             }
  127.             // @TODO
  128.             $translationDomain 'navigation';
  129.             if (array_key_exists('translation_domain'$menuItem)) {
  130.                 $translationDomain $menuItem['translation_domain'];
  131.             }
  132.             // menu action URL
  133.             $menuParams['uri'] = null// no action by default
  134.             // generate the URI with the value of the "route" attribute
  135.             if (isset($menuItem['route'])) {
  136.                 $routeParams = [];
  137.                 if (isset($menuItem['routeParams'])) {
  138.                     $routeParams $menuItem['routeParams'];
  139.                 }
  140.                 $menuParams['uri'] = $this->urlGenerator->generate($menuItem['route'], $routeParamsUrlGeneratorInterface::ABSOLUTE_URL);
  141.             }
  142.             // the value of the "uri" attribute (if not empty) will override
  143.             // the uri generated with the value of the "route" attribute
  144.             if (isset($menuItem['uri'])) {
  145.                 $menuParams['uri'] = $menuItem['uri'];
  146.             }
  147.             // item [name] attribute (could be used as anchor, hashtag etc)
  148.             if (isset($menuItem['name'])) {
  149.                 $menuParams['name'] = $menuItem['name'];
  150.             }
  151.             // menu item label
  152.             $menuParams['label'] = '';
  153.             if (isset($menuItem['label'])) {
  154.                 $menuParams['label'] = $this->translator->trans($menuItem['label'], [], $translationDomain);
  155.             }
  156.             // menu item attributes
  157.             $menuParams['attributes'] = $this->prepareMenuAttributes($menuItem);
  158.             // if (!isset($menuItem['iconClass'])) {
  159.             //     // set the default icon using the translation file
  160.             //     // the translation key should be the same as for label except for "label"
  161.             //     // is replaced by "icon"
  162.             //     // $menuParams['extras']['icon'] = $this->translator->trans(
  163.             //     //     str_replace('label', 'icon', $menuItem['name']),
  164.             //     //     [],
  165.             //     //     $translationDomain
  166.             //     // );
  167.             // icon property
  168.             if (isset($menuItem['icon'])) {
  169.                 $menuParams['extras']['icon'] = $this->translator->trans($menuItem['icon'], [], $translationDomain);
  170.             }
  171.             // hint property
  172.             if (isset($menuItem['hint'])) {
  173.                 $menuParams['extras']['hint'] = $this->translator->trans($menuItem['hint'], [], $translationDomain);
  174.             }
  175.             // // set the default uri hash
  176.             // // the translation key should be the same as for label except for "label"
  177.             // // is replaced by "hash"
  178.             // $menuParams['extras']['hash'] = $this->translator->trans(
  179.             //     str_replace('label', 'hash', $menuItem['name']),
  180.             //     [],
  181.             //     $translationDomain
  182.             // );
  183.             // // hash property overrides the default behaviour
  184.             // if (isset($menuItem['hash'])) {
  185.             //     $menuParams['extras']['hash'] = $menuItem['hash'];
  186.             // }
  187.             // if (isset($menuItem['options'])) {
  188.             //     $menuParams['extras']['options'] = $menuItem['options'];
  189.             // }
  190.             // $menuParams['extras']['index'] = $itemIndex++;
  191.             $this->processNode($menu$menuItem$menuParams);
  192.         }
  193.         return $this;
  194.     }
  195.     /**
  196.      * Menu node generator.
  197.      *
  198.      * @param array $menuData   Menu utems table
  199.      * @param array $attributes Attributes for menu items
  200.      *
  201.      * @return ItemInterface Processed menu object
  202.      */
  203.     private function generateMenu(array &$menuData, array $attributes = []): ItemInterface
  204.     {
  205.         $menu $this->factory->createItem('root');
  206.         foreach ($attributes as $attrName => $attrValue) {
  207.             $menu->setChildrenAttribute($attrName$attrValue);
  208.         }
  209.         $this->fillMenuNodes($menu$menuData);
  210.         return $menu;
  211.     }
  212.     // /**
  213.     //  * Sidebar menu service.
  214.     //  *
  215.     //  * @param UrlGeneratorInterface $urlGenerator Url generation service
  216.     //  * @param TranslatorInterface   $translator   Translation service
  217.     //  * @param SidebarMenu           $sidebarMenu  Sidebar menu items mapping service
  218.     //  *
  219.     //  * @return ItemInterface generated menu item
  220.     //  */
  221.     // public function createSidebarMenu(UrlGeneratorInterface $urlGenerator, TranslatorInterface $translator, SidebarMenu $sidebarMenu)
  222.     // {
  223.     //     $this->urlGenerator = $urlGenerator;
  224.     //     $this->translator = $translator;
  225.     //     $items = $sidebarMenu->items;
  226.     //     $attributes = [
  227.     //         'class' => 'mdc-list',
  228.     //         'aria-hidden' => 'true',
  229.     //         'aria-orientation' => 'vertical',
  230.     //         'data-nautile-plus-list' => '',
  231.     //     ];
  232.     //     return $this->generateMenu($items, $attributes);
  233.     // }
  234.     /**
  235.      * Main menu service.
  236.      *
  237.      * @return ItemInterface generated menu item
  238.      */
  239.     public function createMainMenu(array $options): ItemInterface
  240.     {
  241.         $menu = new MainMenu($options$this->security);
  242.         return $this->generateMenu($menu->items$menu->attributes);
  243.     }
  244.     /**
  245.      * Userbox menu service.
  246.      *
  247.      * @return ItemInterface generated menu item
  248.      */
  249.     public function createUserboxMenu(array $options): ItemInterface
  250.     {
  251.         $menu = new UserboxMenu($options$this->security);
  252.         return $this->generateMenu($menu->items$menu->attributes);
  253.     }
  254.     // /**
  255.     //  * Settings menu service.
  256.     //  *
  257.     //  * @param UrlGeneratorInterface $urlGenerator Url generation service
  258.     //  * @param TranslatorInterface   $translator   Translation service
  259.     //  * @param BaseMenu              $menu         Menu items mapping service
  260.     //  *
  261.     //  * @return ItemInterface generated menu item
  262.     //  */
  263.     // public function createContextMenu(UrlGeneratorInterface $urlGenerator, TranslatorInterface $translator, BaseMenu $menu)
  264.     // {
  265.     //     $this->urlGenerator = $urlGenerator;
  266.     //     $this->translator = $translator;
  267.     //     $items = $menu->items;
  268.     //     $attributes = [
  269.     //         // 'class' => 'mdc-list',
  270.     //         // 'aria-hidden' => 'true',
  271.     //         // 'aria-orientation' => 'vertical',
  272.     //         // 'data-nautile-plus-list' => '',
  273.     //         // 'tabindex' => '-1',
  274.     //     ];
  275.     //     return $this->generateMenu($items, $attributes);
  276.     // }
  277. }