mirror of
				https://github.com/Icinga/icingaweb2.git
				synced 2025-10-30 02:44:04 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			807 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			807 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| /* Icinga Web 2 | (c) 2014 Icinga Development Team | GPLv2+ */
 | |
| 
 | |
| namespace Icinga\Web;
 | |
| 
 | |
| use RecursiveIterator;
 | |
| use Icinga\Application\Config;
 | |
| use Icinga\Application\Icinga;
 | |
| use Icinga\Application\Logger;
 | |
| use Icinga\Authentication\Auth;
 | |
| use Icinga\Data\ConfigObject;
 | |
| use Icinga\Exception\ConfigurationError;
 | |
| use Icinga\Exception\ProgrammingError;
 | |
| use Icinga\Web\Menu\MenuItemRenderer;
 | |
| 
 | |
| class Menu implements RecursiveIterator
 | |
| {
 | |
|     /**
 | |
|      * The id of this menu
 | |
|      *
 | |
|      * @var string
 | |
|      */
 | |
|     protected $id;
 | |
| 
 | |
|     /**
 | |
|      * The title of this menu
 | |
|      *
 | |
|      * Used for sorting when priority is unset or equal to other items
 | |
|      *
 | |
|      * @var string
 | |
|      */
 | |
|     protected $title;
 | |
| 
 | |
|     /**
 | |
|      * The priority of this menu
 | |
|      *
 | |
|      * Used for sorting
 | |
|      *
 | |
|      * @var int
 | |
|      */
 | |
|     protected $priority = 100;
 | |
| 
 | |
|     /**
 | |
|      * The url of this menu
 | |
|      *
 | |
|      * @var string|null
 | |
|      */
 | |
|     protected $url;
 | |
| 
 | |
|     /**
 | |
|      * The path to the icon of this menu
 | |
|      *
 | |
|      * @var string
 | |
|      */
 | |
|     protected $icon;
 | |
| 
 | |
|     /**
 | |
|      * The sub menus of this menu
 | |
|      *
 | |
|      * @var array
 | |
|      */
 | |
|     protected $subMenus = array();
 | |
| 
 | |
|     /**
 | |
|      * A custom item renderer used instead of the default rendering logic
 | |
|      *
 | |
|      * @var MenuItemRenderer
 | |
|      */
 | |
|     protected $itemRenderer = null;
 | |
| 
 | |
|     /*
 | |
|      * Parent menu
 | |
|      *
 | |
|      * @var Menu
 | |
|      */
 | |
|     protected $parent;
 | |
| 
 | |
|     /**
 | |
|      * Permission a user is required to have granted to display the menu item
 | |
|      *
 | |
|      * If a permission is set, authentication is of course required.
 | |
|      *
 | |
|      * Note that only one required permission can be set yet.
 | |
|      *
 | |
|      * @var string|null
 | |
|      */
 | |
|     protected $permission;
 | |
| 
 | |
|     /**
 | |
|      * Create a new menu
 | |
|      *
 | |
|      * @param   int             $id         The id of this menu
 | |
|      * @param   ConfigObject    $config     The configuration for this menu
 | |
|      * @param   Menu            $parent     Parent menu
 | |
|      */
 | |
|     public function __construct($id, ConfigObject $config = null, Menu $parent = null)
 | |
|     {
 | |
|         $this->id = $id;
 | |
|         if ($parent !== null) {
 | |
|             $this->parent = $parent;
 | |
|         }
 | |
|         $this->setProperties($config);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Set all given properties
 | |
|      *
 | |
|      * @param   array|ConfigObject  $props Property list
 | |
|      *
 | |
|      * @return  $this
 | |
|      *
 | |
|      * @throws  ConfigurationError  If a property is invalid
 | |
|      */
 | |
|     public function setProperties($props = null)
 | |
|     {
 | |
|         if ($props !== null) {
 | |
|             foreach ($props as $key => $value) {
 | |
|                 $method = 'set' . implode('', array_map('ucfirst', explode('_', strtolower($key))));
 | |
|                 if ($key === 'renderer') {
 | |
|                     // nested configuration is used to pass multiple arguments to the item renderer
 | |
|                     if ($value instanceof ConfigObject) {
 | |
|                         $args = $value;
 | |
|                         $value = $value->get('0');
 | |
|                     }
 | |
| 
 | |
|                     $value = '\\' . ltrim($value, '\\');
 | |
|                     if (class_exists($value)) {
 | |
|                         if (isset($args)) {
 | |
|                             $value = new $value($args);
 | |
|                         } else {
 | |
|                             $value = new $value;
 | |
|                         }
 | |
|                     } else {
 | |
|                         $class = '\Icinga\Web\Menu' . $value;
 | |
|                         if (!class_exists($class)) {
 | |
|                             throw new ConfigurationError(
 | |
|                                 sprintf('ItemRenderer with class "%s" does not exist', $class)
 | |
|                             );
 | |
|                         }
 | |
|                         if (isset($args)) {
 | |
|                             $value = new $class($args);
 | |
|                         } else {
 | |
|                             $value = new $class;
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|                 if (method_exists($this, $method)) {
 | |
|                     $this->{$method}($value);
 | |
|                 } else {
 | |
|                     throw new ConfigurationError(
 | |
|                         sprintf('Menu got invalid property "%s"', $key)
 | |
|                     );
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Get Properties
 | |
|      *
 | |
|      * @return array
 | |
|      */
 | |
|     public function getProperties()
 | |
|     {
 | |
|         $props = array();
 | |
|         $keys = array('url', 'icon', 'priority', 'title');
 | |
|         foreach ($keys as $key) {
 | |
|             $func = 'get' . ucfirst($key);
 | |
|             if (null !== ($val = $this->{$func}())) {
 | |
|                 $props[$key] = $val;
 | |
|             }
 | |
|         }
 | |
|         return $props;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Whether this Menu conflicts with the given Menu object
 | |
|      *
 | |
|      * @param   Menu $menu
 | |
|      *
 | |
|      * @return  bool
 | |
|      */
 | |
|     public function conflictsWith(Menu $menu)
 | |
|     {
 | |
|         if ($menu->getUrl() === null || $this->getUrl() === null) {
 | |
|             return false;
 | |
|         }
 | |
|         return $menu->getUrl() !== $this->getUrl();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Create menu from the application's menu config file plus the config files from all enabled modules
 | |
|      *
 | |
|      * @return      static
 | |
|      *
 | |
|      * @deprecated  THIS IS OBSOLETE. LEFT HERE FOR FUTURE USE WITH USER-SPECIFIC MODULES
 | |
|      */
 | |
|     public static function fromConfig()
 | |
|     {
 | |
|         $menu = new static('menu');
 | |
|         $manager = Icinga::app()->getModuleManager();
 | |
|         $modules = $manager->listEnabledModules();
 | |
|         $menuConfigs = array(Config::app('menu'));
 | |
| 
 | |
|         foreach ($modules as $moduleName) {
 | |
|             $moduleMenuConfig = Config::module($moduleName, 'menu');
 | |
|             if (! $moduleMenuConfig->isEmpty()) {
 | |
|                 $menuConfigs[] = $moduleMenuConfig;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         return $menu->loadSubMenus($menu->flattenConfigs($menuConfigs));
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Create menu from the application's menu config plus menu entries provided by all enabled modules
 | |
|      *
 | |
|      * @return static
 | |
|      */
 | |
|     public static function load()
 | |
|     {
 | |
|         $menu = new static('menu');
 | |
|         $menu->addMainMenuItems();
 | |
|         $auth = Auth::getInstance();
 | |
|         $manager = Icinga::app()->getModuleManager();
 | |
|         foreach ($manager->getLoadedModules() as $module) {
 | |
|             if ($auth->hasPermission($manager::MODULE_PERMISSION_NS . $module->getName())) {
 | |
|                 $menu->mergeSubMenus($module->getMenuItems());
 | |
|             }
 | |
|         }
 | |
|         return $menu->order();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Add Applications Main Menu Items
 | |
|      */
 | |
|     protected function addMainMenuItems()
 | |
|     {
 | |
|         $auth = Auth::getInstance();
 | |
| 
 | |
|         if ($auth->isAuthenticated()) {
 | |
|             $this->add(t('Dashboard'), array(
 | |
|                 'url'      => 'dashboard',
 | |
|                 'icon'     => 'dashboard',
 | |
|                 'priority' => 10
 | |
|             ));
 | |
| 
 | |
|             $section = $this->add(t('System'), array(
 | |
|                 'icon'     => 'services',
 | |
|                 'priority' => 700,
 | |
|                 'renderer' => array(
 | |
|                     'SummaryMenuItemRenderer',
 | |
|                     'state' => 'critical'
 | |
|                 )
 | |
|             ));
 | |
|             $section->add(t('About'), array(
 | |
|                 'url'       => 'about',
 | |
|                 'priority'  => 701
 | |
|             ));
 | |
|             if (Logger::writesToFile()) {
 | |
|                 $section->add(t('Application Log'), array(
 | |
|                     'url'        => 'list/applicationlog',
 | |
|                     'permission' => 'application/log',
 | |
|                     'priority'   => 710
 | |
|                 ));
 | |
|             }
 | |
| 
 | |
|             $section = $this->add(t('Configuration'), array(
 | |
|                 'icon'          => 'wrench',
 | |
|                 'permission'    => 'config/*',
 | |
|                 'priority'      => 800
 | |
|             ));
 | |
|             $section->add(t('Application'), array(
 | |
|                 'url'           => 'config/general',
 | |
|                 'permission'    => 'config/application/*',
 | |
|                 'priority'      => 810
 | |
|             ));
 | |
|             $section->add(t('Authentication'), array(
 | |
|                 'url'           => 'config/userbackend',
 | |
|                 'permission'    => 'config/authentication/*',
 | |
|                 'priority'      => 820
 | |
|             ));
 | |
|             $section->add(t('Roles'), array(
 | |
|                 'url'           => 'role/list',
 | |
|                 'permission'    => 'config/authentication/roles/show',
 | |
|                 'priority'      => 830
 | |
|             ));
 | |
|             $section->add(t('Users'), array(
 | |
|                 'url'           => 'user/list',
 | |
|                 'permission'    => 'config/authentication/users/show',
 | |
|                 'priority'      => 840
 | |
|             ));
 | |
|             $section->add(t('Usergroups'), array(
 | |
|                 'url'           => 'group/list',
 | |
|                 'permission'    => 'config/authentication/groups/show',
 | |
|                 'priority'      => 850
 | |
|             ));
 | |
|             $section->add(t('Modules'), array(
 | |
|                 'url'           => 'config/modules',
 | |
|                 'permission'    => 'config/modules',
 | |
|                 'priority'      => 890
 | |
|             ));
 | |
| 
 | |
|             $section = $this->add($auth->getUser()->getUsername(), array(
 | |
|                 'icon'     => 'user',
 | |
|                 'priority' => 900
 | |
|             ));
 | |
|             $section->add(t('Preferences'), array(
 | |
|                 'url'      => 'preference',
 | |
|                 'priority' => 910
 | |
|             ));
 | |
| 
 | |
|             $section->add(t('Logout'), array(
 | |
|                 'url'      => 'authentication/logout',
 | |
|                 'priority' => 990,
 | |
|                 'renderer' => array(
 | |
|                     'MenuItemRenderer',
 | |
|                     'target' => '_self'
 | |
|                 )
 | |
|             ));
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Set the id of this menu
 | |
|      *
 | |
|      * @param   string  $id     The id to set for this menu
 | |
|      *
 | |
|      * @return  $this
 | |
|      */
 | |
|     public function setId($id)
 | |
|     {
 | |
|         $this->id = $id;
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Return the id of this menu
 | |
|      *
 | |
|      * @return  string
 | |
|      */
 | |
|     public function getId()
 | |
|     {
 | |
|         return $this->id;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Get our ID without invalid characters
 | |
|      *
 | |
|      * @return string the ID
 | |
|      */
 | |
|     protected function getSafeHtmlId()
 | |
|     {
 | |
|         return preg_replace('/[^a-zA-Z0-9]/', '_', $this->getId());
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Get a unique menu item id
 | |
|      *
 | |
|      * @return string the ID
 | |
|      */
 | |
|     public function getUniqueId()
 | |
|     {
 | |
|         if ($this->parent === null) {
 | |
|             return 'menuitem-' . $this->getSafeHtmlId();
 | |
|         } else {
 | |
|             return $this->parent->getUniqueId() . '-' . $this->getSafeHtmlId();
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Set the title of this menu
 | |
|      *
 | |
|      * @param   string  $title  The title to set for this menu
 | |
|      *
 | |
|      * @return  $this
 | |
|      */
 | |
|     public function setTitle($title)
 | |
|     {
 | |
|         $this->title = $title;
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Return the title of this menu if set, otherwise its id
 | |
|      *
 | |
|      * @return  string
 | |
|      */
 | |
|     public function getTitle()
 | |
|     {
 | |
|         return $this->title ? $this->title : $this->id;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Set the priority of this menu
 | |
|      *
 | |
|      * @param   int     $priority   The priority to set for this menu
 | |
|      *
 | |
|      * @return  $this
 | |
|      */
 | |
|     public function setPriority($priority)
 | |
|     {
 | |
|         $this->priority = (int) $priority;
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Return the priority of this menu
 | |
|      *
 | |
|      * @return  int
 | |
|      */
 | |
|     public function getPriority()
 | |
|     {
 | |
|         return $this->priority;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Set the url of this menu
 | |
|      *
 | |
|      * @param   Url|string  $url    The url to set for this menu
 | |
|      *
 | |
|      * @return  $this
 | |
|      */
 | |
|     public function setUrl($url)
 | |
|     {
 | |
|         $this->url = $url;
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Return the url of this menu
 | |
|      *
 | |
|      * @return Url|null
 | |
|      */
 | |
|     public function getUrl()
 | |
|     {
 | |
|         if ($this->url !== null && ! $this->url instanceof Url) {
 | |
|             $this->url = Url::fromPath($this->url);
 | |
|         }
 | |
|         return $this->url;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Set the path to the icon of this menu
 | |
|      *
 | |
|      * @param   string  $path   The path to the icon for this menu
 | |
|      *
 | |
|      * @return  $this
 | |
|      */
 | |
|     public function setIcon($path)
 | |
|     {
 | |
|         $this->icon = $path;
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Return the path to the icon of this menu
 | |
|      *
 | |
|      * @return  string
 | |
|      */
 | |
|     public function getIcon()
 | |
|     {
 | |
|         return $this->icon;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Get the class that renders the current menu item
 | |
|      *
 | |
|      * @return MenuItemRenderer
 | |
|      */
 | |
|     public function getRenderer()
 | |
|     {
 | |
|         return $this->itemRenderer;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Set the class that renders the current menu item
 | |
|      *
 | |
|      * @param MenuItemRenderer $renderer
 | |
|      */
 | |
|     public function setRenderer(MenuItemRenderer $renderer)
 | |
|     {
 | |
|         $this->itemRenderer = $renderer;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Return whether this menu has any sub menus
 | |
|      *
 | |
|      * @return  bool
 | |
|      */
 | |
|     public function hasSubMenus()
 | |
|     {
 | |
|         return false === empty($this->subMenus);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Add a sub menu to this menu
 | |
|      *
 | |
|      * @param   string          $id             The id of the menu to add
 | |
|      * @param   ConfigObject    $menuConfig     The config with which to initialize the menu
 | |
|      *
 | |
|      * @return  static
 | |
|      */
 | |
|     public function addSubMenu($id, ConfigObject $menuConfig = null)
 | |
|     {
 | |
|         $subMenu = new static($id, $menuConfig, $this);
 | |
|         $this->subMenus[$id] = $subMenu;
 | |
|         return $subMenu;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Get the permission a user is required to have granted to display the menu item
 | |
|      *
 | |
|      * @return string|null
 | |
|      */
 | |
|     public function getPermission()
 | |
|     {
 | |
|         return $this->permission;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Get parent menu
 | |
|      *
 | |
|      * @return \Icinga\Web\Menu
 | |
|      */
 | |
|     public function getParent()
 | |
|     {
 | |
|         return $this->parent;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Get submenus
 | |
|      *
 | |
|      * @return array
 | |
|      */
 | |
|     public function getSubMenus()
 | |
|     {
 | |
|         return $this->subMenus;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Set permission a user is required to have granted to display the menu item
 | |
|      *
 | |
|      * If a permission is set, authentication is of course required.
 | |
|      *
 | |
|      * @param   string  $permission
 | |
|      *
 | |
|      * @return  $this
 | |
|      */
 | |
|     public function setPermission($permission)
 | |
|     {
 | |
|         $this->permission = (string) $permission;
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Merge Sub Menus
 | |
|      *
 | |
|      * @param   array $submenus
 | |
|      *
 | |
|      * @return  $this
 | |
|      */
 | |
|     public function mergeSubMenus(array $submenus)
 | |
|     {
 | |
|         foreach ($submenus as $menu) {
 | |
|             $this->mergeSubMenu($menu);
 | |
|         }
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Merge Sub Menu
 | |
|      *
 | |
|      * @param   Menu $menu
 | |
|      *
 | |
|      * @return  static
 | |
|      */
 | |
|     public function mergeSubMenu(Menu $menu)
 | |
|     {
 | |
|         $name = $menu->getId();
 | |
|         if (array_key_exists($name, $this->subMenus)) {
 | |
|             /** @var $current Menu */
 | |
|             $current = $this->subMenus[$name];
 | |
|             if ($current->conflictsWith($menu)) {
 | |
|                 while (array_key_exists($name, $this->subMenus)) {
 | |
|                     if (preg_match('/_(\d+)$/', $name, $m)) {
 | |
|                         $name = preg_replace('/_\d+$/', $m[1]++, $name);
 | |
|                     } else {
 | |
|                         $name .= '_2';
 | |
|                     }
 | |
|                 }
 | |
|                 $menu->setId($name);
 | |
|                 $this->subMenus[$name] = $menu;
 | |
|             } else {
 | |
|                 $current->setProperties($menu->getProperties());
 | |
|                 foreach ($menu->subMenus as $child) {
 | |
|                     $current->mergeSubMenu($child);
 | |
|                 }
 | |
|             }
 | |
|         } else {
 | |
|             $this->subMenus[$name] = $menu;
 | |
|         }
 | |
| 
 | |
|         return $this->subMenus[$name];
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Add a Menu
 | |
|      *
 | |
|      * @param   $name
 | |
|      * @param   array $config
 | |
|      *
 | |
|      * @return  static
 | |
|      */
 | |
|     public function add($name, $config = array())
 | |
|     {
 | |
|         return $this->addSubMenu($name, new ConfigObject($config));
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Return whether a sub menu with the given id exists
 | |
|      *
 | |
|      * @param   string  $id     The id of the sub menu
 | |
|      *
 | |
|      * @return  bool
 | |
|      */
 | |
|     public function hasSubMenu($id)
 | |
|     {
 | |
|         return array_key_exists($id, $this->subMenus);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Get sub menu by its id
 | |
|      *
 | |
|      * @param   string      $id     The id of the sub menu
 | |
|      *
 | |
|      * @return  static              The found sub menu
 | |
|      *
 | |
|      * @throws  ProgrammingError    In case there is no sub menu with the given id to be found
 | |
|      */
 | |
|     public function getSubMenu($id)
 | |
|     {
 | |
|         if (false === $this->hasSubMenu($id)) {
 | |
|             throw new ProgrammingError(
 | |
|                 'Tried to get invalid sub menu "%s"',
 | |
|                 $id
 | |
|             );
 | |
|         }
 | |
| 
 | |
|         return $this->subMenus[$id];
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Order this menu's sub menus based on their priority
 | |
|      *
 | |
|      * @return  $this
 | |
|      */
 | |
|     public function order()
 | |
|     {
 | |
|         uasort($this->subMenus, array($this, 'cmpSubMenus'));
 | |
|         foreach ($this->subMenus as $subMenu) {
 | |
|             if ($subMenu->hasSubMenus()) {
 | |
|                 $subMenu->order();
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Compare sub menus based on priority and title
 | |
|      *
 | |
|      * @param   Menu    $a
 | |
|      * @param   Menu    $b
 | |
|      *
 | |
|      * @return  int
 | |
|      */
 | |
|     protected function cmpSubMenus($a, $b)
 | |
|     {
 | |
|         if ($a->priority == $b->priority) {
 | |
|             return $a->getTitle() > $b->getTitle() ? 1 : (
 | |
|                 $a->getTitle() < $b->getTitle() ? -1 : 0
 | |
|             );
 | |
|         }
 | |
| 
 | |
|         return $a->priority > $b->priority ? 1 : -1;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Flatten configs
 | |
|      *
 | |
|      * @param   array   $configs    An two dimensional array of menu configurations
 | |
|      *
 | |
|      * @return  array               The flattened config, as key-value array
 | |
|      */
 | |
|     protected function flattenConfigs(array $configs)
 | |
|     {
 | |
|         $flattened = array();
 | |
|         foreach ($configs as $menuConfig) {
 | |
|             foreach ($menuConfig as $section => $itemConfig) {
 | |
|                 while (array_key_exists($section, $flattened)) {
 | |
|                     $section .= '_dup';
 | |
|                 }
 | |
|                 $flattened[$section] = $itemConfig;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         return $flattened;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Load the sub menus
 | |
|      *
 | |
|      * @param   array   $menus  The menus to load, as key-value array
 | |
|      *
 | |
|      * @return  $this
 | |
|      */
 | |
|     protected function loadSubMenus(array $menus)
 | |
|     {
 | |
|         foreach ($menus as $menuId => $menuConfig) {
 | |
|             $this->addSubMenu($menuId, $menuConfig);
 | |
|         }
 | |
| 
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Check whether the current menu node has any sub menus
 | |
|      *
 | |
|      * @return  bool
 | |
|      */
 | |
|     public function hasChildren()
 | |
|     {
 | |
|         $current = $this->current();
 | |
|         if (false !== $current) {
 | |
|             return $current->hasSubMenus();
 | |
|         }
 | |
| 
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Return a iterator for the current menu node
 | |
|      *
 | |
|      * @return  RecursiveIterator
 | |
|      */
 | |
|     public function getChildren()
 | |
|     {
 | |
|         return $this->current();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Rewind the iterator to its first menu node
 | |
|      */
 | |
|     public function rewind()
 | |
|     {
 | |
|         reset($this->subMenus);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Return whether the iterator position is valid
 | |
|      *
 | |
|      * @return bool
 | |
|      */
 | |
|     public function valid()
 | |
|     {
 | |
|         return $this->key() !== null;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Return the current menu node
 | |
|      *
 | |
|      * @return static
 | |
|      */
 | |
|     public function current()
 | |
|     {
 | |
|         return current($this->subMenus);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Return the id of the current menu node
 | |
|      *
 | |
|      * @return string
 | |
|      */
 | |
|     public function key()
 | |
|     {
 | |
|         return key($this->subMenus);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Move the iterator to the next menu node
 | |
|      */
 | |
|     public function next()
 | |
|     {
 | |
|         next($this->subMenus);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * PHP 5.3 GC should not leak, but just to be on the safe side...
 | |
|      */
 | |
|     public function __destruct()
 | |
|     {
 | |
|         $this->parent = null;
 | |
|     }
 | |
| }
 |