diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 11:46:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 11:46:43 +0000 |
commit | 3e02d5aff85babc3ffbfcf52313f2108e313aa23 (patch) | |
tree | b01f3923360c20a6a504aff42d45670c58af3ec5 /library/Icinga/Web/Navigation/Renderer | |
parent | Initial commit. (diff) | |
download | icingaweb2-upstream.tar.xz icingaweb2-upstream.zip |
Adding upstream version 2.12.1.upstream/2.12.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'library/Icinga/Web/Navigation/Renderer')
7 files changed, 1174 insertions, 0 deletions
diff --git a/library/Icinga/Web/Navigation/Renderer/BadgeNavigationItemRenderer.php b/library/Icinga/Web/Navigation/Renderer/BadgeNavigationItemRenderer.php new file mode 100644 index 0000000..8510f70 --- /dev/null +++ b/library/Icinga/Web/Navigation/Renderer/BadgeNavigationItemRenderer.php @@ -0,0 +1,139 @@ +<?php +/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Web\Navigation\Renderer; + +use Icinga\Web\Navigation\NavigationItem; + +/** + * Abstract base class for a NavigationItem with a status badge + */ +abstract class BadgeNavigationItemRenderer extends NavigationItemRenderer +{ + const STATE_OK = 'ok'; + const STATE_CRITICAL = 'critical'; + const STATE_WARNING = 'warning'; + const STATE_PENDING = 'pending'; + const STATE_UNKNOWN = 'unknown'; + + /** + * The tooltip text for the badge + * + * @var string + */ + protected $title; + + /** + * The state identifier being used + * + * The state identifier defines the background color of the badge. + * + * @var string + */ + protected $state; + + /** + * Set the tooltip text for the badge + * + * @param string $title + * + * @return $this + */ + public function setTitle($title) + { + $this->title = $title; + return $this; + } + + /** + * Return the tooltip text for the badge + * + * @return string + */ + public function getTitle() + { + return $this->title; + } + + /** + * Set the state identifier to use + * + * @param string $state + * + * @return $this + */ + public function setState($state) + { + $this->state = $state; + return $this; + } + + /** + * Return the state identifier to use + * + * @return string + */ + public function getState() + { + return $this->state; + } + + /** + * Return the amount of items represented by the badge + * + * @return int + */ + abstract public function getCount(); + + /** + * Render the given navigation item as HTML anchor with a badge + * + * @param NavigationItem $item + * + * @return string + */ + public function render(NavigationItem $item = null) + { + if ($item === null) { + $item = $this->getItem(); + } + + $cssClass = ''; + if ($item->getCssClass() !== null) { + $cssClass = ' ' . $item->getCssClass(); + } + + $item->setCssClass('badge-nav-item' . $cssClass); + $this->setEscapeLabel(false); + $label = $this->view()->escape($item->getLabel()); + $item->setLabel($this->renderBadge() . $label); + $html = parent::render($item); + return $html; + } + + /** + * Render the badge + * + * @return string + */ + protected function renderBadge() + { + if ($count = $this->getCount()) { + if ($count > 1000000) { + $count = round($count, -6) / 1000000 . 'M'; + } elseif ($count > 1000) { + $count = round($count, -3) / 1000 . 'k'; + } + + $view = $this->view(); + return sprintf( + '<span title="%s" class="badge state-%s">%s</span>', + $view->escape($this->getTitle()), + $view->escape($this->getState()), + $count + ); + } + + return ''; + } +} diff --git a/library/Icinga/Web/Navigation/Renderer/HealthNavigationRenderer.php b/library/Icinga/Web/Navigation/Renderer/HealthNavigationRenderer.php new file mode 100644 index 0000000..577895b --- /dev/null +++ b/library/Icinga/Web/Navigation/Renderer/HealthNavigationRenderer.php @@ -0,0 +1,44 @@ +<?php +/* Icinga Web 2 | (c) 2021 Icinga GmbH | GPLv2+ */ + +namespace Icinga\Web\Navigation\Renderer; + +use Icinga\Application\Hook\HealthHook; + +class HealthNavigationRenderer extends BadgeNavigationItemRenderer +{ + public function getCount() + { + $count = 0; + $title = null; + $worstState = null; + foreach (HealthHook::collectHealthData()->select() as $result) { + if ($worstState === null || $result->state > $worstState) { + $worstState = $result->state; + $title = $result->message; + $count = 1; + } elseif ($worstState === $result->state) { + $count++; + } + } + + switch ($worstState) { + case HealthHook::STATE_OK: + $count = 0; + break; + case HealthHook::STATE_WARNING: + $this->state = self::STATE_WARNING; + break; + case HealthHook::STATE_CRITICAL: + $this->state = self::STATE_CRITICAL; + break; + case HealthHook::STATE_UNKNOWN: + $this->state = self::STATE_UNKNOWN; + break; + } + + $this->title = $title; + + return $count; + } +} diff --git a/library/Icinga/Web/Navigation/Renderer/NavigationItemRenderer.php b/library/Icinga/Web/Navigation/Renderer/NavigationItemRenderer.php new file mode 100644 index 0000000..51136ff --- /dev/null +++ b/library/Icinga/Web/Navigation/Renderer/NavigationItemRenderer.php @@ -0,0 +1,235 @@ +<?php +/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Web\Navigation\Renderer; + +use Icinga\Application\Icinga; +use Icinga\Exception\ProgrammingError; +use Icinga\Util\StringHelper; +use Icinga\Web\Navigation\NavigationItem; +use Icinga\Web\Url; +use Icinga\Web\View; + +/** + * NavigationItemRenderer + */ +class NavigationItemRenderer +{ + /** + * View + * + * @var View + */ + protected $view; + + /** + * The item being rendered + * + * @var NavigationItem + */ + protected $item; + + /** + * Internal link targets provided by Icinga Web 2 + * + * @var array + */ + protected $internalLinkTargets; + + /** + * Whether to escape the label + * + * @var bool + */ + protected $escapeLabel; + + /** + * Create a new NavigationItemRenderer + * + * @param array $options + */ + public function __construct(array $options = null) + { + if (! empty($options)) { + $this->setOptions($options); + } + + $this->internalLinkTargets = array('_main', '_self', '_next'); + $this->init(); + } + + /** + * Initialize this renderer + */ + public function init() + { + } + + /** + * Set the given options + * + * @param array $options + * + * @return $this + */ + public function setOptions(array $options) + { + foreach ($options as $name => $value) { + $setter = 'set' . StringHelper::cname($name); + if (method_exists($this, $setter)) { + $this->$setter($value); + } + } + + return $this; + } + + /** + * Set the view + * + * @param View $view + * + * @return $this + */ + public function setView(View $view) + { + $this->view = $view; + 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 navigation item to render + * + * @param NavigationItem $item + * + * @return $this + */ + public function setItem(NavigationItem $item) + { + $this->item = $item; + return $this; + } + + /** + * Return the navigation item being rendered + * + * @return NavigationItem + */ + public function getItem() + { + return $this->item; + } + + /** + * Set whether to escape the label + * + * @param bool $state + * + * @return $this + */ + public function setEscapeLabel($state = true) + { + $this->escapeLabel = (bool) $state; + return $this; + } + + /** + * Return whether to escape the label + * + * @return bool + */ + public function getEscapeLabel() + { + return $this->escapeLabel !== null ? $this->escapeLabel : true; + } + + /** + * Render the given navigation item as HTML anchor + * + * @param NavigationItem $item + * + * @return string + */ + public function render(NavigationItem $item = null) + { + if ($item !== null) { + $this->setItem($item); + } elseif (($item = $this->getItem()) === null) { + throw new ProgrammingError( + 'Cannot render nothing. Pass the item to render as part' + . ' of the call to render() or set it with setItem()' + ); + } + + $label = $this->getEscapeLabel() + ? $this->view()->escape($item->getLabel()) + : $item->getLabel(); + if (($icon = $item->getIcon()) !== null) { + $label = $this->view()->icon($icon) . $label; + } elseif ($item->getName()) { + $firstLetter = $item->getName()[0]; + $label = $this->view()->icon('letter', null, ['data-letter' => strtolower($firstLetter)]) . $label; + } + + if (($url = $item->getUrl()) !== null) { + $url->overwriteParams($item->getUrlParameters()); + + $target = $item->getTarget(); + if ($url->isExternal() && (!$target || in_array($target, $this->internalLinkTargets, true))) { + $url = Url::fromPath('iframe', array('url' => $url)); + } + + $content = sprintf( + '<a%s href="%s"%s>%s</a>', + $this->view()->propertiesToString($item->getAttributes()), + $this->view()->escape($url->getAbsoluteUrl('&')), + $this->renderTargetAttribute(), + $label + ); + } elseif ($label) { + $content = sprintf( + '<%1$s%2$s>%3$s</%1$s>', + $item::LINK_ALTERNATIVE, + $this->view()->propertiesToString($item->getAttributes()), + $label + ); + } else { + $content = ''; + } + + return $content; + } + + /** + * Render and return the attribute to provide a non-default target for the url + * + * @return string + */ + protected function renderTargetAttribute() + { + $target = $this->getItem()->getTarget(); + if ($target === null || $this->getItem()->getUrl()->getAbsoluteUrl() == '#') { + return ''; + } + + if (! in_array($target, $this->internalLinkTargets, true)) { + return ' target="' . $this->view()->escape($target) . '"'; + } + + return ' data-base-target="' . $target . '"'; + } +} diff --git a/library/Icinga/Web/Navigation/Renderer/NavigationRenderer.php b/library/Icinga/Web/Navigation/Renderer/NavigationRenderer.php new file mode 100644 index 0000000..00c0f9a --- /dev/null +++ b/library/Icinga/Web/Navigation/Renderer/NavigationRenderer.php @@ -0,0 +1,356 @@ +<?php +/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Web\Navigation\Renderer; + +use ArrayIterator; +use Exception; +use RecursiveIterator; +use Icinga\Application\Icinga; +use Icinga\Exception\IcingaException; +use Icinga\Web\Navigation\Navigation; +use Icinga\Web\Navigation\NavigationItem; +use Icinga\Web\View; + +/** + * Renderer for single level navigation + */ +class NavigationRenderer implements RecursiveIterator, NavigationRendererInterface +{ + /** + * The tag used for the outer element + * + * @var string + */ + protected $elementTag; + + /** + * The CSS class used for the outer element + * + * @var string + */ + protected $cssClass; + + /** + * The navigation's heading text + * + * @var string + */ + protected $heading; + + /** + * The content rendered so far + * + * @var array + */ + protected $content; + + /** + * Whether to skip rendering the outer element + * + * @var bool + */ + protected $skipOuterElement; + + /** + * The navigation's iterator + * + * @var ArrayIterator + */ + protected $iterator; + + /** + * The navigation + * + * @var Navigation + */ + protected $navigation; + + /** + * View + * + * @var View + */ + protected $view; + + /** + * Create a new NavigationRenderer + * + * @param Navigation $navigation + * @param bool $skipOuterElement + */ + public function __construct(Navigation $navigation, $skipOuterElement = false) + { + $this->skipOuterElement = $skipOuterElement; + $this->iterator = $navigation->getIterator(); + $this->navigation = $navigation; + $this->content = array(); + } + + /** + * {@inheritdoc} + */ + public function setElementTag($tag) + { + $this->elementTag = $tag; + return $this; + } + + /** + * {@inheritdoc} + */ + public function getElementTag() + { + return $this->elementTag ?: static::OUTER_ELEMENT_TAG; + } + + /** + * {@inheritdoc} + */ + public function setCssClass($class) + { + $this->cssClass = $class; + return $this; + } + + /** + * {@inheritdoc} + */ + public function getCssClass() + { + return $this->cssClass; + } + + /** + * {@inheritdoc} + */ + public function setHeading($heading) + { + $this->heading = $heading; + return $this; + } + + /** + * {@inheritdoc} + */ + public function getHeading() + { + return $this->heading; + } + + /** + * 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; + } + + public function getChildren(): NavigationRenderer + { + return new static($this->current()->getChildren(), $this->skipOuterElement); + } + + public function hasChildren(): bool + { + return $this->current()->hasChildren(); + } + + public function current(): NavigationItem + { + return $this->iterator->current(); + } + + public function key(): int + { + return $this->iterator->key(); + } + + public function next(): void + { + $this->iterator->next(); + } + + public function rewind(): void + { + $this->iterator->rewind(); + if (! $this->skipOuterElement) { + $this->content[] = $this->beginMarkup(); + } + } + + public function valid(): bool + { + $valid = $this->iterator->valid(); + if (! $this->skipOuterElement && !$valid) { + $this->content[] = $this->endMarkup(); + } + + return $valid; + } + + /** + * Return the opening markup for the navigation + * + * @return string + */ + public function beginMarkup() + { + $content = array(); + $content[] = sprintf( + '<%s%s role="navigation">', + $this->getElementTag(), + $this->getCssClass() !== null ? ' class="' . $this->getCssClass() . '"' : '' + ); + if (($heading = $this->getHeading()) !== null) { + $content[] = sprintf( + '<h%1$d id="navigation" class="sr-only" tabindex="-1">%2$s</h%1$d>', + static::HEADING_RANK, + $this->view()->escape($heading) + ); + } + $content[] = $this->beginChildrenMarkup(); + return join("\n", $content); + } + + /** + * Return the closing markup for the navigation + * + * @return string + */ + public function endMarkup() + { + $content = array(); + $content[] = $this->endChildrenMarkup(); + $content[] = '</' . $this->getElementTag() . '>'; + return join("\n", $content); + } + + /** + * Return the opening markup for multiple navigation items + * + * @param int $level + * + * @return string + */ + public function beginChildrenMarkup($level = 1) + { + $cssClass = array(static::CSS_CLASS_NAV); + if ($this->navigation->getLayout() === Navigation::LAYOUT_TABS) { + $cssClass[] = static::CSS_CLASS_NAV_TABS; + } elseif ($this->navigation->getLayout() === Navigation::LAYOUT_DROPDOWN) { + $cssClass[] = static::CSS_CLASS_NAV_DROPDOWN; + } + + $cssClass[] = 'nav-level-' . $level; + + return '<ul class="' . join(' ', $cssClass) . '">'; + } + + /** + * Return the closing markup for multiple navigation items + * + * @return string + */ + public function endChildrenMarkup() + { + return '</ul>'; + } + + /** + * Return the opening markup for the given navigation item + * + * @param NavigationItem $item + * + * @return string + */ + public function beginItemMarkup(NavigationItem $item) + { + $cssClasses = array(static::CSS_CLASS_ITEM); + + if ($item->hasChildren() && $item->getChildren()->getLayout() === Navigation::LAYOUT_DROPDOWN) { + $cssClasses[] = static::CSS_CLASS_DROPDOWN; + $item + ->setAttribute('class', static::CSS_CLASS_DROPDOWN_TOGGLE) + ->setIcon(static::DROPDOWN_TOGGLE_ICON) + ->setUrl('#'); + } + + if ($item->getActive()) { + $cssClasses[] = static::CSS_CLASS_ACTIVE; + } + + if ($item->getSelected()) { + $cssClasses[] = static::CSS_CLASS_SELECTED; + } + + if ($cssClass = $item->getCssClass()) { + $cssClasses[] = $cssClass; + } + + $content = sprintf( + '<li class="%s">', + join(' ', $cssClasses) + ); + return $content; + } + + /** + * Return the closing markup for a navigation item + * + * @return string + */ + public function endItemMarkup() + { + return '</li>'; + } + + /** + * {@inheritdoc} + */ + public function render() + { + foreach ($this as $item) { + /** @var NavigationItem $item */ + if ($item->shouldRender()) { + $content = $item->render(); + $this->content[] = $this->beginItemMarkup($item); + $this->content[] = $content; + $this->content[] = $this->endItemMarkup(); + } + } + + return join("\n", $this->content); + } + + /** + * {@inheritdoc} + */ + public function __toString() + { + try { + return $this->render(); + } catch (Exception $e) { + return IcingaException::describe($e); + } + } +} diff --git a/library/Icinga/Web/Navigation/Renderer/NavigationRendererInterface.php b/library/Icinga/Web/Navigation/Renderer/NavigationRendererInterface.php new file mode 100644 index 0000000..4495b73 --- /dev/null +++ b/library/Icinga/Web/Navigation/Renderer/NavigationRendererInterface.php @@ -0,0 +1,142 @@ +<?php +/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Web\Navigation\Renderer; + +/** + * Interface for navigation renderers + */ +interface NavigationRendererInterface +{ + /** + * CSS class for items + * + * @var string + */ + const CSS_CLASS_ITEM = 'nav-item'; + + /** + * CSS class for active items + * + * @var string + */ + const CSS_CLASS_ACTIVE = 'active'; + + /** + * CSS class for selected items + * + * @var string + */ + const CSS_CLASS_SELECTED = 'selected'; + + /** + * CSS class for dropdown items + * + * @var string + */ + const CSS_CLASS_DROPDOWN = 'dropdown-nav-item'; + + /** + * CSS class for a dropdown item's trigger + * + * @var string + */ + 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 with dropdown layout + * + * @var string + */ + const CSS_CLASS_NAV_DROPDOWN = 'dropdown-nav'; + + /** + * CSS class for the ul element with tabs layout + * + * @var string + */ + const CSS_CLASS_NAV_TABS = 'tab-nav'; + + /** + * Icon for a dropdown item's trigger + * + * @var string + */ + const DROPDOWN_TOGGLE_ICON = 'menu'; + + /** + * Default tag for the outer element the navigation will be wrapped with + * + * @var string + */ + const OUTER_ELEMENT_TAG = 'div'; + + /** + * The heading's rank + * + * @var int + */ + const HEADING_RANK = 1; + + /** + * Set the tag for the outer element the navigation is wrapped with + * + * @param string $tag + * + * @return $this + */ + public function setElementTag($tag); + + /** + * Return the tag for the outer element the navigation is wrapped with + * + * @return string + */ + public function getElementTag(); + + /** + * Set the CSS class to use for the outer element + * + * @param string $class + * + * @return $this + */ + public function setCssClass($class); + + /** + * Get the CSS class used for the outer element + * + * @return string + */ + public function getCssClass(); + + /** + * Set the navigation's heading text + * + * @param string $heading + * + * @return $this + */ + public function setHeading($heading); + + /** + * Return the navigation's heading text + * + * @return string + */ + public function getHeading(); + + /** + * Return the navigation rendered to HTML + * + * @return string + */ + public function render(); +} diff --git a/library/Icinga/Web/Navigation/Renderer/RecursiveNavigationRenderer.php b/library/Icinga/Web/Navigation/Renderer/RecursiveNavigationRenderer.php new file mode 100644 index 0000000..315c2aa --- /dev/null +++ b/library/Icinga/Web/Navigation/Renderer/RecursiveNavigationRenderer.php @@ -0,0 +1,186 @@ +<?php +/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Web\Navigation\Renderer; + +use Exception; +use RecursiveIteratorIterator; +use Icinga\Exception\IcingaException; +use Icinga\Web\Navigation\Navigation; +use Icinga\Web\Navigation\NavigationItem; +use Icinga\Web\Navigation\Renderer\NavigationItemRenderer; + +/** + * Renderer for multi level navigation + * + * @method NavigationRenderer getInnerIterator() { + * {@inheritdoc} + * } + */ +class RecursiveNavigationRenderer extends RecursiveIteratorIterator implements NavigationRendererInterface +{ + /** + * The content rendered so far + * + * @var array + */ + protected $content; + + /** + * Whether to use the standard item renderer + * + * @var bool + */ + protected $useStandardRenderer; + + /** + * Create a new RecursiveNavigationRenderer + * + * @param Navigation $navigation + */ + public function __construct(Navigation $navigation) + { + $this->content = array(); + parent::__construct( + new NavigationRenderer($navigation, true), + RecursiveIteratorIterator::SELF_FIRST + ); + } + + /** + * Set whether to use the standard navigation item renderer + * + * @param bool $state + * + * @return $this + */ + public function setUseStandardItemRenderer($state = true) + { + $this->useStandardRenderer = (bool) $state; + return $this; + } + + /** + * Return whether to use the standard navigation item renderer + * + * @return bool + */ + public function getUseStandardItemRenderer() + { + return $this->useStandardRenderer; + } + + /** + * {@inheritdoc} + */ + public function setElementTag($tag) + { + $this->getInnerIterator()->setElementTag($tag); + return $this; + } + + /** + * {@inheritdoc} + */ + public function getElementTag() + { + return $this->getInnerIterator()->getElementTag(); + } + + /** + * {@inheritdoc} + */ + public function setCssClass($class) + { + $this->getInnerIterator()->setCssClass($class); + return $this; + } + + /** + * {@inheritdoc} + */ + public function getCssClass() + { + return $this->getInnerIterator()->getCssClass(); + } + + /** + * {@inheritdoc} + */ + public function setHeading($heading) + { + $this->getInnerIterator()->setHeading($heading); + return $this; + } + + /** + * {@inheritdoc} + */ + public function getHeading() + { + return $this->getInnerIterator()->getHeading(); + } + + public function beginIteration(): void + { + $this->content[] = $this->getInnerIterator()->beginMarkup(); + } + + public function endIteration(): void + { + $this->content[] = $this->getInnerIterator()->endMarkup(); + } + + public function beginChildren(): void + { + $this->content[] = $this->getInnerIterator()->beginChildrenMarkup($this->getDepth() + 1); + } + + public function endChildren(): void + { + $this->content[] = $this->getInnerIterator()->endChildrenMarkup(); + $this->content[] = $this->getInnerIterator()->endItemMarkup(); + } + + /** + * {@inheritdoc} + */ + public function render() + { + foreach ($this as $item) { + /** @var NavigationItem $item */ + if ($item->shouldRender()) { + if ($this->getDepth() > 0) { + $item->setIcon(null); + } + if ($this->getUseStandardItemRenderer()) { + $renderer = new NavigationItemRenderer(); + $content = $renderer->render($item); + } else { + $content = $item->render(); + } + $this->content[] = $this->getInnerIterator()->beginItemMarkup($item); + + $this->content[] = $content; + + if (! $item->hasChildren()) { + $this->content[] = $this->getInnerIterator()->endItemMarkup(); + } + } + } + + return join("\n", $this->content); + } + + /** + * {@inheritdoc} + */ + public function __toString() + { + try { + return $this->render(); + } catch (Exception $e) { + return IcingaException::describe($e); + } + } +} diff --git a/library/Icinga/Web/Navigation/Renderer/SummaryNavigationItemRenderer.php b/library/Icinga/Web/Navigation/Renderer/SummaryNavigationItemRenderer.php new file mode 100644 index 0000000..2916f4e --- /dev/null +++ b/library/Icinga/Web/Navigation/Renderer/SummaryNavigationItemRenderer.php @@ -0,0 +1,72 @@ +<?php +/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Web\Navigation\Renderer; + +/** + * Badge renderer summing up the worst state of its children + */ +class SummaryNavigationItemRenderer extends BadgeNavigationItemRenderer +{ + /** + * Cached count + * + * @var int + */ + protected $count; + + /** + * State to severity map + * + * @var array + */ + protected static $stateSeverityMap = array( + self::STATE_OK => 0, + self::STATE_PENDING => 1, + self::STATE_UNKNOWN => 2, + self::STATE_WARNING => 3, + self::STATE_CRITICAL => 4, + ); + + /** + * Severity to state map + * + * @var array + */ + protected static $severityStateMap = array( + self::STATE_OK, + self::STATE_PENDING, + self::STATE_UNKNOWN, + self::STATE_WARNING, + self::STATE_CRITICAL + ); + + /** + * {@inheritdoc} + */ + public function getCount() + { + if ($this->count === null) { + $countMap = array_fill(0, 5, 0); + $maxSeverity = 0; + $titles = array(); + foreach ($this->getItem()->getChildren() as $child) { + $renderer = $child->getRenderer(); + if ($renderer instanceof BadgeNavigationItemRenderer) { + $count = $renderer->getCount(); + if ($count) { + $severity = static::$stateSeverityMap[$renderer->getState()]; + $countMap[$severity] += $count; + $titles[] = $renderer->getTitle(); + $maxSeverity = max($maxSeverity, $severity); + } + } + } + $this->count = $countMap[$maxSeverity]; + $this->state = static::$severityStateMap[$maxSeverity]; + $this->title = implode('. ', $titles); + } + + return $this->count; + } +} |