NavigationItem: Add support for custom renderers

refs #5600
This commit is contained in:
Johannes Meyer 2015-09-03 11:25:51 +02:00
parent 811269df01
commit 2834e206d5
2 changed files with 164 additions and 53 deletions

View File

@ -9,7 +9,7 @@ use IteratorAggregate;
use Icinga\Application\Icinga;
use Icinga\Exception\IcingaException;
use Icinga\Exception\ProgrammingError;
use Icinga\Web\View;
use Icinga\Web\Navigation\Renderer\NavigationItemRenderer;
use Icinga\Web\Url;
/**
@ -24,6 +24,11 @@ class NavigationItem implements IteratorAggregate
*/
const LINK_ALTERNATIVE = 'span';
/**
* The class namespace where to locate navigation type renderer classes
*/
const RENDERER_NS = 'Web\\Navigation\\Renderer';
/**
* Whether this item is active
*
@ -97,11 +102,11 @@ class NavigationItem implements IteratorAggregate
protected $urlParameters;
/**
* View
* This item's renderer
*
* @var View
* @var NavigationItemRenderer
*/
protected $view;
protected $renderer;
/**
* Create a new NavigationItem
@ -500,33 +505,6 @@ class NavigationItem implements IteratorAggregate
return $this;
}
/**
* Return the view
*
* @return View
*/
public function view()
{
if ($this->view === null) {
$this->setView(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 this item's properties
*
@ -600,6 +578,79 @@ class NavigationItem implements IteratorAggregate
return $this->getUrl() !== $item->getUrl();
}
/**
* Create and return the given renderer
*
* @param string $name
*
* @return NavigationItemRenderer
*/
protected function createRenderer($name)
{
$renderer = null;
foreach (Icinga::app()->getModuleManager()->getLoadedModules() as $module) {
$classPath = 'Icinga\\Module\\' . $module->getName() . '\\' . static::RENDERER_NS . '\\' . $name;
if (class_exists($classPath)) {
$renderer = new $classPath();
break;
}
}
if ($renderer === null) {
$classPath = 'Icinga\\' . static::RENDERER_NS . '\\' . $name;
if (class_exists($classPath)) {
$renderer = new $classPath();
}
}
if ($renderer === null) {
throw new ProgrammingError(
'Cannot find renderer "%s" for navigation item "%s"',
$name,
$this->getName()
);
} elseif (! $renderer instanceof NavigationItemRenderer) {
throw new ProgrammingError('Class %s must inherit from NavigationItemRenderer', $classPath);
}
return $renderer;
}
/**
* Set this item's renderer
*
* @param string|NavigationItemRenderer $renderer
*
* @return $this
*
* @throws InvalidArgumentException If the $renderer argument is neither a string nor a NavigationItemRenderer
*/
public function setRenderer($renderer)
{
if (is_string($renderer)) {
$renderer = $this->createRenderer($renderer);
} elseif (! $renderer instanceof NavigationItemRenderer) {
throw new InvalidArgumentException('Argument $renderer must be of type string or NavigationItemRenderer');
}
$this->renderer = $renderer;
return $this;
}
/**
* Return this item's renderer
*
* @return NavigationItemRenderer
*/
public function getRenderer()
{
if ($this->renderer === null) {
$this->setRenderer('NavigationItemRenderer');
}
return $this->renderer;
}
/**
* Return this item rendered to HTML
*
@ -607,28 +658,7 @@ class NavigationItem implements IteratorAggregate
*/
public function render()
{
$label = $this->view()->escape($this->getLabel());
if (($icon = $this->getIcon()) !== null) {
$label = $this->view()->icon($icon) . $label;
}
if (($url = $this->getUrl()) !== null) {
$content = sprintf(
'<a%s href="%s">%s</a>',
$this->view()->propertiesToString($this->getAttributes()),
$this->view()->url($url, $this->getUrlParameters()),
$label
);
} else {
$content = sprintf(
'<%1$s%2$s>%3$s</%1$s>',
static::LINK_ALTERNATIVE,
$this->view()->propertiesToString($this->getAttributes()),
$label
);
}
return $content;
$this->getRenderer()->render($this);
}
/**

View File

@ -0,0 +1,81 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Web\Navigation\Renderer;
use Icinga\Application\Icinga;
use Icinga\Web\Navigation\NavigationItem;
use Icinga\Web\View;
/**
* NavigationItemRenderer
*/
class NavigationItemRenderer
{
/**
* View
*
* @var View
*/
protected $view;
/**
* Return the view
*
* @return View
*/
public function view()
{
if ($this->view === null) {
$this->setView(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;
}
/**
* Render the given navigation item as HTML anchor
*
* @param NavigationItem $item
*
* @return string
*/
public function render(NavigationItem $item)
{
$label = $this->view()->escape($item->getLabel());
if (($icon = $item->getIcon()) !== null) {
$label = $this->view()->icon($icon) . $label;
}
if (($url = $item->getUrl()) !== null) {
$content = sprintf(
'<a%s href="%s">%s</a>',
$this->view()->propertiesToString($item->getAttributes()),
$this->view()->url($url, $item->getUrlParameters()),
$label
);
} else {
$content = sprintf(
'<%1$s%2$s>%3$s</%1$s>',
$item::LINK_ALTERNATIVE,
$this->view()->propertiesToString($item->getAttributes()),
$label
);
}
return $content;
}
}