diff --git a/library/Icinga/Application/Modules/Module.php b/library/Icinga/Application/Modules/Module.php index 3d5e3752e..a4b87be08 100644 --- a/library/Icinga/Application/Modules/Module.php +++ b/library/Icinga/Application/Modules/Module.php @@ -5,6 +5,7 @@ namespace Icinga\Application\Modules; use Exception; +use Zend_Config; use Zend_Controller_Router_Route_Abstract; use Zend_Controller_Router_Route as Route; use Icinga\Application\ApplicationBootstrap; @@ -13,6 +14,7 @@ use Icinga\Application\Icinga; use Icinga\Logger\Logger; use Icinga\Util\Translator; use Icinga\Web\Hook; +use Icinga\Web\Menu; use Icinga\Web\Widget; use Icinga\Util\File; use Icinga\Exception\ProgrammingError; @@ -136,7 +138,6 @@ class Module */ private $app; - /** * Routes to add to the route chain * @@ -146,6 +147,42 @@ class Module */ protected $routes = array(); + /** + * A set of menu elements + * + * @var array + */ + protected $menuItems = array(); + + /** + * Get all Menu Items + * + * @return array + */ + public function getMenuItems() + { + $this->launchConfigScript(); + return $this->menuItems; + } + + /** + * Add a menu Section to the Sidebar menu + * + * @param $name + * @param array $properties + * @return mixed + */ + protected function menuSection($name, array $properties = array()) + { + if (array_key_exists($name, $this->menuItems)) { + $this->menuItems[$name]->setProperties($properties); + } else { + $this->menuItems[$name] = new Menu($name, new Zend_Config($properties)); + } + + return $this->menuItems[$name]; + } + /** * Create a new module object * @@ -781,4 +818,15 @@ class Module $this->routes[$name] = $route; return $this; } + + /** + * Translate a string with the global mt() + * + * @param $string + * @return mixed|string + */ + protected function translate($string) + { + return mt($this->name, $string); + } } diff --git a/library/Icinga/Web/Menu.php b/library/Icinga/Web/Menu.php index d5b7ba882..0d8cda402 100644 --- a/library/Icinga/Web/Menu.php +++ b/library/Icinga/Web/Menu.php @@ -4,6 +4,7 @@ namespace Icinga\Web; +use Icinga\Exception\ConfigurationError; use Zend_Config; use RecursiveIterator; use Icinga\Application\Config; @@ -67,20 +68,68 @@ class Menu implements RecursiveIterator public function __construct($id, Zend_Config $config = null) { $this->id = $id; + $this->setProperties($config); + } - if ($config !== null) { - foreach ($config as $key => $value) { + /** + * Set all given properties + * + * @param array|Zend_Config $props Property list + */ + public function setProperties($props = null) + { + if ($props !== null) { + foreach ($props as $key => $value) { $method = 'set' . implode('', array_map('ucfirst', explode('_', strtolower($key)))); 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 * + * THIS IS OBSOLATE. LEFT HERE FOR FUTURE USE WITH USER-SPECIFIC MODULES + * * @return self */ public static function fromConfig() @@ -100,6 +149,63 @@ class Menu implements RecursiveIterator return $menu->loadSubMenus($menu->flattenConfigs($menuConfigs)); } + /** + * Create menu from the application's menu config plus menu entries provided by all enabled modules + * + * @return self + */ + public static function load() + { + /** @var $menu \Icinga\Web\Menu */ + $menu = new static('menu'); + $menu->addMainMenuItems(); + $manager = Icinga::app()->getModuleManager(); + foreach ($manager->getLoadedModules() as $module) { + /** @var $module \Icinga\Application\Modules\Module */ + $menu->mergeSubMenus($module->getMenuItems()); + } + return $menu->order(); + } + + /** + * Add Applications Main Menu Items + */ + protected function addMainMenuItems() + { + $this->add(t('Dashboard'), array( + 'url' => 'dashboard', + 'icon' => 'img/icons/dashboard.png', + 'priority' => 10 + )); + + $section = $this->add(t('System'), array( + 'icon' => 'img/icons/configuration.png', + 'priority' => 200 + )); + $section->add(t('Preferences'), array( + 'url' => 'preference', + 'priority' => 200 + )); + $section->add(t('Configuration'), array( + 'url' => 'config', + 'priority' => 300 + )); + $section->add(t('Modules'), array( + 'url' => 'config/modules', + 'priority' => 400 + )); + $section->add(t('ApplicationLog'), array( + 'url' => 'list/applicationlog', + 'priority' => 500 + )); + + $this->add(t('Logout'), array( + 'url' => 'authentication/logout', + 'icon' => 'img/icons/logout.png', + 'priority' => 300 + )); + } + /** * Set the id of this menu * @@ -253,6 +359,79 @@ class Menu implements RecursiveIterator return $subMenu; } + /** + * Set required Permissions + * + * @param $permission + * @return $this + */ + public function requirePermission($permission) + { + // Not implemented yet + 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 mixed + */ + 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 Menu + */ + public function add($name, $config = array()) + { + return $this->addSubMenu($name, new Zend_Config($config)); + } + /** * Return whether a sub menu with the given id exists *