mirror of
				https://github.com/Icinga/icingaweb2.git
				synced 2025-10-25 17:34:03 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			191 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			191 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| /* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
 | |
| 
 | |
| namespace Icinga\Web;
 | |
| 
 | |
| use Exception;
 | |
| use RecursiveIteratorIterator;
 | |
| use Icinga\Application\Logger;
 | |
| 
 | |
| /**
 | |
|  * A renderer to draw a menu with its sub-menus using an unordered html list
 | |
|  */
 | |
| class MenuRenderer extends RecursiveIteratorIterator
 | |
| {
 | |
|     /**
 | |
|      * The relative url of the current request
 | |
|      *
 | |
|      * @var string
 | |
|      */
 | |
|     protected $url;
 | |
| 
 | |
|     /**
 | |
|      * The html tags to assemble the menu with
 | |
|      *
 | |
|      * @var array
 | |
|      */
 | |
|     protected $tags = array();
 | |
| 
 | |
|     /**
 | |
|      * @var bool
 | |
|      */
 | |
|     protected $useCustomRenderer = false;
 | |
| 
 | |
|     /**
 | |
|      * Create a new MenuRenderer
 | |
|      *
 | |
|      * @param   Menu    $menu   The menu to render
 | |
|      * @param   string  $url    A relative url to identify "active" children with
 | |
|      */
 | |
|     public function __construct(Menu $menu, $url = null)
 | |
|     {
 | |
|         if ($url instanceof Url) {
 | |
|             $this->url = $url;
 | |
|         } else {
 | |
|             $this->url = Url::fromPath($url);
 | |
|         }
 | |
|         parent::__construct($menu, RecursiveIteratorIterator::CHILD_FIRST);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @param bool $value
 | |
|      */
 | |
|     public function useCustomRenderer($value = true)
 | |
|     {
 | |
|         $this->useCustomRenderer = $value;
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Register the outer ul opening html-tag
 | |
|      */
 | |
|     public function beginIteration()
 | |
|     {
 | |
|         $this->tags[] = '<ul>';
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Register the outer ul closing html-tag
 | |
|      */
 | |
|     public function endIteration()
 | |
|     {
 | |
|         $this->tags[] = '</ul>';
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Register a inner ul opening html-tag
 | |
|      */
 | |
|     public function beginChildren()
 | |
|     {
 | |
|         // The iterator runs in mode CHILD_FIRST so we need to remember
 | |
|         // where to insert the parent's opening html tag once its rendered
 | |
|         $parent = $this->getSubIterator(0)->current();
 | |
|         $this->tags[$parent->getId() . '_begin'] = null;
 | |
| 
 | |
|         $this->tags[] = '<ul>';
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Register a inner ul closing html-tag
 | |
|      */
 | |
|     public function endChildren()
 | |
|     {
 | |
|         $this->tags[] = '</ul>';
 | |
| 
 | |
|         // Remember the position of the parent's closing html-tag
 | |
|         $parent = $this->getSubIterator(0)->current();
 | |
|         $this->tags[$parent->getId() . '_end'] = null;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Render the given child
 | |
|      *
 | |
|      * @param   Menu    $child      The menu's child to render
 | |
|      *
 | |
|      * @return  string              The child rendered as html
 | |
|      */
 | |
|     public function renderChild(Menu $child)
 | |
|     {
 | |
|         if ($child->getRenderer() !== null && $this->useCustomRenderer) {
 | |
|             try {
 | |
|                 return $child->getRenderer()->render($child);
 | |
|             } catch (Exception $e) {
 | |
|                 Logger::error('Could not invoke custom renderer. Exception: '. $e->getMessage());
 | |
|             }
 | |
|         }
 | |
|         if ($child->getIcon() && strpos($child->getIcon(), '.') === false) {
 | |
|             return sprintf(
 | |
|                 '<a href="%s"><i aria-hidden="true" class="icon-%s"></i>%s</a>',
 | |
|                 $child->getUrl() ?: '#',
 | |
|                 $child->getIcon(),
 | |
|                 htmlspecialchars($child->getTitle())
 | |
|             );
 | |
|         }
 | |
|         return sprintf(
 | |
|             '<a href="%s">%s%s</a>',
 | |
|             $child->getUrl() ?: '#',
 | |
|             $child->getIcon()
 | |
|                 ? '<img aria-hidden="true" src="' . Url::fromPath($child->getIcon()) . '" class="icon" /> '
 | |
|                 : '',
 | |
|             htmlspecialchars($child->getTitle())
 | |
|         );
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Return the menu rendered as html
 | |
|      *
 | |
|      * @return  string
 | |
|      */
 | |
|     public function render()
 | |
|     {
 | |
|         $passedActiveChild = false;
 | |
|         foreach ($this as $child) {
 | |
|             $childIsActive = $this->isActive($child);
 | |
|             if ($childIsActive && $this->getDepth() > 0) {
 | |
|                 $passedActiveChild = true;
 | |
|             }
 | |
| 
 | |
|             if ($childIsActive || ($passedActiveChild && $this->getDepth() === 0)) {
 | |
|                 $passedActiveChild &= $this->getDepth() !== 0;
 | |
|                 $openTag = '<li class="active" id="' . $child->getUniqueId() . '">';
 | |
|             } else {
 | |
|                 $openTag = '<li id="' . $child->getUniqueId() . '">';
 | |
|             }
 | |
|             $content = $this->renderChild($child);
 | |
|             $closingTag = '</li>';
 | |
| 
 | |
|             if (array_key_exists($child->getId() . '_begin', $this->tags)) {
 | |
|                 $this->tags[$child->getId() . '_begin'] = $openTag . $content;
 | |
|                 $this->tags[$child->getId() . '_end'] = $closingTag;
 | |
|             } else {
 | |
|                 $this->tags[] = $openTag . $content . $closingTag;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         return implode("\n", $this->tags);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @see MenuRenderer::render()
 | |
|      */
 | |
|     public function __toString()
 | |
|     {
 | |
|         return $this->render();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Return whether the current request url references the child's url
 | |
|      *
 | |
|      * @param   Menu    $child      The menu's child to check
 | |
|      *
 | |
|      * @return  bool
 | |
|      */
 | |
|     protected function isActive(Menu $child)
 | |
|     {
 | |
|         if (! $this->url) return false;
 | |
|         if (! ($childUrl = $child->getUrl())) return false;
 | |
| 
 | |
|         return $this->url && $this->url->matches($childUrl);
 | |
|     }
 | |
| }
 |