lib: Add navigation classes (WIP)
- Lacks custom renderer functionality - Lacks navigation item priorities - Lacks permission handling refs #5600
This commit is contained in:
parent
1014cdfa3c
commit
1122ffafad
|
@ -0,0 +1,21 @@
|
||||||
|
<?php
|
||||||
|
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
|
||||||
|
|
||||||
|
namespace Icinga\Web\Navigation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dropdown navigation item
|
||||||
|
*
|
||||||
|
* @see \Icinga\Web\Navigation\Navigation For a usage example.
|
||||||
|
*/
|
||||||
|
class DropdownItem extends NavigationItem
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function init()
|
||||||
|
{
|
||||||
|
$this->children->setLayout(Navigation::LAYOUT_DROPDOWN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,235 @@
|
||||||
|
<?php
|
||||||
|
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
|
||||||
|
|
||||||
|
namespace Icinga\Web\Navigation;
|
||||||
|
|
||||||
|
use ArrayAccess;
|
||||||
|
use ArrayIterator;
|
||||||
|
use Countable;
|
||||||
|
use InvalidArgumentException;
|
||||||
|
use IteratorAggregate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Container for navigation items
|
||||||
|
*
|
||||||
|
* Usage example:
|
||||||
|
* <code>
|
||||||
|
* <?php
|
||||||
|
*
|
||||||
|
* namespace Icinga\Example;
|
||||||
|
*
|
||||||
|
* use Icinga\Web\Navigation\DropdownItem;
|
||||||
|
* use Icinga\Web\Navigation\Navigation;
|
||||||
|
* use Icinga\Web\Navigation\NavigationItem;
|
||||||
|
*
|
||||||
|
* $navigation = new Navigation();
|
||||||
|
* $navigation->setLayout(Navigation::LAYOUT_TABS);
|
||||||
|
* $home = new NavigationItem();
|
||||||
|
* $home
|
||||||
|
* ->setIcon('home')
|
||||||
|
* ->setLabel('Home');
|
||||||
|
* ->setUrl('/home');
|
||||||
|
* $logout = new NavigationItem();
|
||||||
|
* $logout
|
||||||
|
* ->setIcon('logout')
|
||||||
|
* ->setLabel('Logout')
|
||||||
|
* ->setUrl('/logout');
|
||||||
|
* $dropdown = new DropdownItem();
|
||||||
|
* $dropdown
|
||||||
|
* ->setIcon('user')
|
||||||
|
* ->setLabel('Preferences');
|
||||||
|
* $preferences = new NavigationItem();
|
||||||
|
* $preferences
|
||||||
|
* ->setIcon('preferences');
|
||||||
|
* ->setLabel('preferences')
|
||||||
|
* ->setUrl('/preferences');
|
||||||
|
* $dropdown->addChild($preferences);
|
||||||
|
* $navigation
|
||||||
|
* ->addItem($home)
|
||||||
|
* ->addItem($logout);
|
||||||
|
* ->addItem($dropdown);
|
||||||
|
* echo $navigation
|
||||||
|
* ->getRenderer()
|
||||||
|
* ->setCssClass('example-nav')
|
||||||
|
* ->render();
|
||||||
|
*/
|
||||||
|
class Navigation implements ArrayAccess, Countable, IteratorAggregate
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Flag for dropdown layout
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
const LAYOUT_DROPDOWN = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flag for tabs layout
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
const LAYOUT_TABS = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Navigation items
|
||||||
|
*
|
||||||
|
* @var NavigationItem[]
|
||||||
|
*/
|
||||||
|
protected $items = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Navigation layout
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $layout;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function offsetExists($offset)
|
||||||
|
{
|
||||||
|
return isset($this->items[$offset]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function offsetGet($offset)
|
||||||
|
{
|
||||||
|
return isset($this->items[$offset]) ? $this->items[$offset] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function offsetSet($offset, $value)
|
||||||
|
{
|
||||||
|
$this->items[$offset] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function offsetUnset($offset)
|
||||||
|
{
|
||||||
|
unset($this->items[$offset]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function count()
|
||||||
|
{
|
||||||
|
return count($this->items);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getIterator()
|
||||||
|
{
|
||||||
|
return new ArrayIterator($this->items);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ad a navigation item
|
||||||
|
*
|
||||||
|
* @param NavigationItem|array $item The item to append
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
* @throws InvalidArgumentException If the item argument is invalid
|
||||||
|
*/
|
||||||
|
public function addItem(NavigationItem $item)
|
||||||
|
{
|
||||||
|
if (! $item instanceof NavigationItem) {
|
||||||
|
if (! is_array($item)) {
|
||||||
|
throw new InvalidArgumentException(
|
||||||
|
'Argument item must be either an array or an instance of NavigationItem'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$item = new NavigationItem($item);
|
||||||
|
}
|
||||||
|
$this->items[] = $item;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the item with the given ID
|
||||||
|
*
|
||||||
|
* @param mixed $id
|
||||||
|
* @param mixed $default
|
||||||
|
*
|
||||||
|
* @return NavigationItem|mixed
|
||||||
|
*/
|
||||||
|
public function getItem($id, $default = null)
|
||||||
|
{
|
||||||
|
if (isset($this->items[$id])) {
|
||||||
|
return $this->items[$id];
|
||||||
|
}
|
||||||
|
return $default;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the items
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getItems()
|
||||||
|
{
|
||||||
|
return $this->items;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get whether the navigation has items
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function hasItems()
|
||||||
|
{
|
||||||
|
return ! empty($this->items);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get whether the navigation is empty
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isEmpty()
|
||||||
|
{
|
||||||
|
return empty($this->items);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the layout
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getLayout()
|
||||||
|
{
|
||||||
|
return $this->layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the layout
|
||||||
|
*
|
||||||
|
* @param int $layout
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setLayout($layout)
|
||||||
|
{
|
||||||
|
$this->layout = (int) $layout;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the navigation renderer
|
||||||
|
*
|
||||||
|
* @return RecursiveNavigationRenderer
|
||||||
|
*/
|
||||||
|
public function getRenderer()
|
||||||
|
{
|
||||||
|
return new RecursiveNavigationRenderer($this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,483 @@
|
||||||
|
<?php
|
||||||
|
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
|
||||||
|
|
||||||
|
namespace Icinga\Web\Navigation;
|
||||||
|
|
||||||
|
use Countable;
|
||||||
|
use InvalidArgumentException;
|
||||||
|
use IteratorAggregate;
|
||||||
|
use Icinga\Application\Icinga;
|
||||||
|
use Icinga\Web\View;
|
||||||
|
use Icinga\Web\Url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A navigation item
|
||||||
|
*
|
||||||
|
* @see \Icinga\Web\Navigation\Navigation For a usage example.
|
||||||
|
*/
|
||||||
|
class NavigationItem implements Countable, IteratorAggregate
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Alternative markup element if the navigation item has no URL
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
const LINK_ALTERNATIVE = 'span';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the item is active
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $active = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attributes of the item's element
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $attributes = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Item's children
|
||||||
|
*
|
||||||
|
* @var Navigation
|
||||||
|
*/
|
||||||
|
protected $children;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Icon
|
||||||
|
*
|
||||||
|
* @var string|null
|
||||||
|
*/
|
||||||
|
protected $icon;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Item's ID
|
||||||
|
*
|
||||||
|
* @var mixed
|
||||||
|
*/
|
||||||
|
protected $id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Label
|
||||||
|
*
|
||||||
|
* @var string|null
|
||||||
|
*/
|
||||||
|
protected $label;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parent
|
||||||
|
*
|
||||||
|
* @var NavigationItem|null
|
||||||
|
*/
|
||||||
|
private $parent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* URL
|
||||||
|
*
|
||||||
|
* @var Url|null
|
||||||
|
*/
|
||||||
|
protected $url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* URL parameters
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $urlParameters = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* View
|
||||||
|
*
|
||||||
|
* @var View|null
|
||||||
|
*/
|
||||||
|
protected $view;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new navigation item
|
||||||
|
*
|
||||||
|
* @param array $properties
|
||||||
|
*/
|
||||||
|
public function __construct(array $properties = array())
|
||||||
|
{
|
||||||
|
if (! empty($properties)) {
|
||||||
|
$this->setProperties($properties);
|
||||||
|
}
|
||||||
|
$this->children = new Navigation();
|
||||||
|
$this->init();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the navigation item
|
||||||
|
*/
|
||||||
|
public function init()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function count()
|
||||||
|
{
|
||||||
|
return $this->children->count();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getIterator()
|
||||||
|
{
|
||||||
|
return $this->children;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get whether the item is active
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function getActive()
|
||||||
|
{
|
||||||
|
return $this->active;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set whether the item is active
|
||||||
|
*
|
||||||
|
* Bubbles active state.
|
||||||
|
*
|
||||||
|
* @param bool $active
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setActive($active = true)
|
||||||
|
{
|
||||||
|
$this->active = (bool) $active;
|
||||||
|
$parent = $this;
|
||||||
|
while (($parent = $parent->parent) !== null) {
|
||||||
|
$parent->setActive($active);
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an attribute's value of the item's element
|
||||||
|
*
|
||||||
|
* @param string $name Name of the attribute
|
||||||
|
* @param mixed $default Default value
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getAttribute($name, $default = null)
|
||||||
|
{
|
||||||
|
$name = (string) $name;
|
||||||
|
if (array_key_exists($name, $this->attributes)) {
|
||||||
|
return $this->attributes[$name];
|
||||||
|
}
|
||||||
|
return $default;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set an attribute of the item's element
|
||||||
|
*
|
||||||
|
* @param string $name Name of the attribute
|
||||||
|
* @param mixed $value Value of the attribute
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setAttribute($name, $value)
|
||||||
|
{
|
||||||
|
$name = (string) $name;
|
||||||
|
$this->attributes[$name] = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the item's attributes
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getAttributes()
|
||||||
|
{
|
||||||
|
return $this->attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the item's attributes
|
||||||
|
*
|
||||||
|
* @param array $attributes
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setAttributes(array $attributes)
|
||||||
|
{
|
||||||
|
foreach ($attributes as $name => $value) {
|
||||||
|
$this->setAttribute($name, $value);
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a child item to this item
|
||||||
|
*
|
||||||
|
* Bubbles active state.
|
||||||
|
*
|
||||||
|
* @param NavigationItem|array $child The child to add
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
* @throws InvalidArgumentException If the child argument is invalid
|
||||||
|
*/
|
||||||
|
public function addChild($child)
|
||||||
|
{
|
||||||
|
if (! $child instanceof NavigationItem) {
|
||||||
|
if (! is_array($child)) {
|
||||||
|
throw new InvalidArgumentException(
|
||||||
|
'Argument child must be either an array or an instance of NavigationItem'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$child = new NavigationItem($child);
|
||||||
|
}
|
||||||
|
$child->parent = $this;
|
||||||
|
$this->children->addItem($child);
|
||||||
|
if ($child->getActive()) {
|
||||||
|
$this->setActive();
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the item's children
|
||||||
|
*
|
||||||
|
* @return Navigation
|
||||||
|
*/
|
||||||
|
public function getChildren()
|
||||||
|
{
|
||||||
|
return $this->children;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get whether the item has children
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function hasChildren()
|
||||||
|
{
|
||||||
|
return ! $this->children->isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set children
|
||||||
|
*
|
||||||
|
* @param Navigation $children
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setChildren(Navigation $children)
|
||||||
|
{
|
||||||
|
$this->children = $children;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the icon
|
||||||
|
*
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public function getIcon()
|
||||||
|
{
|
||||||
|
return $this->icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the icon
|
||||||
|
*
|
||||||
|
* @param string $icon
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setIcon($icon)
|
||||||
|
{
|
||||||
|
$this->icon = (string) $icon;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the item's ID
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getId()
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the item's ID
|
||||||
|
*
|
||||||
|
* @param mixed $id ID of the item
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setId($id)
|
||||||
|
{
|
||||||
|
$this->id = $id;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the label
|
||||||
|
*
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public function getLabel()
|
||||||
|
{
|
||||||
|
return $this->label;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the label
|
||||||
|
*
|
||||||
|
* @param string $label
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setLabel($label)
|
||||||
|
{
|
||||||
|
$this->label = (string) $label;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the URL
|
||||||
|
*
|
||||||
|
* @return Url|null
|
||||||
|
*/
|
||||||
|
public function getUrl()
|
||||||
|
{
|
||||||
|
if ($this->url !== null && ! $this->url instanceof Url) {
|
||||||
|
$this->url = Url::fromPath((string) $this->url);
|
||||||
|
}
|
||||||
|
return $this->url;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the URL
|
||||||
|
*
|
||||||
|
* @param Url|string $url
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setUrl($url)
|
||||||
|
{
|
||||||
|
$this->url = $url;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the URL parameters
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getUrlParameters()
|
||||||
|
{
|
||||||
|
return $this->urlParameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the URL parameters
|
||||||
|
*
|
||||||
|
* @param array $urlParameters
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setUrlParameters(array $urlParameters)
|
||||||
|
{
|
||||||
|
$this->urlParameters = $urlParameters;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the view
|
||||||
|
*
|
||||||
|
* @return View
|
||||||
|
*/
|
||||||
|
public function getView()
|
||||||
|
{
|
||||||
|
if ($this->view === null) {
|
||||||
|
$this->view = Icinga::app()->getViewRenderer()->view;
|
||||||
|
}
|
||||||
|
return $this->view;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the view
|
||||||
|
*
|
||||||
|
* @param View $view
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setView(View $view)
|
||||||
|
{
|
||||||
|
$this->view = $view;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set properties for the item
|
||||||
|
*
|
||||||
|
* @param array $properties
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setProperties(array $properties = array())
|
||||||
|
{
|
||||||
|
foreach ($properties as $name => $value) {
|
||||||
|
$setter = 'set' . ucfirst($name);
|
||||||
|
if (method_exists($this, $setter)) {
|
||||||
|
$this->$setter($value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the navigation item to HTML
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function render()
|
||||||
|
{
|
||||||
|
$view = $this->getView();
|
||||||
|
$label = $view->escape($this->getLabel());
|
||||||
|
if (null !== $icon = $this->getIcon()) {
|
||||||
|
$label = $view->icon($icon) . $label;
|
||||||
|
}
|
||||||
|
if (null !== $url = $this->getUrl()) {
|
||||||
|
$content = sprintf(
|
||||||
|
'<a%s href="%s">%s</a>',
|
||||||
|
$view->propertiesToString($this->getAttributes()),
|
||||||
|
$view->url($url, $this->getUrlParameters()),
|
||||||
|
$label
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$content = sprintf(
|
||||||
|
'<%1$s%2$s>%3$s</%1$s>',
|
||||||
|
static::LINK_ALTERNATIVE,
|
||||||
|
$view->propertiesToString($this->getAttributes()),
|
||||||
|
$label
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return $content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the navigation item to HTML
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return $this->render();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,340 @@
|
||||||
|
<?php
|
||||||
|
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
|
||||||
|
|
||||||
|
namespace Icinga\Web\Navigation;
|
||||||
|
|
||||||
|
use ArrayIterator;
|
||||||
|
use RecursiveIterator;
|
||||||
|
use Icinga\Application\Icinga;
|
||||||
|
use Icinga\Web\View;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renderer for single level navigation
|
||||||
|
*/
|
||||||
|
class NavigationRenderer implements RecursiveIterator, NavigationRendererInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Content to render
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $content = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CSS class for the navigation element
|
||||||
|
*
|
||||||
|
* @var string|null
|
||||||
|
*/
|
||||||
|
protected $cssClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flags
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
private $flags;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The heading for the navigation
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $heading;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flag for checking whether to call begin/endMarkup() or not
|
||||||
|
*7
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private $inIteration = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterator over navigation
|
||||||
|
*
|
||||||
|
* @var ArrayIterator
|
||||||
|
*/
|
||||||
|
private $iterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current navigation
|
||||||
|
*
|
||||||
|
* @var Navigation
|
||||||
|
*/
|
||||||
|
private $navigation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* View
|
||||||
|
*
|
||||||
|
* @var View|null
|
||||||
|
*/
|
||||||
|
protected $view;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new navigation renderer
|
||||||
|
*
|
||||||
|
* @param Navigation $navigation
|
||||||
|
* @param int $flags
|
||||||
|
*/
|
||||||
|
public function __construct(Navigation $navigation, $flags = 0)
|
||||||
|
{
|
||||||
|
$this->iterator = $navigation->getIterator();
|
||||||
|
$this->navigation = $navigation;
|
||||||
|
$this->flags = $flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getChildren()
|
||||||
|
{
|
||||||
|
return new static($this->current()->getChildren(), $this->flags & static::NAV_DISABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function hasChildren()
|
||||||
|
{
|
||||||
|
return $this->current()->hasChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
* @return \Icinga\Web\Navigation\NavigationItem
|
||||||
|
*/
|
||||||
|
public function current()
|
||||||
|
{
|
||||||
|
return $this->iterator->current();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function key()
|
||||||
|
{
|
||||||
|
return $this->iterator->key();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function next()
|
||||||
|
{
|
||||||
|
$this->iterator->next();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function rewind()
|
||||||
|
{
|
||||||
|
$this->iterator->rewind();
|
||||||
|
if (! (bool) ($this->flags & static::NAV_DISABLE) && ! $this->inIteration) {
|
||||||
|
$this->content[] = $this->beginMarkup();
|
||||||
|
$this->inIteration = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function valid()
|
||||||
|
{
|
||||||
|
$valid = $this->iterator->valid();
|
||||||
|
if (! (bool) ($this->flags & static::NAV_DISABLE) && ! $valid && $this->inIteration) {
|
||||||
|
$this->content[] = $this->endMarkup();
|
||||||
|
$this->inIteration = false;
|
||||||
|
}
|
||||||
|
return $valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Begin navigation markup
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function beginMarkup()
|
||||||
|
{
|
||||||
|
$content = array();
|
||||||
|
if ($this->flags & static::NAV_MAJOR) {
|
||||||
|
$el = 'nav';
|
||||||
|
} else {
|
||||||
|
$el = 'div';
|
||||||
|
}
|
||||||
|
if (($elCssClass = $this->getCssClass()) !== null) {
|
||||||
|
$elCss = ' class="' . $elCssClass . '"';
|
||||||
|
} else {
|
||||||
|
$elCss = '';
|
||||||
|
}
|
||||||
|
$content[] = sprintf(
|
||||||
|
'<%s%s role="navigation">',
|
||||||
|
$el,
|
||||||
|
$elCss
|
||||||
|
);
|
||||||
|
$content[] = sprintf(
|
||||||
|
'<h%1$d class="sr-only" tabindex="-1">%2$s</h%1$d>',
|
||||||
|
static::HEADING_RANK,
|
||||||
|
$this->getView()->escape($this->getHeading())
|
||||||
|
);
|
||||||
|
$content[] = $this->beginChildrenMarkup();
|
||||||
|
return implode("\n", $content);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* End navigation markup
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function endMarkup()
|
||||||
|
{
|
||||||
|
$content = array();
|
||||||
|
$content[] = $this->endChildrenMarkup();
|
||||||
|
if ($this->flags & static::NAV_MAJOR) {
|
||||||
|
$content[] = '</nav>';
|
||||||
|
} else {
|
||||||
|
$content[] = '</div>';
|
||||||
|
}
|
||||||
|
return implode("\n", $content);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Begin children markup
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function beginChildrenMarkup()
|
||||||
|
{
|
||||||
|
$ulCssClass = static::CSS_CLASS_NAV;
|
||||||
|
if ($this->navigation->getLayout() & Navigation::LAYOUT_TABS) {
|
||||||
|
$ulCssClass .= ' ' . static::CSS_CLASS_NAV_TABS;
|
||||||
|
}
|
||||||
|
if ($this->navigation->getLayout() & Navigation::LAYOUT_DROPDOWN) {
|
||||||
|
$ulCssClass .= ' ' . static::CSS_CLASS_NAV_DROPDOWN;
|
||||||
|
}
|
||||||
|
return '<ul class="' . $ulCssClass . '">';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* End children markup
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function endChildrenMarkup()
|
||||||
|
{
|
||||||
|
return '</ul>';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Begin item markup
|
||||||
|
*
|
||||||
|
* @param NavigationItem $item
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function beginItemMarkup(NavigationItem $item)
|
||||||
|
{
|
||||||
|
$cssClass = array();
|
||||||
|
if ($item->getActive()) {
|
||||||
|
$cssClass[] = static::CSS_CLASS_ACTIVE;
|
||||||
|
}
|
||||||
|
if ($item->hasChildren()
|
||||||
|
&& $item->getChildren()->getLayout() === Navigation::LAYOUT_DROPDOWN
|
||||||
|
) {
|
||||||
|
$cssClass[] = static::CSS_CLASS_DROPDOWN;
|
||||||
|
$item
|
||||||
|
->setAttribute('class', static::CSS_CLASS_DROPDOWN_TOGGLE)
|
||||||
|
->setIcon(static::DROPDOWN_TOGGLE_ICON)
|
||||||
|
->setUrl('#');
|
||||||
|
}
|
||||||
|
if (! empty($cssClass)) {
|
||||||
|
$content = sprintf('<li class="%s">', implode(' ', $cssClass));
|
||||||
|
} else {
|
||||||
|
$content = '<li>';
|
||||||
|
}
|
||||||
|
return $content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* End item markup
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function endItemMarkup()
|
||||||
|
{
|
||||||
|
return '</li>';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getCssClass()
|
||||||
|
{
|
||||||
|
return $this->cssClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function setCssClass($class)
|
||||||
|
{
|
||||||
|
$this->cssClass = trim((string) $class);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getHeading()
|
||||||
|
{
|
||||||
|
return $this->heading;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function setHeading($heading)
|
||||||
|
{
|
||||||
|
$this->heading = (string) $heading;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the view
|
||||||
|
*
|
||||||
|
* @return View
|
||||||
|
*/
|
||||||
|
public function getView()
|
||||||
|
{
|
||||||
|
if ($this->view === null) {
|
||||||
|
$this->view = Icinga::app()->getViewRenderer()->view;
|
||||||
|
}
|
||||||
|
return $this->view;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the view
|
||||||
|
*
|
||||||
|
* @param View $view
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setView(View $view)
|
||||||
|
{
|
||||||
|
$this->view = $view;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function render()
|
||||||
|
{
|
||||||
|
foreach ($this as $navigationItem) {
|
||||||
|
/** @var \Icinga\Web\Navigation\NavigationItem $navigationItem */
|
||||||
|
$this->content[] = $this->beginItemMarkup($navigationItem);
|
||||||
|
$this->content[] = $navigationItem->render();
|
||||||
|
$this->content[] = $this->endItemMarkup();
|
||||||
|
}
|
||||||
|
return implode("\n", $this->content);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,122 @@
|
||||||
|
<?php
|
||||||
|
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
|
||||||
|
|
||||||
|
namespace Icinga\Web\Navigation;
|
||||||
|
|
||||||
|
use Icinga\Web\View;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for navigation renderer
|
||||||
|
*/
|
||||||
|
interface NavigationRendererInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* CSS class for active items
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
const CSS_CLASS_ACTIVE = 'active';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CSS class for dropdown items
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
const CSS_CLASS_DROPDOWN = 'dropdown';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CSS class for dropdown's trigger
|
||||||
|
*/
|
||||||
|
const CSS_CLASS_DROPDOWN_TOGGLE = 'dropdown-toggle';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CSS class for the ul element
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
const CSS_CLASS_NAV = 'nav';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CSS class for the ul element w/ dropdown layout
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
const CSS_CLASS_NAV_DROPDOWN = 'dropdown-menu';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CSS class for the ul element w/ tabs layout
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
const CSS_CLASS_NAV_TABS = 'nav-tabs';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Icon for the dropdown's trigger
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
const DROPDOWN_TOGGLE_ICON = 'menu';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Heading rank
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
const HEADING_RANK = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flag for major navigation
|
||||||
|
*
|
||||||
|
* With this flag the outer navigation element will be nav instead of div
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
const NAV_MAJOR = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flag for disabling the outer navigation element
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
const NAV_DISABLE = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the CSS class for the outer element
|
||||||
|
*
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public function getCssClass();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the CSS class for the outer element
|
||||||
|
*
|
||||||
|
* @param string $class
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setCssClass($class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the heading
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getHeading();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the heading
|
||||||
|
*
|
||||||
|
* @param string $heading
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setHeading($heading);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render navigation to HTML
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function render();
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,118 @@
|
||||||
|
<?php
|
||||||
|
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
|
||||||
|
|
||||||
|
namespace Icinga\Web\Navigation;
|
||||||
|
|
||||||
|
use RecursiveIteratorIterator;
|
||||||
|
use Icinga\Web\View;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renderer for multi level navigation
|
||||||
|
*
|
||||||
|
* @method NavigationRenderer getInnerIterator() {
|
||||||
|
* {@inheritdoc}
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
class RecursiveNavigationRenderer extends RecursiveIteratorIterator implements NavigationRendererInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Content to render
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $content = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new recursive navigation renderer
|
||||||
|
*
|
||||||
|
* @param Navigation $navigation
|
||||||
|
* @param int $flags
|
||||||
|
*/
|
||||||
|
public function __construct(Navigation $navigation, $flags = 0)
|
||||||
|
{
|
||||||
|
$navigationRenderer = new NavigationRenderer($navigation, $flags & static::NAV_DISABLE);
|
||||||
|
parent::__construct($navigationRenderer, RecursiveIteratorIterator::SELF_FIRST);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function beginIteration()
|
||||||
|
{
|
||||||
|
$this->content[] = $this->getInnerIterator()->beginMarkup();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function endIteration()
|
||||||
|
{
|
||||||
|
$this->content[] = $this->getInnerIterator()->endMarkup();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function beginChildren()
|
||||||
|
{
|
||||||
|
$this->content[] = $this->getInnerIterator()->beginChildrenMarkup();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function endChildren()
|
||||||
|
{
|
||||||
|
$this->content[] = $this->getInnerIterator()->endChildrenMarkup();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getCssClass()
|
||||||
|
{
|
||||||
|
return $this->getInnerIterator()->getCssClass();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function setCssClass($class)
|
||||||
|
{
|
||||||
|
$this->getInnerIterator()->setCssClass($class);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getHeading()
|
||||||
|
{
|
||||||
|
return $this->getInnerIterator()->getHeading();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function setHeading($heading)
|
||||||
|
{
|
||||||
|
$this->getInnerIterator()->setHeading($heading);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function render()
|
||||||
|
{
|
||||||
|
foreach ($this as $navigationItem) {
|
||||||
|
/** @var \Icinga\Web\Navigation\NavigationItem $navigationItem */
|
||||||
|
$this->content[] = $this->getInnerIterator()->beginItemMarkup($navigationItem);
|
||||||
|
$this->content[] = $navigationItem->render();
|
||||||
|
if (! $navigationItem->hasChildren()) {
|
||||||
|
$this->content[] = $this->getInnerIterator()->endItemMarkup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return implode("\n", $this->content);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue