mirror of
				https://gitlab.com/Chill-Projet/chill-bundles.git
				synced 2025-10-31 01:08:26 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			197 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			197 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| 
 | |
| namespace Chill\MainBundle\Routing;
 | |
| 
 | |
| use Symfony\Component\Routing\RouteCollection;
 | |
| use Symfony\Component\Routing\RouterInterface;
 | |
| use Knp\Menu\FactoryInterface;
 | |
| use Knp\Menu\ItemInterface;
 | |
| use Symfony\Component\Translation\TranslatorInterface;
 | |
| 
 | |
| 
 | |
| /**
 | |
|  * This class permit to build menu from the routing information
 | |
|  * stored in each bundle.
 | |
|  * 
 | |
|  * how to must come here FIXME 
 | |
|  *
 | |
|  * @author julien
 | |
|  */
 | |
| class MenuComposer
 | |
| {
 | |
|     
 | |
|     /**
 | |
|      *
 | |
|      * @var RouterInterface
 | |
|      */
 | |
|     private $router;
 | |
|     
 | |
|     /**
 | |
|      *
 | |
|      * @var FactoryInterface
 | |
|      */
 | |
|     private $menuFactory;
 | |
|     
 | |
|     /**
 | |
|      *
 | |
|      * @var TranslatorInterface
 | |
|      */
 | |
|     private $translator;
 | |
|     
 | |
|     /**
 | |
|      *
 | |
|      * @var 
 | |
|      */
 | |
|     private $localMenuBuilders = [];
 | |
|     
 | |
|     
 | |
|     function __construct(
 | |
|         RouterInterface $router,
 | |
|         FactoryInterface $menuFactory,
 | |
|         TranslatorInterface $translator
 | |
|     ) {
 | |
|         $this->router = $router;
 | |
|         $this->menuFactory = $menuFactory;
 | |
|         $this->translator = $translator;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Set the route Collection
 | |
|      * This function is needed for testing purpose: routeCollection is not
 | |
|      * available as a service (RouterInterface is provided as a service and
 | |
|      * added to this class as paramater in __construct)
 | |
|      * 
 | |
|      * @param RouteCollection $routeCollection
 | |
|      */
 | |
|     public function setRouteCollection(RouteCollection $routeCollection)
 | |
|     {
 | |
|         $this->routeCollection = $routeCollection;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Return an array of routes added to $menuId,
 | |
|      * The array is aimed to build route with MenuTwig
 | |
|      * 
 | |
|      * @param string $menuId
 | |
|      * @param array $parameters see https://redmine.champs-libres.coop/issues/179
 | |
|      * @return array
 | |
|      */
 | |
|     public function getRoutesFor($menuId, array $parameters = array())
 | |
|     {
 | |
|         $routes = array();
 | |
|         $routeCollection = $this->router->getRouteCollection();
 | |
| 
 | |
|         foreach ($routeCollection->all() as $routeKey => $route) {
 | |
|             if ($route->hasOption('menus')) {
 | |
|                 
 | |
|                 if (array_key_exists($menuId, $route->getOption('menus'))) {
 | |
|                     $route = $route->getOption('menus')[$menuId];
 | |
| 
 | |
|                     $route['key'] = $routeKey;
 | |
| 
 | |
|                     $order = $this->resolveOrder($routes, $route['order']);
 | |
|                     //we do not want to duplicate order information
 | |
|                     unset($route['order']);
 | |
|                     $routes[$order] = $route;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         ksort($routes);
 | |
| 
 | |
|         return $routes;
 | |
|     }
 | |
|     
 | |
|     public function getMenuFor($menuId, array $parameters = array())
 | |
|     {
 | |
|         $routes = $this->getRoutesFor($menuId, $parameters);
 | |
|         $menu = $this->menuFactory->createItem($menuId);
 | |
|         
 | |
|         // build menu from routes
 | |
|         foreach ($routes as $order => $route) {
 | |
|             $menu->addChild($this->translator->trans($route['label']), [
 | |
|                     'route' => $route['key'],
 | |
|                     'routeParameters' => $parameters['args'],
 | |
|                     'order' => $order
 | |
|                 ])
 | |
|                 ->setExtras([
 | |
|                     'icon' => $route['icon'],
 | |
|                     'order' => $order
 | |
|                 ])
 | |
|             ;
 | |
|         }
 | |
|         
 | |
|         if ($this->hasLocalMenuBuilder($menuId)) {
 | |
|             foreach ($this->localMenuBuilders[$menuId] as $builder) {
 | |
|                 /* @var $builder LocalMenuBuilderInterface */
 | |
|                 $builder->buildMenu($menuId, $menu, $parameters['args']);
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         $this->reorderMenu($menu);
 | |
|         
 | |
|         return $menu;
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * recursive function to resolve the order of a array of routes.
 | |
|      * If the order chosen in routing.yml is already in used, find the 
 | |
|      * first next order available.
 | |
|      * 
 | |
|      * @param array $routes the routes previously added
 | |
|      * @param int $order
 | |
|      * @return int
 | |
|      */
 | |
|     private function resolveOrder($routes, $order)
 | |
|     {
 | |
|         if (isset($routes[$order])) {
 | |
|             return $this->resolveOrder($routes, $order + 1);
 | |
|         } else {
 | |
|             return $order;
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     private function reorderMenu(ItemInterface $menu) 
 | |
|     {
 | |
|         $ordered = [];
 | |
|         $unordered = [];
 | |
|         
 | |
|         foreach ($menu->getChildren() as $name => $item) {
 | |
|             $order = $item->getExtra('order');
 | |
|             
 | |
|             if ($order !== null) {
 | |
|                $ordered[$this->resolveOrder($ordered, $order)] = $name;
 | |
|             } else {
 | |
|                 $unordered = $name;
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         ksort($ordered);
 | |
|         
 | |
|         $menus = \array_merge(\array_values($ordered), $unordered);
 | |
|         $menu->reorderChildren($menus);
 | |
|     }
 | |
|     
 | |
|     
 | |
|     public function addLocalMenuBuilder(LocalMenuBuilderInterface $menuBuilder, $menuId) 
 | |
|     {
 | |
|         $this->localMenuBuilders[$menuId][] = $menuBuilder;
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Return true if the menu has at least one builder.
 | |
|      * 
 | |
|      * This function is a helper to determine if the method `getMenuFor`
 | |
|      * should be used, or `getRouteFor`. The method `getMenuFor` should be used
 | |
|      * if the result is true (it **does** exists at least one menu builder.
 | |
|      * 
 | |
|      * @param string $menuId
 | |
|      * @return bool
 | |
|      */
 | |
|     public function hasLocalMenuBuilder($menuId): bool
 | |
|     {
 | |
|         return \array_key_exists($menuId, $this->localMenuBuilders);
 | |
|     }
 | |
| 
 | |
| }
 |