Merge branch 'master' into feature/activity-indicators-for-form-submits-8369

This commit is contained in:
Johannes Meyer 2015-08-21 13:37:54 +02:00
commit 9ca278d7b2
20 changed files with 489 additions and 394 deletions

View File

@ -81,22 +81,6 @@ class LdapResourceForm extends Form
)
);
if (isset($formData['encryption']) && $formData['encryption'] !== 'none') {
// TODO(jom): Do not show this checkbox unless the connection is actually failing due to certificate errors
$this->addElement(
'checkbox',
'reqcert',
array(
'required' => true,
'label' => $this->translate('Require Certificate'),
'description' => $this->translate(
'When checked, the LDAP server must provide a valid and known (trusted) certificate.'
),
'value' => 1
)
);
}
$this->addElement(
'text',
'root_dn',

View File

@ -122,13 +122,6 @@ class LdapConnection implements Selectable, Inspectable
*/
protected $rootDn;
/**
* Whether to load the configuration for strict certificate validation or the one for non-strict validation
*
* @var bool
*/
protected $validateCertificate;
/**
* Whether the bind on this connection has already been performed
*
@ -176,7 +169,6 @@ class LdapConnection implements Selectable, Inspectable
$this->bindPw = $config->bind_pw;
$this->rootDn = $config->root_dn;
$this->port = $config->get('port', 389);
$this->validateCertificate = (bool) $config->get('reqcert', true);
$this->encryption = $config->encryption;
if ($this->encryption !== null) {
@ -957,16 +949,9 @@ class LdapConnection implements Selectable, Inspectable
$info = new Inspection('');
}
if ($this->encryption === static::STARTTLS || $this->encryption === static::LDAPS) {
$this->prepareTlsEnvironment();
}
$hostname = $this->hostname;
if ($this->encryption === static::LDAPS) {
$info->write('Connect using LDAPS');
if (! $this->validateCertificate) {
$info->write('Skip certificate validation');
}
$hostname = 'ldaps://' . $hostname;
}
@ -983,9 +968,6 @@ class LdapConnection implements Selectable, Inspectable
if ($this->encryption === static::STARTTLS) {
$this->encrypted = true;
$info->write('Connect using STARTTLS');
if (! $this->validateCertificate) {
$info->write('Skip certificate validation');
}
if (! ldap_start_tls($ds)) {
throw new LdapException('LDAP STARTTLS failed: %s', ldap_error($ds));
}
@ -998,30 +980,6 @@ class LdapConnection implements Selectable, Inspectable
return $ds;
}
/**
* Set up how to handle StartTLS connections
*
* @throws LdapException In case the LDAPRC environment variable cannot be set
*/
protected function prepareTlsEnvironment()
{
// TODO: allow variable known CA location (system VS Icinga)
if (Platform::isWindows()) {
putenv('LDAPTLS_REQCERT=never');
} else {
if ($this->validateCertificate) {
$ldap_conf = $this->getConfigDir('ldap_ca.conf');
} else {
$ldap_conf = $this->getConfigDir('ldap_nocert.conf');
}
putenv('LDAPRC=' . $ldap_conf); // TODO: Does not have any effect
if (getenv('LDAPRC') !== $ldap_conf) {
throw new LdapException('putenv failed');
}
}
}
/**
* Create an LDAP entry
*
@ -1103,6 +1061,13 @@ class LdapConnection implements Selectable, Inspectable
try {
$ds = $this->prepareNewConnection($insp);
} catch (Exception $e) {
if ($this->encryption === 'starttls') {
// The Exception does not return any proper error messages in case of certificate errors. Connecting
// by STARTTLS will usually fail at this point when the certificate is unknown,
// so at least try to give some hints.
$insp->write('NOTE: There might be an issue with the chosen encryption. Ensure that the LDAP-Server ' .
'supports STARTTLS and that the LDAP-Client is configured to accept its certificate.');
}
return $insp->error($e->getMessage());
}
@ -1116,6 +1081,13 @@ class LdapConnection implements Selectable, Inspectable
'***' /* $this->bindPw */
);
if (! $success) {
// ldap_error does not return any proper error messages in case of certificate errors. Connecting
// by LDAPS will usually fail at this point when the certificate is unknown, so at least try to give
// some hints.
if ($this->encryption === 'ldaps') {
$insp->write('NOTE: There might be an issue with the chosen encryption. Ensure that the LDAP-Server ' .
' supports LDAPS and that the LDAP-Client is configured to accept its certificate.');
}
return $insp->error(sprintf('%s failed: %s', $msg, ldap_error($ds)));
}
$insp->write(sprintf($msg . ' successful'));
@ -1137,12 +1109,4 @@ class LdapConnection implements Selectable, Inspectable
}
return $insp;
}
/**
* Reset the environment variables set by self::prepareTlsEnvironment()
*/
public function __destruct()
{
putenv('LDAPRC');
}
}

View File

@ -117,9 +117,19 @@ class Menu implements RecursiveIterator
foreach ($props as $key => $value) {
$method = 'set' . implode('', array_map('ucfirst', explode('_', strtolower($key))));
if ($key === 'renderer') {
// nested configuration is used to pass multiple arguments to the item renderer
if ($value instanceof ConfigObject) {
$args = $value;
$value = $value->get('0');
}
$value = '\\' . ltrim($value, '\\');
if (class_exists($value)) {
$value = new $value;
if (isset($args)) {
$value = new $value($args);
} else {
$value = new $value;
}
} else {
$class = '\Icinga\Web\Menu' . $value;
if (!class_exists($class)) {
@ -127,7 +137,11 @@ class Menu implements RecursiveIterator
sprintf('ItemRenderer with class "%s" does not exist', $class)
);
}
$value = new $class;
if (isset($args)) {
$value = new $class($args);
} else {
$value = new $class;
}
}
}
if (method_exists($this, $method)) {
@ -226,7 +240,6 @@ class Menu implements RecursiveIterator
$auth = Auth::getInstance();
if ($auth->isAuthenticated()) {
$this->add(t('Dashboard'), array(
'url' => 'dashboard',
'icon' => 'dashboard',
@ -236,7 +249,10 @@ class Menu implements RecursiveIterator
$section = $this->add(t('System'), array(
'icon' => 'services',
'priority' => 700,
'renderer' => 'ProblemMenuItemRenderer'
'renderer' => array(
'SummaryMenuItemRenderer',
'state' => 'critical'
)
));
$section->add(t('About'), array(
'url' => 'about',
@ -297,7 +313,10 @@ class Menu implements RecursiveIterator
$section->add(t('Logout'), array(
'url' => 'authentication/logout',
'priority' => 990,
'renderer' => 'ForeignMenuItemRenderer'
'renderer' => array(
'MenuItemRenderer',
'target' => '_self'
)
));
}
}

View File

@ -0,0 +1,65 @@
<?php
namespace Icinga\Web\Menu;
use Icinga\Web\Menu;
abstract class BadgeMenuItemRenderer extends MenuItemRenderer
{
const STATE_OK = 'ok';
const STATE_CRITICAL = 'critical';
const STATE_WARNING = 'warning';
const STATE_PENDING = 'pending';
const STATE_UNKNOWN = 'unknown';
/**
* Defines the color of the badge
*
* @return string
*/
abstract public function getState();
/**
* The amount of items to display in the badge
*
* @return int
*/
abstract public function getCount();
/**
* The tooltip title
*
* @return string
*/
abstract public function getTitle();
/**
* Renders the html content of a single menu item
*
* @param Menu $menu
*
* @return string
*/
public function render(Menu $menu)
{
return $this->renderBadge() . $this->createLink($menu);
}
/**
* Render the badge
*
* @return string
*/
protected function renderBadge()
{
if ($count = $this->getCount()) {
return sprintf(
'<div title="%s" class="badge-container"><span class="badge badge-%s">%s</span></div>',
$this->getView()->escape($this->getTitle()),
$this->getView()->escape($this->getState()),
$count
);
}
return '';
}
}

View File

@ -1,17 +0,0 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Web\Menu;
use Icinga\Web\Menu;
use Icinga\Web\Url;
/**
* A menu item with a link that surpasses the regular navigation link behavior
*/
class ForeignMenuItemRenderer extends MenuItemRenderer
{
protected $attributes = array(
'target' => '_self'
);
}

View File

@ -7,6 +7,7 @@ use Icinga\Application\Icinga;
use Icinga\Web\Menu;
use Icinga\Web\Url;
use Icinga\Web\View;
use Icinga\Data\ConfigObject;
/**
* Default MenuItemRenderer class
@ -14,38 +15,39 @@ use Icinga\Web\View;
class MenuItemRenderer
{
/**
* Contains <a> element specific attributes
*
* @var array
*/
protected $attributes = array();
/**
* View
* The view this menu item is being rendered to
*
* @var View|null
*/
protected $view;
protected $view = null;
/**
* Set the view
* The link target
*
* @param View $view
*
* @return $this
* @var string
*/
public function setView(View $view)
protected $target = null;
/**
* Create a new instance of MenuItemRenderer
*
* Is is possible to configure the link target using the option 'target'
*
* @param ConfigObject|null $configuration
*/
public function __construct(ConfigObject $configuration = null)
{
$this->view = $view;
return $this;
if ($configuration !== null) {
$this->target = $configuration->get('target', null);
}
}
/**
* Get the view
* Get the view this menu item is being rendered to
*
* @return View
*/
public function getView()
protected function getView()
{
if ($this->view === null) {
$this->view = Icinga::app()->getViewRenderer()->view;
@ -53,6 +55,36 @@ class MenuItemRenderer
return $this->view;
}
/**
* Creates a menu item link element
*
* @param Menu $menu
*
* @return string
*/
public function createLink(Menu $menu)
{
$attributes = isset($this->target) ? sprintf(' target="%s"', $this->getView()->escape($this->target)) : '';
if ($menu->getIcon() && strpos($menu->getIcon(), '.') === false) {
return sprintf(
'<a href="%s"%s><i aria-hidden="true" class="icon-%s"></i>%s</a>',
$menu->getUrl() ? : '#',
$attributes,
$menu->getIcon(),
$this->getView()->escape($menu->getTitle())
);
}
return sprintf(
'<a href="%s"%s>%s%s<span></span></a>',
$menu->getUrl() ? : '#',
$attributes,
$menu->getIcon() ? '<img aria-hidden="true" src="' . Url::fromPath($menu->getIcon()) . '" class="icon" /> ' : '',
$this->getView()->escape($menu->getTitle())
);
}
/**
* Renders the html content of a single menu item
*
@ -64,47 +96,4 @@ class MenuItemRenderer
{
return $this->createLink($menu);
}
/**
* Creates a menu item link element
*
* @param Menu $menu
*
* @return string
*/
public function createLink(Menu $menu)
{
if ($menu->getIcon() && strpos($menu->getIcon(), '.') === false) {
return sprintf(
'<a href="%s"%s><i aria-hidden="true" class="icon-%s"></i>%s</a>',
$menu->getUrl() ? : '#',
$this->getAttributes(),
$menu->getIcon(),
$this->getView()->escape($menu->getTitle())
);
}
return sprintf(
'<a href="%s"%s>%s%s<span></span></a>',
$menu->getUrl() ? : '#',
$this->getAttributes(),
$menu->getIcon() ? '<img aria-hidden="true" src="' . Url::fromPath($menu->getIcon()) . '" class="icon" /> ' : '',
$this->getView()->escape($menu->getTitle())
);
}
/**
* Returns <a> element specific attributes if present
*
* @return string
*/
protected function getAttributes()
{
$attributes = '';
$view = $this->getView();
foreach ($this->attributes as $attribute => $value) {
$attributes .= ' ' . $view->escape($attribute) . '="' . $view->escape($value) . '"';
}
return $attributes;
}
}

View File

@ -1,64 +0,0 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Web\Menu;
use Icinga\Web\Menu;
class ProblemMenuItemRenderer extends MenuItemRenderer
{
/**
* Set of summarized problems from submenus
*
* @var array
*/
protected $summary = array();
/**
* Renders the html content of a single menu item and summarizes submenu problems
*
* @param Menu $menu
*
* @return string
*/
public function render(Menu $menu)
{
if ($menu->getParent() !== null && $menu->hasSubMenus()) {
/** @var $submenu Menu */
foreach ($menu->getSubMenus() as $submenu) {
$renderer = $submenu->getRenderer();
if (method_exists($renderer, 'getSummary')) {
if ($renderer->getSummary() !== null) {
$this->summary[] = $renderer->getSummary();
}
}
}
}
return $this->getBadge() . $this->createLink($menu);
}
/**
* Get the problem badge
*
* @return string
*/
protected function getBadge()
{
if (count($this->summary) > 0) {
$problems = 0;
$titles = array();
foreach ($this->summary as $summary) {
$problems += $summary['problems'];
$titles[] = $summary['title'];
}
return sprintf(
'<div title="%s" class="badge-container"><span class="badge badge-critical">%s</span></div>',
implode(', ', $titles),
$problems
);
}
return '';
}
}

View File

@ -0,0 +1,94 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Web\Menu;
use Icinga\Web\Menu;
use Icinga\Data\ConfigObject;
/**
* Summary badge adding up all badges in the sub-menus that have the same state
*/
class SummaryMenuItemRenderer extends BadgeMenuItemRenderer
{
/**
* Set of summarized problems from submenus
*
* @var array
*/
protected $titles = array();
/**
* The amount of problems
*
* @var int
*/
protected $count = 0;
/**
* The state that should be summarized
*
* @var string
*/
protected $state;
/**
* The amount of problems
*/
public function __construct(ConfigObject $configuration)
{
$this->state = $configuration->get('state', self::STATE_CRITICAL);
}
/**
* Renders the html content of a single menu item and summarized sub-menus
*
* @param Menu $menu
*
* @return string
*/
public function render(Menu $menu)
{
/** @var $submenu Menu */
foreach ($menu->getSubMenus() as $submenu) {
$renderer = $submenu->getRenderer();
if ($renderer instanceof BadgeMenuItemRenderer) {
if ($renderer->getState() === $this->state) {
$this->titles[] = $renderer->getTitle();
$this->count += $renderer->getCount();
}
}
}
return $this->renderBadge() . $this->createLink($menu);
}
/**
* The amount of items to display in the badge
*
* @return int
*/
public function getCount()
{
return $this->count;
}
/**
* Defines the color of the badge
*
* @return string
*/
public function getState()
{
return $this->state;
}
/**
* The tooltip title
*
* @return string
*/
public function getTitle()
{
return implode(', ', $this->titles);
}
}

View File

@ -119,6 +119,11 @@ class Request extends Zend_Controller_Request_Http
return $id . '-' . $this->uniqueId;
}
/**
* Detect whether cookies are enabled
*
* @return bool
*/
public function hasCookieSupport()
{
$cookie = new Cookie($this);

View File

@ -67,7 +67,7 @@
) : $this->translate('This comment does not expire.'); ?>
</td>
<?php if (isset($delCommentForm)): // Form is unset if the current user lacks the respective permission ?>
<td style="width: 2em" data-base-target="self">
<td style="width: 2em" data-base-target="_self">
<?php
$delCommentForm = clone $delCommentForm;
$delCommentForm->populate(

View File

@ -126,7 +126,7 @@ if (! $this->compact): ?>
</small>
</td>
<?php if (isset($delDowntimeForm)): // Form is unset if the current user lacks the respective permission ?>
<td style="width: 2em" data-base-target="self">
<td style="width: 2em" data-base-target="_self">
<?php
$delDowntimeForm = clone $delDowntimeForm;
$delDowntimeForm->populate(

View File

@ -89,17 +89,34 @@ $this->provideSearchUrl($this->translate('Servicegroups'), 'monitoring/list/serv
* Problems Section
*/
$section = $this->menuSection($this->translate('Problems'), array(
'renderer' => 'Icinga\Module\Monitoring\Web\Menu\ProblemMenuItemRenderer',
'renderer' => array(
'SummaryMenuItemRenderer',
'state' => 'critical'
),
'icon' => 'block',
'priority' => 20
));
$section->add($this->translate('Unhandled Hosts'), array(
'renderer' => 'Icinga\Module\Monitoring\Web\Menu\UnhandledHostMenuItemRenderer',
'renderer' => array(
'Icinga\Module\Monitoring\Web\Menu\MonitoringBadgeMenuItemRenderer',
'columns' => array(
'hosts_down_unhandled' => $this->translate('%d unhandled hosts down')
),
'state' => 'critical',
'dataView' => 'statussummary'
),
'url' => 'monitoring/list/hosts?host_problem=1&host_handled=0',
'priority' => 30
));
$section->add($this->translate('Unhandled Services'), array(
'renderer' => 'Icinga\Module\Monitoring\Web\Menu\UnhandledServiceMenuItemRenderer',
'renderer' => array(
'Icinga\Module\Monitoring\Web\Menu\MonitoringBadgeMenuItemRenderer',
'columns' => array(
'services_critical_unhandled' => $this->translate('%d unhandled services critical')
),
'state' => 'critical',
'dataView' => 'statussummary'
),
'url' => 'monitoring/list/services?service_problem=1&service_handled=0&sort=service_severity',
'priority' => 40
));
@ -204,7 +221,7 @@ $section = $this->menuSection($this->translate('System'));
$section->add($this->translate('Monitoring Health'), array(
'url' => 'monitoring/process/info',
'priority' => 720,
'renderer' => 'Icinga\Module\Monitoring\Web\Menu\BackendAvailabilityMenuItemRenderer'
'renderer' => 'Icinga\Module\Monitoring\Web\Menu\BackendAvailabilityMenuItemRenderer'
));
/*

View File

@ -479,8 +479,12 @@ abstract class IdoQuery extends DbQuery
}
}
/**
* {@inheritdoc}
*/
public function addFilter(Filter $filter)
{
$filter = clone $filter;
$this->requireFilterColumns($filter);
return parent::addFilter($filter);
}

View File

@ -4,10 +4,10 @@
namespace Icinga\Module\Monitoring\Web\Menu;
use Icinga\Web\Menu;
use Icinga\Web\Menu\MenuItemRenderer;
use Icinga\Web\Menu\BadgeMenuItemRenderer;
use Icinga\Module\Monitoring\Backend\MonitoringBackend;
class BackendAvailabilityMenuItemRenderer extends MenuItemRenderer
class BackendAvailabilityMenuItemRenderer extends BadgeMenuItemRenderer
{
/**
* Get whether or not the monitoring backend is currently running
@ -27,47 +27,39 @@ class BackendAvailabilityMenuItemRenderer extends MenuItemRenderer
}
/**
* {@inheritdoc}
*/
public function render(Menu $menu)
{
return $this->getBadge() . $this->createLink($menu);
}
/**
* Get the problem badge HTML
* The css class of the badge
*
* @return string
*/
protected function getBadge()
public function getState()
{
if (! $this->isCurrentlyRunning()) {
return sprintf(
'<div title="%s" class="badge-container"><span class="badge badge-critical">%d</span></div>',
sprintf(
mt('monitoring', 'Monitoring backend %s is not running'), MonitoringBackend::instance()->getName()
),
1
);
}
return '';
return self::STATE_CRITICAL;
}
/**
* Get the problem data for the summary
* The amount of items to display in the badge
*
* @return array|null
* @return int
*/
public function getSummary()
public function getCount()
{
if (! $this->isCurrentlyRunning()) {
return array(
'problems' => 1,
'title' => sprintf(
mt('monitoring', 'Monitoring backend %s is not running'), MonitoringBackend::instance()->getName()
)
);
return 1;
}
return null;
return 0;
}
/**
* The tooltip title
*
* @return string
* @throws \Icinga\Exception\ConfigurationError
*/
public function getTitle()
{
return sprintf(
mt('monitoring', 'Monitoring backend %s is not running'),
MonitoringBackend::instance()->getName()
);
}
}

View File

@ -0,0 +1,183 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Monitoring\Web\Menu;
use Icinga\Authentication\Auth;
use Icinga\Data\ConfigObject;
use Icinga\Data\Filter\Filter;
use Icinga\Data\Filterable;
use Icinga\Web\Menu;
use Icinga\Module\Monitoring\Backend\MonitoringBackend;
use Icinga\Web\Menu\BadgeMenuItemRenderer;
/**
* Render generic dataView columns as badges in MenuItems
*
* Renders numeric data view column values into menu item badges, fully configurable
* and with a caching mechanism to prevent needless requests to the same data view
*/
class MonitoringBadgeMenuItemRenderer extends BadgeMenuItemRenderer
{
/**
* Caches the responses for all executed summaries
*
* @var array
*/
protected static $summaries = array();
/**
* Accumulates all needed columns for a view to allow fetching the needed columns in
* one single query
*
* @var array
*/
protected static $dataViews = array();
/**
* The data view displayed by this menu item
*
* @var string
*/
protected $dataView;
/**
* The columns and titles displayed in the badge
*
* @var array
*/
protected $columns;
/**
* The titles that will be used to render this menu item tooltip
*
* @var String[]
*/
protected $titles;
/**
* The class of the badge element
*
* @var string
*/
protected $state;
/**
* Create a new instance of ColumnMenuItemRenderer
*
* It is possible to configure the class of the rendered badge as option 'class', the column
* to fetch using the option 'column' and the dataView from which the columns will be
* fetched using the option 'dataView'.
*
* @param $configuration ConfigObject The configuration to use
*/
public function __construct(ConfigObject $configuration)
{
parent::__construct($configuration);
$this->columns = $configuration->get('columns');
$this->state = $configuration->get('state');
$this->dataView = $configuration->get('dataView');
// clear the outdated summary cache, since new columns are being added. Optimally all menu item are constructed
// before any rendering is going on to avoid trashing too man old requests
if (isset(self::$summaries[$this->dataView])) {
unset(self::$summaries[$this->dataView]);
}
// add the new columns to this view
if (! isset(self::$dataViews[$this->dataView])) {
self::$dataViews[$this->dataView] = array();
}
foreach ($this->columns as $column => $title) {
if (! array_search($column, self::$dataViews[$this->dataView])) {
self::$dataViews[$this->dataView][] = $column;
}
$this->titles[$column] = $title;
}
}
/**
* Apply a restriction on the given data view
*
* @param string $restriction The name of restriction
* @param Filterable $filterable The filterable to restrict
*
* @return Filterable The filterable
*/
protected static function applyRestriction($restriction, Filterable $filterable)
{
$restrictions = Filter::matchAny();
foreach (Auth::getInstance()->getRestrictions($restriction) as $filter) {
$restrictions->addFilter(Filter::fromQueryString($filter));
}
$filterable->applyFilter($restrictions);
return $filterable;
}
/**
* Fetch the response from the database or access cache
*
* @param $view
*
* @return null
* @throws \Icinga\Exception\ConfigurationError
*/
protected static function summary($view)
{
if (! isset(self::$summaries[$view])) {
$summary = MonitoringBackend::instance()->select()->from(
$view,
self::$dataViews[$view]
);
static::applyRestriction('monitoring/filter/objects', $summary);
self::$summaries[$view] = $summary->fetchRow();
}
return isset(self::$summaries[$view]) ? self::$summaries[$view] : null;
}
/**
* Defines the color of the badge
*
* @return string
*/
public function getState()
{
return $this->state;
}
/**
* The amount of items to display in the badge
*
* @return int
*/
public function getCount()
{
$sum = self::summary($this->dataView);
$count = 0;
foreach ($this->columns as $col => $title) {
if (isset($sum->$col)) {
$count += $sum->$col;
}
}
return $count;
}
/**
* The tooltip title
*
* @return string
*/
public function getTitle()
{
$titles = array();
$sum = $this->summary($this->dataView);
foreach ($this->columns as $column => $value) {
if (isset($sum->$column) && $sum->$column > 0) {
$titles[] = sprintf($this->titles[$column], $sum->$column);
}
}
return implode(', ', $titles);
}
}

View File

@ -1,109 +0,0 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Monitoring\Web\Menu;
use Icinga\Authentication\Auth;
use Icinga\Data\Filter\Filter;
use Icinga\Data\Filterable;
use Icinga\Web\Menu;
use Icinga\Module\Monitoring\Backend\MonitoringBackend;
use Icinga\Web\Menu\MenuItemRenderer;
class MonitoringMenuItemRenderer extends MenuItemRenderer
{
protected static $summary;
protected $columns = array();
/**
* Apply a restriction on the given data view
*
* @param string $restriction The name of restriction
* @param Filterable $filterable The filterable to restrict
*
* @return Filterable The filterable
*/
protected static function applyRestriction($restriction, Filterable $filterable)
{
$restrictions = Filter::matchAny();
foreach (Auth::getInstance()->getRestrictions($restriction) as $filter) {
$restrictions->addFilter(Filter::fromQueryString($filter));
}
$filterable->applyFilter($restrictions);
return $filterable;
}
protected static function summary($column = null)
{
if (self::$summary === null) {
$summary = MonitoringBackend::instance()->select()->from(
'statussummary',
array(
'hosts_down_unhandled',
'services_critical_unhandled'
)
);
static::applyRestriction('monitoring/filter/objects', $summary);
self::$summary = $summary->fetchRow();
}
if ($column === null) {
return self::$summary;
} elseif (isset(self::$summary->$column)) {
return self::$summary->$column;
} else {
return null;
}
}
protected function getBadgeTitle()
{
$translations = array(
'hosts_down_unhandled' => mt('monitoring', '%d unhandled hosts down'),
'services_critical_unhandled' => mt('monitoring', '%d unhandled services critical')
);
$titles = array();
$sum = $this->summary();
foreach ($this->columns as $col) {
if (isset($sum->$col) && $sum->$col > 0) {
$titles[] = sprintf($translations[$col], $sum->$col);
}
}
return implode(', ', $titles);
}
protected function countItems()
{
$sum = self::summary();
$count = 0;
foreach ($this->columns as $col) {
if (isset($sum->$col)) {
$count += $sum->$col;
}
}
return $count;
}
public function render(Menu $menu)
{
return $this->getBadge() . $this->createLink($menu);
}
protected function getBadge()
{
if ($count = $this->countItems()) {
return sprintf(
'<div title="%s" class="badge-container"><span class="badge badge-critical">%s</span></div>',
$this->getBadgeTitle(),
$count
);
}
return '';
}
}

View File

@ -1,12 +0,0 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Monitoring\Web\Menu;
class ProblemMenuItemRenderer extends MonitoringMenuItemRenderer
{
protected $columns = array(
'hosts_down_unhandled',
'services_critical_unhandled'
);
}

View File

@ -1,11 +0,0 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Monitoring\Web\Menu;
class UnhandledHostMenuItemRenderer extends MonitoringMenuItemRenderer
{
protected $columns = array(
'hosts_down_unhandled',
);
}

View File

@ -1,11 +0,0 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Monitoring\Web\Menu;
class UnhandledServiceMenuItemRenderer extends MonitoringMenuItemRenderer
{
protected $columns = array(
'services_critical_unhandled'
);
}

View File

@ -562,6 +562,9 @@
self.icinga.ui.layout1col();
} else {
$target = $('#' + targetId);
if (! $target.length) {
self.icinga.logger.warn('Link target "#' + targetId + '" does not exist in DOM.');
}
}
}