Merge branch 'master' into bugfix/significant-whitespaces-8777

Conflicts:
	library/Icinga/Web/Widget/FilterEditor.php
This commit is contained in:
Eric Lippmann 2015-05-18 13:35:28 +02:00
commit 82ee1d6e60
189 changed files with 4014 additions and 1470 deletions

View File

@ -1 +1 @@
v2.0.0-beta2
v2.0.0-beta3

View File

@ -11,14 +11,14 @@ use Icinga\Forms\Config\GeneralConfigForm;
use Icinga\Forms\Config\ResourceConfigForm;
use Icinga\Forms\ConfirmRemovalForm;
use Icinga\Security\SecurityException;
use Icinga\Web\Controller\ActionController;
use Icinga\Web\Controller;
use Icinga\Web\Notification;
use Icinga\Web\Widget;
/**
* Application and module configuration
*/
class ConfigController extends ActionController
class ConfigController extends Controller
{
/**
* The first allowed config action according to the user's permissions
@ -128,8 +128,15 @@ class ConfigController extends ActionController
$this->view->modules = Icinga::app()->getModuleManager()->select()
->from('modules')
->order('enabled', 'desc')
->order('name')
->paginate();
->order('name');
$this->setupLimitControl();
$this->setupPaginationControl($this->view->modules);
// TODO: Not working
/*$this->setupSortControl(array(
'name' => $this->translate('Modulename'),
'path' => $this->translate('Installation Path'),
'enabled' => $this->translate('State')
));*/
}
public function moduleAction()

View File

@ -34,7 +34,11 @@ class ErrorController extends ActionController
$path = preg_split('~/~', $path);
$path = array_shift($path);
$this->getResponse()->setHttpResponseCode(404);
$this->view->message = $this->translate('Page not found.');
$title = preg_replace('/\r?\n.*$/s', '', $exception->getMessage());
$this->view->title = 'Server error: ' . $title;
if ($this->getInvokeArg('displayExceptions')) {
$this->view->stackTrace = $exception->getTraceAsString();
}
if ($modules->hasInstalled($path) && ! $modules->hasEnabled($path)) {
$this->view->message .= ' ' . sprintf(
$this->translate('Enabling the "%s" module might help!'),

View File

@ -3,6 +3,8 @@
use Icinga\Module\Monitoring\Controller;
use Icinga\Web\Url;
use Icinga\Web\Widget\Tabextension\DashboardAction;
use Icinga\Web\Widget\Tabextension\OutputFormat;
use Icinga\Application\Config;
use Icinga\Application\Logger;
use Icinga\Data\ConfigObject;
@ -29,7 +31,7 @@ class ListController extends Controller
'list/'
. str_replace(' ', '', $action)
)
))->activate($action);
))->extend(new OutputFormat())->extend(new DashboardAction())->activate($action);
}
/**
@ -42,15 +44,16 @@ class ListController extends Controller
}
$this->addTitleTab('application log');
$pattern = '/^(?<datetime>[0-9]{4}(-[0-9]{2}){2}' // date
. 'T[0-9]{2}(:[0-9]{2}){2}([\\+\\-][0-9]{2}:[0-9]{2})?)' // time
. ' - (?<loglevel>[A-Za-z]+)' // loglevel
. ' - (?<message>.*)$/';
$resource = new FileReader(new ConfigObject(array(
'filename' => Config::app()->get('logging', 'file'),
'fields' => $pattern
'fields' => '/(?<!.)(?<datetime>[0-9]{4}(?:-[0-9]{2}){2}' // date
. 'T[0-9]{2}(?::[0-9]{2}){2}(?:[\+\-][0-9]{2}:[0-9]{2})?)' // time
. ' - (?<loglevel>[A-Za-z]+) - (?<message>.*)(?!.)/msS' // loglevel, message
)));
$this->view->logData = $resource->select()->order('DESC')->paginate();
$this->view->logData = $resource->select()->order('DESC');
$this->setupLimitControl();
$this->setupPaginationControl($this->view->logData);
}
}

View File

@ -51,7 +51,7 @@ class AuthenticationBackendReorderForm extends ConfigForm
try {
if ($configForm->move($backendName, $position)->save()) {
Notification::success($this->translate('Authentication order updated!'));
Notification::success($this->translate('Authentication order updated'));
} else {
return false;
}

View File

@ -199,8 +199,8 @@ msgid "Authentication backend name missing"
msgstr "Nome del Backend di autenticazione non specificato"
#: /usr/share/icingaweb2/application/forms/Config/AuthenticationBackendReorderForm.php:54
msgid "Authentication order updated!"
msgstr "Ordine di autenticazione aggiornato!"
msgid "Authentication order updated"
msgstr "Ordine di autenticazione aggiornato"
#: /usr/share/icingaweb2/application/forms/AutoRefreshForm.php:44
msgid "Auto refresh successfully disabled"

View File

@ -130,8 +130,8 @@ msgid "Authentication backend name missing"
msgstr "Falta o nome do backend de autenticação"
#: /usr/local/icingaweb/application/forms/Config/AuthenticationBackendReorderForm.php:55
msgid "Authentication order updated!"
msgstr "Ordem da autenticação atualizada!"
msgid "Authentication order updated"
msgstr "Ordem da autenticação atualizada"
#: /usr/local/icingaweb/application/forms/Config/AuthenticationBackendConfigForm.php:307
msgid "Autologin"

View File

@ -1,8 +1,12 @@
<?php if (! $this->compact): ?>
<div class="controls">
<?= $this->tabs ?>
<?= $this->paginationControl($modules) ?>
<?= $this->tabs; ?>
<?= $this->sortBox; ?>
<?= $this->limiter; ?>
<?= $this->paginator; ?>
<?= $this->filterEditor; ?>
</div>
<?php endif ?>
<div class="content">
<table class="action" data-base-target="_next">
<tbody>

View File

@ -1,9 +1,12 @@
<?php if (! $this->compact): ?>
<div class="controls">
<?= $this->tabs->render($this) ?>
<div style="margin-top: 1em"></div>
<?= $this->logData ?>
<?= $this->tabs; ?>
<?= $this->sortBox; ?>
<?= $this->limiter; ?>
<?= $this->paginator; ?>
<?= $this->filterEditor; ?>
</div>
<?php endif ?>
<div class="content">
<?php if ($this->logData !== null): ?>
<table class="action">
@ -16,7 +19,7 @@
<?= $this->escape($value->loglevel) ?>
</td>
<td>
<?= $this->escape($value->message) ?>
<?= nl2br($this->escape($value->message), false) ?>
</td>
</tr>
<?php endforeach; ?>

View File

@ -107,7 +107,7 @@ Icinga Web 2 uses the MD5 based BSD password algorithm. For generating a passwor
command:
````
openssl passwd -1 "password"
openssl passwd -1 password
````
> Note: The switch to `openssl passwd` is the **number one** (`-1`) for using the MD5 based BSD password algorithm.

View File

@ -3,21 +3,133 @@
The preferred way of installing Icinga Web 2 is to use the official package repositories depending on which operating
system and distribution you are running. But it is also possible to install Icinga Web 2 directly from source.
## <a id="installation-requirements"></a> Installing Requirements
## <a id="installing-requirements"></a> Installing Requirements
* A web server, e.g. Apache or nginx
* PHP >= 5.3.0 w/ gettext and OpenSSL support
* MySQL or PostgreSQL PHP libraries when using a database for authentication or storing user preferences into a database
* PHP >= 5.3.0 w/ gettext, intl and OpenSSL support
* MySQL or PostgreSQL PHP libraries when using a database for authentication or for storing preferences into a database
* LDAP PHP library when using Active Directory or LDAP for authentication
* Icinga 1.x w/ Livestatus or IDO, Icinga 2 w/ Livestatus or IDO feature enabled
* Icinga 1.x w/ Livestatus or IDO; Icinga 2.x w/ Livestatus or IDO feature enabled
* MySQL or PostgreSQL PHP libraries when using IDO
## <a id="installation-from-package"></a> Installing Icinga Web 2 from Package
## <a id="installing-from-package"></a> Installing Icinga Web 2 from Package
A guide on how to install Icinga Web 2 from package will follow shortly.
Below is a list of official package repositories for installing Icinga Web 2 for various operating systems.
## <a id="installation-from-source"></a> Installing Icinga Web 2 from Source
Distribution | Repository
------------------------|---------------------------
Debian | [debmon](http://debmon.org/packages/debmon-wheezy/icingaweb2), [Icinga Repository](http://packages.icinga.org/debian/)
Ubuntu | [Icinga Repository](http://packages.icinga.org/ubuntu/)
RHEL/CentOS | [Icinga Repository](http://packages.icinga.org/epel/)
openSUSE | [Icinga Repository](http://packages.icinga.org/openSUSE/)
SLES | [Icinga Repository](http://packages.icinga.org/SUSE/)
Gentoo | -
FreeBSD | -
ArchLinux | [Upstream](https://aur.archlinux.org/packages/icingaweb2)
**Step 1: Getting the Source**
Packages for distributions other than the ones listed above may also be available.
Please contact your distribution packagers.
### <a id="package-repositories"></a> Setting up Package Repositories
You need to add the Icinga repository to your package management configuration for installing Icinga Web 2.
Below is a list with examples for various distributions.
Debian (debmon):
````
wget -O - http://debmon.org/debmon/repo.key 2>/dev/null | apt-key add -
echo 'deb http://debmon.org/debmon debmon-wheezy main' >/etc/apt/sources.list.d/debmon.list
apt-get update
````
Ubuntu Trusty:
````
wget -O - http://packages.icinga.org/icinga.key | apt-key add -
add-apt-repository 'deb http://packages.icinga.org/ubuntu icinga-trusty main'
apt-get update
````
For other Ubuntu versions just replace trusty with your distribution's code name.
RHEL and CentOS:
````
rpm --import http://packages.icinga.org/icinga.key
curl -o /etc/yum.repos.d/ICINGA-release.repo http://packages.icinga.org/epel/ICINGA-release.repo
yum makecache
````
Fedora:
````
rpm --import http://packages.icinga.org/icinga.key
curl -o /etc/yum.repos.d/ICINGA-release.repo http://packages.icinga.org/fedora/ICINGA-release.repo
yum makecache
````
SLES 11:
````
zypper ar http://packages.icinga.org/SUSE/ICINGA-release-11.repo
zypper ref
````
SLES 12:
````
zypper ar http://packages.icinga.org/SUSE/ICINGA-release.repo
zypper ref
````
openSUSE:
````
zypper ar http://packages.icinga.org/openSUSE/ICINGA-release.repo
zypper ref
````
The packages for RHEL/CentOS depend on other packages which are distributed as part of the
[EPEL repository](http://fedoraproject.org/wiki/EPEL). Please make sure to enable this repository by following
[these instructions](http://fedoraproject.org/wiki/EPEL#How_can_I_use_these_extra_packages.3F).
### <a id="installing-from-package-example"></a> Installing Icinga Web 2
You can install Icinga Web 2 by using your distribution's package manager to install the `icingaweb2` package.
Below is a list with examples for various distributions.
Debian and Ubuntu:
````
apt-get install icingaweb2
````
RHEL, CentOS and Fedora:
````
yum install icingaweb2
````
SLES and openSUSE:
````
zypper install icingaweb2
````
### <a id="preparing-web-setup-from-package"></a> Preparing Web Setup
You can set up Icinga Web 2 quickly and easily with the Icinga Web 2 setup wizard which is available the first time
you visit Icinga Web 2 in your browser. When using the web setup you are required to authenticate using a token.
In order to generate a token use the `icingacli`:
````
icingacli setup token create
````
In case you do not remember the token you can show it using the `icingacli`:
````
icingacli setup token show
````
Finally visit Icinga Web 2 in your browser to access the setup wizard and complete the installation:
`/icingaweb2/setup`.
## <a id="installing-from-source"></a> Installing Icinga Web 2 from Source
Although the preferred way of installing Icinga Web 2 is to use packages, it is also possible to install Icinga Web 2
directly from source.
### <a id="getting-the-source"></a> Getting the Source
First of all, you need to download the sources. Icinga Web 2 is available through a Git repository. You can clone this
repository either via git or http protocol using the following URLs:
@ -33,7 +145,7 @@ This version also offers snapshots for easy download which you can use if you do
git clone git://git.icinga.org/icingaweb2.git
````
**Step 2: Install the Source**
### <a id="installing-from-source-example"></a> Installing Icinga Web 2
Choose a target directory and move Icinga Web 2 there.
@ -41,7 +153,7 @@ Choose a target directory and move Icinga Web 2 there.
mv icingaweb2 /usr/share/icingaweb2
````
**Step 3: Configuring the Web Server**
### <a id="configuring-web-server"></a> Configuring the Web Server
Use `icingacli` to generate web server configuration for either Apache or nginx.
@ -57,13 +169,15 @@ nginx:
Save the output as new file in your webserver's configuration directory.
Example for Apache on RHEL/CentOS:
Example for Apache on RHEL or CentOS:
````
./bin/icingacli setup config webserver apache --document-root /usr/share/icingaweb2/public > /etc/httpd/conf.d/icingaweb2.conf
````
### <a id="preparing-web-setup-from-source"></a> Preparing Web Setup
**Step 4: Preparing Web Setup**
You can set up Icinga Web 2 quickly and easily with the Icinga Web 2 setup wizard which is available the first time
you visit Icinga Web 2 in your browser. Please follow the steps listed below for preparing the web setup.
Because both web and CLI must have access to configuration and logs, permissions will be managed using a special
system group. The web server user and CLI user have to be added to this system group.
@ -102,6 +216,7 @@ Use `icingacli` to create the configuration directory which defaults to **/etc/i
./bin/icingacli setup config directory
````
When using the web setup you are required to authenticate using a token. In order to generate a token use the
`icingacli`:
````
@ -113,11 +228,10 @@ In case you do not remember the token you can show it using the `icingacli`:
./bin/icingacli setup token show
````
**Step 5: Web Setup**
Finally visit Icinga Web 2 in your browser to access the setup wizard and complete the installation:
`/icingaweb2/setup`.
Visit Icinga Web 2 in your browser and complete installation using the web setup: /icingaweb2/setup
## Upgrading to Icinga Web 2 Beta 2
## <a id="upgrading-to-beta2"></a> Upgrading to Icinga Web 2 Beta 2
Icinga Web 2 Beta 2 introduces access control based on roles for secured actions. If you've already set up Icinga Web 2,
you are required to create the file **roles.ini** beneath Icinga Web 2's configuration directory with the following
@ -134,7 +248,7 @@ If you delegated authentication to your web server using the `autologin` backend
authentication backend to be able to log in again. The new name better reflects whats going on. A similar change
affects environments that opted for not storing preferences, your new backend is `none`.
## Upgrading to Icinga Web 2 Beta 3
## <a id="upgrading-to-beta3"></a> Upgrading to Icinga Web 2 Beta 3
Because Icinga Web 2 Beta 3 does not introduce any backward incompatible change you don't have to change your
configuration files after upgrading to Icinga Web 2 Beta 3.

View File

@ -506,12 +506,21 @@ abstract class ApplicationBootstrap
protected function setupLogger()
{
if ($this->config->hasSection('logging')) {
$loggingConfig = $this->config->getSection('logging');
try {
Logger::create($this->config->getSection('logging'));
Logger::create($loggingConfig);
} catch (ConfigurationError $e) {
Logger::error($e);
Logger::getInstance()->registerConfigError($e->getMessage());
try {
Logger::getInstance()->setLevel($loggingConfig->get('level', Logger::ERROR));
} catch (ConfigurationError $e) {
Logger::getInstance()->registerConfigError($e->getMessage());
}
}
}
return $this;
}

View File

@ -67,6 +67,13 @@ class Logger
*/
protected $level;
/**
* Error messages to be displayed prior to any other log message
*
* @var array
*/
protected $configErrors = array();
/**
* Create a new logger object
*
@ -81,39 +88,71 @@ class Logger
throw new ConfigurationError('Required logging configuration directive \'log\' missing');
}
if (($level = $config->level) !== null) {
if (is_numeric($level)) {
$level = (int) $level;
if (! isset(static::$levels[$level])) {
throw new ConfigurationError(
'Can\'t set logging level %d. Logging level is not defined. Use one of %s or one of the'
. ' Logger\'s constants.',
$level,
implode(', ', array_keys(static::$levels))
);
}
$this->level = $level;
} else {
$level = strtoupper($level);
$levels = array_flip(static::$levels);
if (! isset($levels[$level])) {
throw new ConfigurationError(
'Can\'t set logging level "%s". Logging level is not defined. Use one of %s.',
$level,
implode(', ', array_keys($levels))
);
}
$this->level = $levels[$level];
}
} else {
$this->level = static::ERROR;
}
$this->setLevel($config->get('level', static::ERROR));
if (strtolower($config->get('log', 'syslog')) !== 'none') {
$this->writer = $this->createWriter($config);
}
}
/**
* Set the logging level to use
*
* @param mixed $level
*
* @return $this
*
* @throws ConfigurationError In case the given level is invalid
*/
public function setLevel($level)
{
if (is_numeric($level)) {
$level = (int) $level;
if (! isset(static::$levels[$level])) {
throw new ConfigurationError(
'Can\'t set logging level %d. Logging level is invalid. Use one of %s or one of the'
. ' Logger\'s constants.',
$level,
implode(', ', array_keys(static::$levels))
);
}
$this->level = $level;
} else {
$level = strtoupper($level);
$levels = array_flip(static::$levels);
if (! isset($levels[$level])) {
throw new ConfigurationError(
'Can\'t set logging level "%s". Logging level is invalid. Use one of %s.',
$level,
implode(', ', array_keys($levels))
);
}
$this->level = $levels[$level];
}
return $this;
}
/**
* Register the given message as config error
*
* Config errors are logged every time a log message is being logged.
*
* @param mixed $arg,... A string, exception or format-string + substitutions
*
* @return $this
*/
public function registerConfigError()
{
if (func_num_args() > 0) {
$this->configErrors[] = static::formatMessage(func_get_args());
}
return $this;
}
/**
* Create a new logger object
*
@ -156,6 +195,10 @@ class Logger
public function log($level, $message)
{
if ($this->writer !== null && $this->level <= $level) {
foreach ($this->configErrors as $error_message) {
$this->writer->log(static::ERROR, $error_message);
}
$this->writer->log($level, $message);
}
}

View File

@ -67,6 +67,6 @@ class SyslogWriter extends LogWriter
public function log($level, $message)
{
openlog($this->ident, LOG_PID, $this->facility);
syslog(static::$severityMap[$level], $message);
syslog(static::$severityMap[$level], str_replace("\n", ' ', $message));
}
}

View File

@ -12,7 +12,6 @@ use Icinga\Exception\ConfigurationError;
use Icinga\Exception\SystemPermissionException;
use Icinga\Exception\ProgrammingError;
use Icinga\Exception\NotReadableError;
use Icinga\Exception\NotFoundError;
/**
* Module manager that handles detecting, enabling and disabling of modules
@ -102,6 +101,16 @@ class Manager
*/
private function detectEnabledModules()
{
if (! file_exists($parent = dirname($this->enableDir))) {
return;
}
if (! is_readable($parent)) {
throw new NotReadableError(
'Cannot read enabled modules. Module directory\'s parent directory "%s" is not readable',
$parent
);
}
if (! file_exists($this->enableDir)) {
return;
}
@ -199,7 +208,6 @@ class Manager
*
* @return $this
* @throws ConfigurationError When trying to enable a module that is not installed
* @throws NotFoundError In case the "enabledModules" directory does not exist
* @throws SystemPermissionException When insufficient permissions for the application exist
*/
public function enableModule($name)
@ -218,14 +226,15 @@ class Manager
if (! is_dir($this->enableDir) && !@mkdir($this->enableDir, 02770, true)) {
$error = error_get_last();
throw new SystemPermissionException(
'Failed to create enabledModule directory "%s" (%s)',
'Failed to create enabledModules directory "%s" (%s)',
$this->enableDir,
$error['message']
);
} elseif (! is_writable($this->enableDir)) {
throw new SystemPermissionException(
'Cannot enable module "%s". Insufficient system permissions for enabling modules.',
$name
'Cannot enable module "%s". Check the permissions for the enabledModules directory: %s',
$name,
$this->enableDir
);
}
@ -237,10 +246,11 @@ class Manager
$error = error_get_last();
if (strstr($error["message"], "File exists") === false) {
throw new SystemPermissionException(
'Could not enable module "%s" due to file system errors. '
'Cannot enable module "%s" at %s due to file system errors. '
. 'Please check path and mounting points because this is not a permission error. '
. 'Primary error was: %s',
$name,
$this->enableDir,
$error['message']
);
}
@ -259,32 +269,37 @@ class Manager
* @return $this
*
* @throws ConfigurationError When the module is not installed or it's not a symlink
* @throws SystemPermissionException When the module can't be disabled
* @throws SystemPermissionException When insufficient permissions for the application exist
*/
public function disableModule($name)
{
if (! $this->hasEnabled($name)) {
return $this;
}
if (! is_writable($this->enableDir)) {
throw new SystemPermissionException(
'Could not disable module. Module path is not writable.'
'Cannot disable module "%s". Check the permissions for the enabledModules directory: %s',
$name,
$this->enableDir
);
}
$link = $this->enableDir . DIRECTORY_SEPARATOR . $name;
if (! file_exists($link)) {
throw new ConfigurationError(
'Could not disable module. The module %s was not found.',
'Cannot disable module "%s". Module is not installed.',
$name
);
}
if (! is_link($link)) {
throw new ConfigurationError(
'Could not disable module. The module "%s" is not a symlink. '
'Cannot disable module %s at %s. '
. 'It looks like you have installed this module manually and moved it to your module folder. '
. 'In order to dynamically enable and disable modules, you have to create a symlink to '
. 'the enabled_modules folder.',
$name
. 'the enabledModules folder.',
$name,
$this->enableDir
);
}
@ -292,10 +307,11 @@ class Manager
if (! @unlink($link)) {
$error = error_get_last();
throw new SystemPermissionException(
'Could not disable module "%s" due to file system errors. '
'Cannot enable module "%s" at %s due to file system errors. '
. 'Please check path and mounting points because this is not a permission error. '
. 'Primary error was: %s',
$name,
$this->enableDir,
$error['message']
);
}

View File

@ -1,20 +0,0 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Data;
/**
* Interface for browsing data
*/
interface Browsable
{
/**
* Paginate data
*
* @param int $itemsPerPage Number of items per page
* @param int $pageNumber Current page number
*
* @return Zend_Paginator
*/
public function paginate($itemsPerPage = null, $pageNumber = null);
}

View File

@ -5,4 +5,4 @@ namespace Icinga\Data;
use Countable;
interface QueryInterface extends Browsable, Fetchable, Filterable, Limitable, Sortable, Countable {};
interface QueryInterface extends Fetchable, Filterable, Limitable, Sortable, Countable {};

View File

@ -3,14 +3,12 @@
namespace Icinga\Data;
use Icinga\Application\Icinga;
use ArrayIterator;
use IteratorAggregate;
use Icinga\Data\Filter\Filter;
use Icinga\Web\Paginator\Adapter\QueryAdapter;
use Zend_Paginator;
use Exception;
use Icinga\Exception\IcingaException;
class SimpleQuery implements QueryInterface, Queryable
class SimpleQuery implements QueryInterface, Queryable, IteratorAggregate
{
/**
* Query data source
@ -91,6 +89,16 @@ class SimpleQuery implements QueryInterface, Queryable
*/
protected function init() {}
/**
* Return a iterable for this query's result
*
* @return ArrayIterator
*/
public function getIterator()
{
return new ArrayIterator($this->fetchAll());
}
/**
* Get the data source
*
@ -319,35 +327,6 @@ class SimpleQuery implements QueryInterface, Queryable
return $this->limitOffset;
}
/**
* Paginate data
*
* Auto-detects pagination parameters from request when unset
*
* @param int $itemsPerPage Number of items per page
* @param int $pageNumber Current page number
*
* @return Zend_Paginator
*/
public function paginate($itemsPerPage = null, $pageNumber = null)
{
if ($itemsPerPage === null || $pageNumber === null) {
// Detect parameters from request
$request = Icinga::app()->getFrontController()->getRequest();
if ($itemsPerPage === null) {
$itemsPerPage = $request->getParam('limit', 25);
}
if ($pageNumber === null) {
$pageNumber = $request->getParam('page', 0);
}
}
$this->limit($itemsPerPage, $pageNumber * $itemsPerPage);
$paginator = new Zend_Paginator(new QueryAdapter($this));
$paginator->setItemCountPerPage($itemsPerPage);
$paginator->setCurrentPageNumber($pageNumber);
return $paginator;
}
/**
* Retrieve an array containing all rows of the result set
*

View File

@ -3,15 +3,13 @@
namespace Icinga\File;
use Icinga\Data\Browsable;
class Csv
{
protected $query;
protected function __construct() {}
public static function fromQuery(Browsable $query)
public static function fromQuery($query)
{
$csv = new Csv();
$csv->query = $query;

View File

@ -26,6 +26,13 @@ class FileReader implements Selectable, Countable
*/
protected $filename;
/**
* Cache for static::count()
*
* @var int
*/
protected $count = null;
/**
* Create a new reader
*
@ -51,7 +58,7 @@ class FileReader implements Selectable, Countable
*/
public function iterate()
{
return new FileIterator($this->filename, $this->fields);
return new LogFileIterator($this->filename, $this->fields);
}
/**
@ -71,7 +78,10 @@ class FileReader implements Selectable, Countable
*/
public function count()
{
return iterator_count($this->iterate());
if ($this->count === null) {
$this->count = iterator_count($this->iterate());
}
return $this->count;
}
/**

View File

@ -0,0 +1,155 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Protocol\File;
use Icinga\Exception\IcingaException;
use SplFileObject;
use Iterator;
/**
* Iterate over a log file, yielding the regex fields of the log messages
*/
class LogFileIterator implements Iterator
{
/**
* Log file
*
* @var SplFileObject
*/
protected $file;
/**
* A PCRE string with the fields to extract
* from the log messages as named subpatterns
*
* @var string
*/
protected $fields;
/**
* Value for static::current()
*
* @var string
*/
protected $current;
/**
* Index for static::key()
*
* @var int
*/
protected $index;
/**
* Value for static::valid()
*
* @var boolean
*/
protected $valid;
/**
* @var string
*/
protected $next = null;
/**
* @param string $filename The log file's name
* @param string $fields A PCRE string with the fields to extract
* from the log messages as named subpatterns
*/
public function __construct($filename, $fields)
{
$this->file = new SplFileObject($filename);
$this->file->setFlags(
SplFileObject::DROP_NEW_LINE |
SplFileObject::READ_AHEAD
);
$this->fields = $fields;
}
public function rewind()
{
$this->file->rewind();
$this->index = 0;
$this->nextMessage();
}
public function next()
{
$this->file->next();
++$this->index;
$this->nextMessage();
}
/**
* @return string
*/
public function current()
{
return $this->current;
}
/**
* @return int
*/
public function key()
{
return $this->index;
}
/**
* @return boolean
*/
public function valid()
{
return $this->valid;
}
protected function nextMessage()
{
$message = $this->next === null ? array() : array($this->next);
$this->valid = null;
while ($this->file->valid()) {
if (false === ($res = preg_match(
$this->fields, $current = $this->file->current()
))) {
throw new IcingaException('Failed at preg_match()');
}
if (empty($message)) {
if ($res === 1) {
$message[] = $current;
}
} else if ($res === 1) {
$this->next = $current;
$this->valid = true;
break;
} else {
$message[] = $current;
}
$this->file->next();
}
if ($this->valid === null) {
$this->next = null;
$this->valid = ! empty($message);
}
if ($this->valid) {
while (! empty($message)) {
$matches = array();
if (false === ($res = preg_match(
$this->fields, implode(PHP_EOL, $message), $matches
))) {
throw new IcingaException('Failed at preg_match()');
}
if ($res === 1) {
$this->current = $matches;
return;
}
array_pop($message);
}
$this->valid = false;
}
}
}

View File

@ -413,30 +413,30 @@ class User
/**
* Whether the user has a given permission
*
* @param string $permission
* @param string $requiredPermission
*
* @return bool
*/
public function can($permission)
public function can($requiredPermission)
{
if (isset($this->permissions['*']) || isset($this->permissions[$permission])) {
if (isset($this->permissions['*']) || isset($this->permissions[$requiredPermission])) {
return true;
}
// If the permission to check contains a wildcard, grant the permission if any permit related to the permission
// matches
$any = strpos($permission, '*');
foreach ($this->permissions as $permitted) {
if ($any !== false) {
$any = strpos($requiredPermission, '*');
foreach ($this->permissions as $grantedPermission) {
if ($any !== false && strpos($grantedPermission, '*') === false) {
$wildcard = $any;
} else {
// If the permit contains a wildcard, grant the permission if it's related to the permit
$wildcard = strpos($permitted, '*');
$wildcard = strpos($grantedPermission, '*');
}
if ($wildcard !== false) {
if (substr($permission, 0, $wildcard) === substr($permitted, 0, $wildcard)) {
if (substr($requiredPermission, 0, $wildcard) === substr($grantedPermission, 0, $wildcard)) {
return true;
}
} elseif ($permission === $permitted) {
} elseif ($requiredPermission === $grantedPermission) {
return true;
}
}

View File

@ -3,7 +3,13 @@
namespace Icinga\Web;
use Zend_Paginator;
use Icinga\Data\Sortable;
use Icinga\Data\QueryInterface;
use Icinga\Web\Paginator\Adapter\QueryAdapter;
use Icinga\Web\Controller\ModuleActionController;
use Icinga\Web\Widget\Limiter;
use Icinga\Web\Widget\SortBox;
/**
* This is the controller all modules should inherit from
@ -12,4 +18,130 @@ use Icinga\Web\Controller\ModuleActionController;
*/
class Controller extends ModuleActionController
{
/**
* @see ActionController::init
*/
public function init()
{
parent::init();
$this->handleSortControlSubmit();
}
/**
* Check whether the sort control has been submitted and redirect using GET parameters
*/
protected function handleSortControlSubmit()
{
$request = $this->getRequest();
if (! $request->isPost()) {
return;
}
if (($sort = $request->getPost('sort'))) {
$url = Url::fromRequest();
$url->setParam('sort', $sort);
if (($dir = $request->getPost('dir'))) {
$url->setParam('dir', $dir);
} else {
$url->removeParam('dir');
}
$this->redirectNow($url);
}
}
/**
* Create a SortBox widget and apply its sort rules on the given query
*
* The widget is set on the `sortBox' view property only if the current view has not been requested as compact
*
* @param array $columns An array containing the sort columns, with the
* submit value as the key and the label as the value
* @param Sortable $query Query to apply the user chosen sort rules on
*
* @return $this
*/
protected function setupSortControl(array $columns, Sortable $query = null)
{
$request = $this->getRequest();
$sortBox = SortBox::create('sortbox-' . $request->getActionName(), $columns);
$sortBox->setRequest($request);
if ($query) {
$sortBox->setQuery($query);
$sortBox->handleRequest($request);
}
if (! $this->view->compact) {
$this->view->sortBox = $sortBox;
}
return $this;
}
/**
* Create a Limiter widget at the `limiter' view property
*
* In case the current view has been requested as compact this method does nothing.
*
* @param int $itemsPerPage Default number of items per page
*
* @return $this
*/
protected function setupLimitControl($itemsPerPage = 25)
{
if (! $this->view->compact) {
$this->view->limiter = new Limiter();
$this->view->limiter->setDefaultLimit($itemsPerPage);
}
return $this;
}
/**
* Apply the given page limit and number on the given query and setup a paginator for it
*
* The $itemsPerPage and $pageNumber parameters are only applied if not available in the current request.
* The paginator is set on the `paginator' view property only if the current view has not been requested as compact.
*
* @param QueryInterface $query The query to create a paginator for
* @param int $itemsPerPage Default number of items per page
* @param int $pageNumber Default page number
*
* @return $this
*/
protected function setupPaginationControl(QueryInterface $query, $itemsPerPage = 25, $pageNumber = 0)
{
$request = $this->getRequest();
$limit = $request->getParam('limit', $itemsPerPage);
$page = $request->getParam('page', $pageNumber);
$query->limit($limit, $page * $limit);
if (! $this->view->compact) {
$paginator = new Zend_Paginator(new QueryAdapter($query));
$paginator->setItemCountPerPage($limit);
$paginator->setCurrentPageNumber($page);
$this->view->paginator = $paginator;
}
return $this;
}
/**
* Set the view property `filterEditor' to the given FilterEditor
*
* In case the current view has been requested as compact this method does nothing.
*
* @param Form $editor The FilterEditor
*
* @return $this
*/
protected function setupFilterControl($editor)
{
if (! $this->view->compact) {
$this->view->filterEditor = $editor;
}
return $this;
}
}

View File

@ -87,6 +87,7 @@ class ActionController extends Zend_Controller_Action
$this->_helper->layout()->isIframe = $request->getUrl()->shift('isIframe');
$this->_helper->layout()->moduleName = false;
$this->view->compact = $request->getParam('view') === 'compact';
if ($this->rerenderLayout = $request->getUrl()->shift('renderLayout')) {
$this->xhrLayout = 'body';
}
@ -315,13 +316,18 @@ class ActionController extends Zend_Controller_Action
if ($redirect !== null) {
$login->setParam('redirect', '__SELF__');
}
$this->_response->setHttpResponseCode(403);
} elseif ($redirect !== null) {
if (! $redirect instanceof Url) {
$redirect = Url::fromPath($redirect);
}
$login->setParam('redirect', $redirect->getRelativeUrl());
if (($relativeUrl = $redirect->getRelativeUrl())) {
$login->setParam('redirect', $relativeUrl);
}
}
$this->rerenderLayout()->redirectNow($login);
}

View File

@ -38,6 +38,28 @@ class Form extends Zend_Form
*/
const DEFAULT_SUFFIX = '_default';
/**
* The type of the notification for the error
*/
const NOTIFICATION_ERROR = 0;
/**
* The type of the notification for the warning
*/
const NOTIFICATION_WARNING = 2;
/**
* The type of the notification for the info
*/
const NOTIFICATION_INFO = 4;
/**
* The notifications of the form
*
* @var array
*/
protected $notifications = array();
/**
* Whether this form has been created
*
@ -1009,6 +1031,7 @@ class Form extends Zend_Form
}
$this->addDecorator('FormErrors', array('onlyCustomFormErrors' => true))
->addDecorator('FormNotifications')
->addDecorator('FormDescriptions')
->addDecorator('FormElements')
//->addDecorator('HtmlTag', array('tag' => 'dl', 'class' => 'zend_form'))
@ -1208,4 +1231,57 @@ class Form extends Zend_Form
throw new SecurityException('No permission for %s', $permission);
}
}
/**
* Return all form notifications
*
* @return array
*/
public function getNotifications()
{
return $this->notifications;
}
/**
* Add a typed message to the notifications
*
* @param string $message The message which would be displayed to the user
*
* @param int $type The type of the message notification
*/
public function addNotification($message, $type = self::NOTIFICATION_ERROR)
{
$this->notifications[$message] = $type;
$this->markAsError();
}
/**
* Add a error message to notifications
*
* @param string $message
*/
public function error($message)
{
$this->addNotification($message, $type = self::NOTIFICATION_ERROR);
}
/**
* Add a warning message to notifications
*
* @param string $message
*/
public function warning($message)
{
$this->addNotification($message, $type = self::NOTIFICATION_WARNING);
}
/**
* Add a info message to notifications
*
* @param string $message
*/
public function info($message)
{
$this->addNotification($message, $type = self::NOTIFICATION_INFO);
}
}

View File

@ -0,0 +1,95 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Web\Form\Decorator;
use Zend_Form_Decorator_Abstract;
use Icinga\Web\Form as Form;
/**
* Decorator to add a list of notifications at the top of a form
*/
class FormNotifications extends Zend_Form_Decorator_Abstract
{
/**
* Render form descriptions
*
* @param string $content The html rendered so far
*
* @return string The updated html
*/
public function render($content = '')
{
$form = $this->getElement();
if (! $form instanceof Form) {
return $content;
}
$view = $form->getView();
if ($view === null) {
return $content;
}
$notifications = $this->recurseForm($form);
if (empty($notifications)) {
return $content;
}
$html = '<ul class="form-notifications">';
asort($notifications);
foreach ($notifications as $message => $type) {
$html .= '<li class="'.self::getNotificationTypeName($type).'">' . $view->escape($message) . '</li>';
}
switch ($this->getPlacement()) {
case self::APPEND:
return $content . $html . '</ul>';
case self::PREPEND:
return $html . '</ul>' . $content;
}
}
/**
* Recurse the given form and return the notifications for it and all of its subforms
*
* @param Form $form The form to recurse
*
* @return array
*/
protected function recurseForm(Form $form)
{
$notifications = $form->getNotifications();
foreach ($form->getSubForms() as $subForm) {
$notifications = $notifications + $this->recurseForm($subForm);
}
return $notifications;
}
/**
* Get the readable type name of the notification
*
* @param $type Type of the message
*
* @return string
*/
public static function getNotificationTypeName($type)
{
switch ($type) {
case Form::NOTIFICATION_ERROR:
return 'error';
break;
case Form::NOTIFICATION_WARNING:
return 'warning';
break;
case Form::NOTIFICATION_INFO:
return 'info';
break;
default:
return 'unknown';
}
}
}

View File

@ -117,13 +117,18 @@ class Menu implements RecursiveIterator
foreach ($props as $key => $value) {
$method = 'set' . implode('', array_map('ucfirst', explode('_', strtolower($key))));
if ($key === 'renderer') {
$class = '\Icinga\Web\Menu\\' . $value;
if (!class_exists($class)) {
throw new ConfigurationError(
sprintf('ItemRenderer with class "%s" does not exist', $class)
);
$value = '\\' . ltrim($value, '\\');
if (class_exists($value)) {
$value = new $value;
} else {
$class = '\Icinga\Web\Menu' . $value;
if (!class_exists($class)) {
throw new ConfigurationError(
sprintf('ItemRenderer with class "%s" does not exist', $class)
);
}
$value = new $class;
}
$value = new $class;
}
if (method_exists($this, $method)) {
$this->{$method}($value);
@ -229,7 +234,8 @@ class Menu implements RecursiveIterator
$section = $this->add(t('System'), array(
'icon' => 'wrench',
'priority' => 200
'priority' => 200,
'renderer' => 'ProblemMenuItemRenderer'
));
$section->add(t('Configuration'), array(
'url' => 'config',
@ -464,6 +470,26 @@ class Menu implements RecursiveIterator
return $this->permission;
}
/**
* Get parent menu
*
* @return \Icinga\Web\Menu
*/
public function getParent()
{
return $this->parent;
}
/**
* Get submenus
*
* @return array
*/
public function getSubMenus()
{
return $this->subMenus;
}
/**
* Set permission a user is required to have granted to display the menu item
*

View File

@ -9,15 +9,9 @@ use Icinga\Web\Url;
/**
* A menu item with a link that surpasses the regular navigation link behavior
*/
class ForeignMenuItemRenderer implements MenuItemRenderer {
public function render(Menu $menu)
{
return sprintf(
'<a href="%s" target="_self">%s%s<span></span></a>',
$menu->getUrl() ?: '#',
$menu->getIcon() ? '<img aria-hidden="true" src="' . Url::fromPath($menu->getIcon()) . '" class="icon" /> ' : '',
htmlspecialchars($menu->getTitle())
);
}
class ForeignMenuItemRenderer extends MenuItemRenderer
{
protected $attributes = array(
'target' => '_self'
);
}

View File

@ -3,11 +3,108 @@
namespace Icinga\Web\Menu;
use Icinga\Application\Icinga;
use Icinga\Web\Menu;
use Icinga\Web\Url;
use Icinga\Web\View;
/**
* Renders the html content of a single menu item
* Default MenuItemRenderer class
*/
interface MenuItemRenderer {
public function render(Menu $menu);
class MenuItemRenderer
{
/**
* Contains <a> element specific attributes
*
* @var array
*/
protected $attributes = array();
/**
* View
*
* @var View|null
*/
protected $view;
/**
* Set the view
*
* @param View $view
*
* @return $this
*/
public function setView(View $view)
{
$this->view = $view;
return $this;
}
/**
* Get the view
*
* @return View
*/
public function getView()
{
if ($this->view === null) {
$this->view = Icinga::app()->getViewRenderer()->view;
}
return $this->view;
}
/**
* Renders the html content of a single menu item
*
* @param Menu $menu
*
* @return string
*/
public function render(Menu $menu)
{
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

@ -3,10 +3,62 @@
namespace Icinga\Web\Menu;
class ProblemMenuItemRenderer extends MonitoringMenuItemRenderer
use Icinga\Web\Menu;
class ProblemMenuItemRenderer extends MenuItemRenderer
{
protected $columns = array(
'hosts_down_unhandled',
'services_critical_unhandled'
);
/**
* 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

@ -4,6 +4,7 @@
namespace Icinga\Web;
use Exception;
use Icinga\Web\Menu\MenuItemRenderer;
use RecursiveIteratorIterator;
use Icinga\Application\Logger;
use Icinga\Web\Menu\PermittedMenuItemFilter;
@ -32,6 +33,11 @@ class MenuRenderer extends RecursiveIteratorIterator
*/
protected $useCustomRenderer = false;
/**
* @var MenuItemRenderer
*/
protected $defaultRenderer;
/**
* Create a new MenuRenderer
*
@ -45,6 +51,7 @@ class MenuRenderer extends RecursiveIteratorIterator
} else {
$this->url = Url::fromPath($url);
}
$this->defaultRenderer = new MenuItemRenderer();
parent::__construct(new PermittedMenuItemFilter($menu), RecursiveIteratorIterator::CHILD_FIRST);
}
@ -114,22 +121,8 @@ class MenuRenderer extends RecursiveIteratorIterator
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 $this->defaultRenderer->render($child);
}
/**

View File

@ -77,7 +77,7 @@ class PhpSession extends Session
}
}
$sessionSavePath = session_save_path();
$sessionSavePath = session_save_path() ?: sys_get_temp_dir();
if (session_module_name() === 'files' && !is_writable($sessionSavePath)) {
throw new ConfigurationError("Can't save session, path '$sessionSavePath' is not writable.");
}

View File

@ -26,7 +26,8 @@ class StyleSheet
'css/icinga/pagination.less',
'css/icinga/monitoring-colors.less',
'css/icinga/selection-toolbar.less',
'css/icinga/login.less'
'css/icinga/login.less',
'css/icinga/controls.less'
);
public static function compileForPdf()

View File

@ -127,7 +127,8 @@ class HistoryColorGrid extends AbstractWidget {
. ' opacity: ' . $this->opacity . ';" ' .
'aria-label="' . $entry['caption'] . '" ' .
'title="' . $entry['caption'] . '" ' .
'href="' . $entry['url'] . '"' .
'href="' . $entry['url'] . '" ' .
'data-tooltip-delay="0"' .
'></a>';
} else {
return '<span ' .

View File

@ -6,6 +6,7 @@ namespace Icinga\Web\Widget;
use Icinga\Data\Filter\Filter;
use Icinga\Data\Filter\FilterExpression;
use Icinga\Data\Filter\FilterChain;
use Icinga\Data\Filter\FilterOr;
use Icinga\Web\Url;
use Icinga\Application\Icinga;
use Icinga\Exception\ProgrammingError;
@ -39,6 +40,8 @@ class FilterEditor extends AbstractWidget
protected $ignoreParams = array();
protected $searchColumns = null;
/**
* @var string
*/
@ -73,6 +76,12 @@ class FilterEditor extends AbstractWidget
return $this->filter;
}
public function setSearchColumns(array $searchColumns)
{
$this->searchColumns = $searchColumns;
return $this;
}
public function setUrl($url)
{
$this->url = $url;
@ -147,6 +156,26 @@ class FilterEditor extends AbstractWidget
return $filter;
}
protected function resetSearchColumns(Filter &$filter)
{
if ($filter->isChain()) {
$filters = &$filter->filters();
if (!($empty = empty($filters))) {
foreach ($filters as $k => &$f) {
if (false === $this->resetSearchColumns($f)) {
unset($filters[$k]);
}
}
}
return $empty || !empty($filters);
}
return $filter->isExpression() ? !(
in_array($filter->getColumn(), $this->searchColumns)
&&
$filter->getSign() === '='
) : true;
}
public function handleRequest($request)
{
$this->setUrl($request->getUrl()->without($this->ignoreParams));
@ -179,35 +208,48 @@ class FilterEditor extends AbstractWidget
$filter = $this->getFilter();
if ($search !== null) {
if (strpos($search, '=') === false) {
// TODO: Ask the view for (multiple) search columns
switch($request->getActionName()) {
case 'services':
$searchCol = 'service_description';
break;
case 'hosts':
$searchCol = 'host_name';
break;
case 'hostgroups':
$searchCol = 'hostgroup';
break;
case 'servicegroups':
$searchCol = 'servicegroup';
break;
default:
$searchCol = null;
}
if ($this->searchColumns === null) {
if (strpos($search, '=') === false) {
// TODO: Ask the view for (multiple) search columns
switch($request->getActionName()) {
case 'services':
$searchCol = 'service';
break;
case 'hosts':
$searchCol = 'host';
break;
case 'hostgroups':
$searchCol = 'hostgroup';
break;
case 'servicegroups':
$searchCol = 'servicegroup';
break;
default:
$searchCol = null;
}
if ($searchCol === null) {
throw new Exception('Cannot search here');
if ($searchCol === null) {
throw new Exception('Cannot search here');
}
$search = ltrim($search);
$filter = $this->mergeRootExpression($filter, $searchCol, '=', "*$search*");
} else {
list($k, $v) = preg_split('/=/', $search);
$filter = $this->mergeRootExpression($filter, trim($k), '=', ltrim($v));
}
$search = ltrim($search);
$filter = $this->mergeRootExpression($filter, $searchCol, '=', "*$search*");
} else {
list($k, $v) = preg_split('/=/', $search);
$filter = $this->mergeRootExpression($filter, trim($k), '=', ltrim($v));
if (false === $this->resetSearchColumns($filter)) {
$filter = Filter::matchAll();
}
$filters = array();
$search = ltrim($search);
foreach ($this->searchColumns as $searchColumn) {
$filters[] = Filter::expression($searchColumn, '=', "*$search*");
}
$filter->andFilter(new FilterOr($filters));
}
$url = $this->url()->setQueryString(
$filter->toQueryString()
)->addParams($preserve);
@ -649,7 +691,7 @@ class FilterEditor extends AbstractWidget
public function renderSearch()
{
$html = ' <form method="post" class="inline dontprint" action="'
$html = ' <form method="post" class="search inline dontprint" action="'
. $this->preservedUrl()
. '"><input type="text" name="q" style="width: 8em" class="search" value="" placeholder="'
. t('Search...')
@ -678,20 +720,22 @@ class FilterEditor extends AbstractWidget
public function render()
{
if (! $this->preservedUrl()->getParam('modifyFilter')) {
return $this->renderSearch() . $this->shorten($this->filter, 50);
return '<div class="filter">' . $this->renderSearch() . $this->shorten($this->filter, 50) . '</div>';
}
return $this->renderSearch()
. '<form action="'
. Url::fromRequest()
. '" class="filterEditor" method="POST">'
. '<ul class="tree widgetFilter"><li>'
. $this->renderFilter($this->filter)
. '</li></ul>'
. '<div style="float: right">'
. '<input type="submit" name="submit" value="Apply" />'
. '<input type="submit" name="cancel" value="Cancel" />'
. '</div>'
. '</form>';
return '<div class="filter">'
. $this->renderSearch()
. '<form action="'
. Url::fromRequest()
. '" class="editor" method="POST">'
. '<ul class="tree"><li>'
. $this->renderFilter($this->filter)
. '</li></ul>'
. '<div class="buttons">'
. '<input type="submit" name="submit" value="Apply" />'
. '<input type="submit" name="cancel" value="Cancel" />'
. '</div>'
. '</form>'
. '</div>';
}
protected function shorten($string, $length)

View File

@ -21,6 +21,8 @@ class Limiter extends AbstractWidget
private $pages;
private $default;
public function setUrl(Url $url)
{
$this->url = $url;
@ -39,13 +41,19 @@ class Limiter extends AbstractWidget
return $this;
}
public function setDefaultLimit($limit)
{
$this->default = $limit;
return $this;
}
public function render()
{
if ($this->url === null) {
$this->url = Url::fromRequest();
}
$currentLimit = (int) $this->url->getParam('limit', 25); // Default??
$currentLimit = (int) $this->url->getParam('limit', $this->default);
$availableLimits = array(
10 => '10',
25 => '25',

View File

@ -3,64 +3,66 @@
namespace Icinga\Web\Widget;
use Zend_Form_Element_Submit;
use Icinga\Web\Form;
use Icinga\Web\Request;
use Icinga\Web\Form\Decorator\ConditionalHidden;
use Icinga\Data\Sortable;
use Icinga\Application\Icinga;
/**
* Sortbox widget
* SortBox widget
*
* The "SortBox" Widget allows you to create a generic sort input for sortable views.
* It automatically creates a form containing a select box with all sort options and a
* dropbox with the sort direction. It also handles automatic submission of sorting changes and draws an additional
* submit button when JavaScript is disabled.
* The "SortBox" Widget allows you to create a generic sort input for sortable views. It automatically creates a form
* containing a select box with all sort options and a dropbox with the sort direction. It also handles automatic
* submission of sorting changes and draws an additional submit button when JavaScript is disabled.
*
* The constructor takes an string for the component name ad an array containing the select options, where the key is
* the value to be submitted and the value is the label that will be shown. You then should call applyRequest in order
* to make sure the form is correctly populated when a request with a sort parameter is being made.
* The constructor takes an string for the component name and an array containing the select options, where the key is
* the value to be submitted and the value is the label that will be shown. You then should call setRequest in order
* to make sure the form is correctly populated when a request with a sort parameter is being made.
*
* Example:
* <pre><code>
* Example:
* <pre><code>
* $this->view->sortControl = new SortBox(
* $this->getRequest()->getActionName(),
* $this->getRequest()->getActionName(),
* $columns
* );
* $this->view->sortControl->applyRequest($this->getRequest());
* </code></pre>
* By default the sortBox uses the GET parameter 'sort' for the sorting key and 'dir' for the sorting direction
*
* $this->view->sortControl->setRequest($this->getRequest());
* </code></pre>
*/
class SortBox extends AbstractWidget
{
/**
* An array containing all sort columns with their associated labels
*
* @var array
*/
private $sortFields;
protected $sortFields;
/**
* The name of the form that will be created
*
* @var string
*/
private $name;
protected $name;
/**
* A request object used for initial form population
*
* @var \Icinga\Web\Request
* @var Request
*/
private $request;
protected $request;
/**
* What to apply sort parameters on
*
* @var Sortable
*/
protected $query = null;
/**
* Create a SortBox with the entries from $sortFields
*
* @param string $name The name of the sort form
* @param array $sortFields An array containing the columns and their labels to be displayed
* in the sort select box
* @param string $name The name for the SortBox
* @param array $sortFields An array containing the columns and their labels to be displayed in the SortBox
*/
public function __construct($name, array $sortFields)
{
@ -69,13 +71,12 @@ class SortBox extends AbstractWidget
}
/**
* Create a SortBox with the entries from $sortFields
* Create a SortBox
*
* @param string $name The name of the sort form
* @param array $sortFields An array containing the columns and their labels to be displayed
* in the sort select box
* @param string $name The name for the SortBox
* @param array $sortFields An array containing the columns and their labels to be displayed in the SortBox
*
* @return static
* @return SortBox
*/
public static function create($name, array $sortFields)
{
@ -85,71 +86,84 @@ class SortBox extends AbstractWidget
/**
* Apply the parameters from the given request on this SortBox
*
* @param Request $request The request to use for populating the form
* @param Request $request The request to use for populating the form
*
* @return $this
* @return $this
*/
public function applyRequest($request)
public function setRequest($request)
{
$this->request = $request;
return $this;
}
/**
* Create a submit button that is hidden via the ConditionalDecorator
* in order to allow sorting changes to be submitted in a JavaScript-less environment
* @param Sortable $query
*
* @return Zend_Form_Element_Submit The submit button that is hidden by default
* @see ConditionalDecorator
* @return $this
*/
private function createFallbackSubmitButton()
public function setQuery(Sortable $query)
{
$manualSubmitButton = new Zend_Form_Element_Submit(
array(
'name' => 'submit_' . $this->name,
'label' => 'Sort',
'class' => '',
'condition' => 0,
'value' => '{{SUBMIT_ICON}}'
)
);
$manualSubmitButton->addDecorator(new ConditionalHidden());
$manualSubmitButton->setAttrib('addLabelPlaceholder', true);
return $manualSubmitButton;
$this->query = $query;
return $this;
}
public function handleRequest(Request $request = null)
{
if ($this->query !== null) {
if ($request === null) {
$request = Icinga::app()->getFrontController()->getRequest();
}
if ($sort = $request->getParam('sort')) {
$this->query->order($sort, $request->getParam('dir'));
}
}
return $this;
}
/**
* Renders this widget via the given view and returns the
* HTML as a string
* Render this SortBox as HTML
*
* @return string
*/
public function render()
{
$form = new Form();
$form->setAttrib('class', 'inline');
$form->setMethod('POST');
$form->setTokenDisabled();
$form->setName($this->name);
$form->addElement('select', 'sort', array(
'label' => 'Sort By',
'multiOptions' => $this->sortFields,
'style' => 'width: 12em',
'autosubmit' => true
$form->setAttrib('class', 'sort-control inline');
$form->addElement(
'select',
'sort',
array(
'autosubmit' => true,
'label' => $this->view()->translate('Sort by'),
'multiOptions' => $this->sortFields
)
);
$form->getElement('sort')->setDecorators(array(
array('ViewHelper'),
array('Label')
));
$form->addElement('select', 'dir', array(
'multiOptions' => array(
'asc' => 'Asc',
'desc' => 'Desc',
),
'style' => 'width: 5em',
'autosubmit' => true
));
$sort = $form->getElement('sort')->setDecorators(array('ViewHelper'));
$dir = $form->getElement('dir')->setDecorators(array('ViewHelper'));
$form->addElement(
'select',
'dir',
array(
'autosubmit' => true,
'multiOptions' => array(
'asc' => 'Asc',
'desc' => 'Desc',
),
'decorators' => array(
array('ViewHelper')
)
)
);
if ($this->request) {
$form->populate($this->request->getParams());
}
return $form;
}
}

View File

@ -24,7 +24,7 @@ class DashboardAction implements Tabextension
'dashboard',
array(
'icon' => 'dashboard',
'label' => 'Add To Dashboard',
'label' => t('Add To Dashboard'),
'url' => Url::fromPath('dashboard/new-dashlet'),
'urlParams' => array(
'url' => rawurlencode(Url::fromRequest()->getRelativeUrl())

View File

@ -22,7 +22,7 @@ class DashboardSettings implements Tabextension
'dashboard_add',
array(
'icon' => 'img/icons/dashboard.png',
'label' => t('Add To Dashboard'),
'label' => t('Add New Pane Or Dashlet'),
'url' => Url::fromPath('dashboard/new-dashlet')
)
);

View File

@ -49,7 +49,7 @@ EOT;
*/
private $closeTpl = <<< 'EOT'
<li class="dropdown" style="float: right;">
<a href="#" class="dropdown-toggle close-toggle">X</a>
<a href="#" class="dropdown-toggle close-toggle"> <i aria-hidden="true" class="icon-cancel"></i> </a>
</li>
EOT;

View File

@ -1,6 +1,7 @@
<div class="controls"></div>
<div class="controls">
<?= /** @var \Icinga\Web\Widget\Tabs $tabs */ $tabs->showOnlyCloseButton(); ?>
<h1><?= $this->translate('Available documentations'); ?></h1>
</div>
<div class="content">
<ul>
<li><?= $this->qlink(

View File

@ -5,9 +5,9 @@ namespace Icinga\Module\Doc;
use Icinga\Module\Doc\Renderer\DocSectionRenderer;
use Icinga\Module\Doc\Renderer\DocTocRenderer;
use Icinga\Web\Controller\ModuleActionController;
use Icinga\Web\Controller;
class DocController extends ModuleActionController
class DocController extends Controller
{
/**
* Render a chapter

View File

@ -6,6 +6,7 @@ use Icinga\Chart\Unit\LinearUnit;
use Icinga\Chart\Unit\StaticAxis;
use Icinga\Module\Monitoring\Controller;
use Icinga\Module\Monitoring\Web\Widget\SelectBox;
use Icinga\Web\Widget\Tabextension\DashboardAction;
use Icinga\Web\Url;
class Monitoring_AlertsummaryController extends Controller
@ -44,7 +45,7 @@ class Monitoring_AlertsummaryController extends Controller
'label' => $this->translate('Alert Summary'),
'url' => Url::fromRequest()
)
)->activate('alertsummary');
)->extend(new DashboardAction())->activate('alertsummary');
$this->view->title = $this->translate('Alert Summary');
$this->view->intervalBox = $this->createIntervalBox();
@ -59,18 +60,20 @@ class Monitoring_AlertsummaryController extends Controller
$query = $this->backend->select()->from(
'notification',
array(
'host',
'host_name',
'host_display_name',
'service',
'service_description',
'service_display_name',
'notification_output',
'notification_contact',
'notification_contact_name',
'notification_start_time',
'notification_state'
)
);
$this->view->notifications = $query;
$this->view->notifications = $query->paginate();
$this->setupLimitControl();
$this->setupPaginationControl($this->view->notifications);
}
/**
@ -85,12 +88,7 @@ class Monitoring_AlertsummaryController extends Controller
$query = $this->backend->select()->from(
'notification',
array(
'host',
'service',
'notification_output',
'notification_contact',
'notification_start_time',
'notification_state'
'notification_start_time'
)
);
@ -138,12 +136,7 @@ class Monitoring_AlertsummaryController extends Controller
$query = $this->backend->select()->from(
'notification',
array(
'host',
'service',
'notification_output',
'notification_contact',
'notification_start_time',
'notification_state'
'notification_start_time'
)
);
@ -210,12 +203,7 @@ class Monitoring_AlertsummaryController extends Controller
$query = $this->backend->select()->from(
'notification',
array(
'host',
'service',
'notification_output',
'notification_contact',
'notification_start_time',
'notification_state'
'notification_start_time'
)
);
@ -263,20 +251,9 @@ class Monitoring_AlertsummaryController extends Controller
$interval = $this->getInterval();
$query = $this->backend->select()->from(
'EventHistory',
'eventHistory',
array(
'host_name',
'service_description',
'object_type',
'timestamp',
'state',
'attempt',
'max_attempts',
'output',
'type',
'host',
'service',
'service_host_name'
'timestamp'
)
);
@ -338,11 +315,7 @@ class Monitoring_AlertsummaryController extends Controller
$query = $this->backend->select()->from(
'notification',
array(
'host',
'service',
'notification_object_id',
'notification_output',
'notification_contact',
'notification_start_time',
'notification_state',
'acknowledgement_entry_time'
@ -507,12 +480,12 @@ class Monitoring_AlertsummaryController extends Controller
$query = $this->backend->select()->from(
'notification',
array(
'host',
'host_name',
'host_display_name',
'service',
'service_description',
'service_display_name',
'notification_output',
'notification_contact',
'notification_contact_name',
'notification_start_time',
'notification_state'
)
@ -520,7 +493,7 @@ class Monitoring_AlertsummaryController extends Controller
$query->order('notification_start_time', 'desc');
return $query->paginate(5);
return $query->limit(5);
}
/**

View File

@ -16,11 +16,6 @@ use Icinga\Chart\Unit\LinearUnit;
class Monitoring_ChartController extends Controller
{
public function init()
{
$this->view->compact = $this->_request->getParam('view') === 'compact';
}
private function drawLogChart1()
{
$chart = new GridChart();

View File

@ -0,0 +1,100 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
use Icinga\Module\Monitoring\Controller;
use Icinga\Module\Monitoring\Forms\Command\Object\DeleteCommentCommandForm;
use Icinga\Web\Url;
use Icinga\Web\Widget\Tabextension\DashboardAction;
/**
* Display detailed information about a comment
*/
class Monitoring_CommentController extends Controller
{
/**
* The fetched comment
*
* @var stdClass
*/
protected $comment;
/**
* Fetch the first comment with the given id and add tabs
*
* @throws Zend_Controller_Action_Exception
*/
public function init()
{
$commentId = $this->params->get('comment_id');
$this->comment = $this->backend->select()->from('comment', array(
'id' => 'comment_internal_id',
'objecttype' => 'comment_objecttype',
'comment' => 'comment_data',
'author' => 'comment_author_name',
'timestamp' => 'comment_timestamp',
'type' => 'comment_type',
'persistent' => 'comment_is_persistent',
'expiration' => 'comment_expiration',
'host_name',
'service_description',
'host_display_name',
'service_display_name'
))->where('comment_internal_id', $commentId)->getQuery()->fetchRow();
if (false === $this->comment) {
throw new Zend_Controller_Action_Exception($this->translate('Comment not found'));
}
$this->getTabs()->add(
'comment',
array(
'title' => $this->translate(
'Display detailed information about a comment.'
),
'icon' => 'comment',
'label' => $this->translate('Comment'),
'url' =>'monitoring/comments/show'
)
)->activate('comment')->extend(new DashboardAction());
}
/**
* Display comment detail view
*/
public function showAction()
{
$listCommentsLink = Url::fromPath('monitoring/list/comments')
->setQueryString('comment_type=(comment|ack)');
$this->view->comment = $this->comment;
if ($this->hasPermission('monitoring/command/comment/delete')) {
$this->view->delCommentForm = $this->createDelCommentForm();
$this->view->delCommentForm->populate(
array(
'redirect' => $listCommentsLink,
'comment_id' => $this->comment->id,
'comment_is_service' => isset($this->comment->service_description)
)
);
}
}
/**
* Create a command form to delete a single comment
*
* @return DeleteCommentsCommandForm
*/
private function createDelCommentForm()
{
$this->assertPermission('monitoring/command/comment/delete');
$delCommentForm = new DeleteCommentCommandForm();
$delCommentForm->setAction(
Url::fromPath('monitoring/comment/show')
->setParam('comment_id', $this->comment->id)
);
$delCommentForm->handleRequest();
return $delCommentForm;
}
}

View File

@ -0,0 +1,100 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
use Icinga\Module\Monitoring\Controller;
use Icinga\Module\Monitoring\Forms\Command\Object\DeleteCommentsCommandForm;
use Icinga\Web\Url;
use Icinga\Data\Filter\Filter;
/**
* Display detailed information about a comment
*/
class Monitoring_CommentsController extends Controller
{
/**
* The fetched comments
*
* @var array
*/
protected $comments;
/**
* Fetch all comments matching the current filter and add tabs
*
* @throws Zend_Controller_Action_Exception
*/
public function init()
{
$this->filter = Filter::fromQueryString(str_replace(
'comment_id',
'comment_internal_id',
(string)$this->params
));
$this->comments = $this->backend->select()->from('comment', array(
'id' => 'comment_internal_id',
'objecttype' => 'comment_objecttype',
'comment' => 'comment_data',
'author' => 'comment_author_name',
'timestamp' => 'comment_timestamp',
'type' => 'comment_type',
'persistent' => 'comment_is_persistent',
'expiration' => 'comment_expiration',
'host_name',
'service_description',
'host_display_name',
'service_display_name'
))->addFilter($this->filter)->getQuery()->fetchAll();
if (false === $this->comments) {
throw new Zend_Controller_Action_Exception($this->translate('Comment not found'));
}
$this->getTabs()->add(
'comments',
array(
'title' => $this->translate(
'Display detailed information about multiple comments.'
),
'icon' => 'comment',
'label' => $this->translate('Comments'),
'url' =>'monitoring/comments/show'
)
)->activate('comments');
}
/**
* Display the detail view for a comment list
*/
public function showAction()
{
$this->view->comments = $this->comments;
$this->view->listAllLink = Url::fromPath('monitoring/list/comments')
->setQueryString($this->filter->toQueryString());
$this->view->removeAllLink = Url::fromPath('monitoring/comments/delete-all')
->setParams($this->params);
}
/**
* Display the form for removing a comment list
*/
public function deleteAllAction()
{
$this->assertPermission('monitoring/command/comment/delete');
$listCommentsLink = Url::fromPath('monitoring/list/comments')
->setQueryString('comment_type=(comment|ack)');
$delCommentForm = new DeleteCommentsCommandForm();
$delCommentForm->setTitle($this->view->translate('Remove all Comments'));
$delCommentForm->addDescription(sprintf(
$this->translate('Confirm removal of %d comments.'),
count($this->comments)
));
$delCommentForm->setComments($this->comments)
->setRedirectUrl($listCommentsLink)
->handleRequest();
$this->view->delCommentForm = $delCommentForm;
$this->view->comments = $this->comments;
$this->view->listAllLink = Url::fromPath('monitoring/list/comments')
->setQueryString($this->filter->toQueryString());
}
}

View File

@ -4,7 +4,7 @@
use Icinga\Web\Notification;
use Icinga\Data\ResourceFactory;
use Icinga\Forms\ConfirmRemovalForm;
use Icinga\Web\Controller\ModuleActionController;
use Icinga\Web\Controller;
use Icinga\Module\Monitoring\Forms\Config\BackendConfigForm;
use Icinga\Module\Monitoring\Forms\Config\InstanceConfigForm;
use Icinga\Module\Monitoring\Forms\Config\SecurityConfigForm;
@ -12,7 +12,7 @@ use Icinga\Module\Monitoring\Forms\Config\SecurityConfigForm;
/**
* Configuration controller for editing monitoring resources
*/
class Monitoring_ConfigController extends ModuleActionController
class Monitoring_ConfigController extends Controller
{
/**
* Display a list of available backends and instances

View File

@ -0,0 +1,141 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
use Icinga\Module\Monitoring\Controller;
use Icinga\Module\Monitoring\Object\Service;
use Icinga\Module\Monitoring\Object\Host;
use Icinga\Module\Monitoring\Forms\Command\Object\DeleteDowntimeCommandForm;
use Icinga\Module\Monitoring\Command\Object\DeleteDowntimeCommand;
use Icinga\Web\Url;
use Icinga\Web\Widget\Tabextension\DashboardAction;
/**
* Display detailed information about a downtime
*/
class Monitoring_DowntimeController extends Controller
{
/**
* The fetched downtime
*
* @var stdClass
*/
protected $downtime;
/**
* If the downtime is a service or not
*
* @var boolean
*/
protected $isService;
/**
* Fetch the downtime matching the given id and add tabs
*
* @throws Zend_Controller_Action_Exception
*/
public function init()
{
$downtimeId = $this->params->get('downtime_id');
$this->downtime = $this->backend->select()->from('downtime', array(
'id' => 'downtime_internal_id',
'objecttype' => 'downtime_objecttype',
'comment' => 'downtime_comment',
'author_name' => 'downtime_author_name',
'start' => 'downtime_start',
'scheduled_start' => 'downtime_scheduled_start',
'scheduled_end' => 'downtime_scheduled_end',
'end' => 'downtime_end',
'duration' => 'downtime_duration',
'is_flexible' => 'downtime_is_flexible',
'is_fixed' => 'downtime_is_fixed',
'is_in_effect' => 'downtime_is_in_effect',
'entry_time' => 'downtime_entry_time',
'host_state' => 'downtime_host_state',
'service_state' => 'downtime_service_state',
'host_name',
'host',
'service',
'service_description',
'host_display_name',
'service_display_name'
))->where('downtime_internal_id', $downtimeId)->getQuery()->fetchRow();
if (false === $this->downtime) {
throw new Zend_Controller_Action_Exception($this->translate('Downtime not found'));
}
if (isset($this->downtime->service_description)) {
$this->isService = true;
} else {
$this->isService = false;
}
$this->getTabs()
->add(
'downtime',
array(
'title' => $this->translate(
'Display detailed information about a downtime.'
),
'icon' => 'plug',
'label' => $this->translate('Downtime'),
'url' =>'monitoring/downtimes/show'
)
)->activate('downtime')->extend(new DashboardAction());
}
/**
* Display the detail view for a downtime
*/
public function showAction()
{
$this->view->downtime = $this->downtime;
$this->view->isService = $this->isService;
$this->view->stateName = isset($this->downtime->service_description) ?
Service::getStateText($this->downtime->service_state) :
Host::getStateText($this->downtime->host_state);
$this->view->listAllLink = Url::fromPath('monitoring/list/downtimes');
$this->view->showHostLink = Url::fromPath('monitoring/host/show')
->setParam('host', $this->downtime->host);
$this->view->showServiceLink = Url::fromPath('monitoring/service/show')
->setParam('host', $this->downtime->host)
->setParam('service', $this->downtime->service_description);
if ($this->hasPermission('monitoring/command/downtime/delete')) {
$this->view->delDowntimeForm = $this->createDelDowntimeForm();
$this->view->delDowntimeForm->populate(
array(
'redirect' => Url::fromPath('monitoring/list/downtimes'),
'downtime_id' => $this->downtime->id,
'downtime_is_service' => $this->isService
)
);
}
}
/**
* Receive DeleteDowntimeCommandForm post from other controller
*/
public function removeAction()
{
$this->assertHttpMethod('POST');
$this->createDelDowntimeForm();
}
/**
* Create a command form to delete a single comment
*
* @return DeleteDowntimeCommandForm
*/
private function createDelDowntimeForm()
{
$this->assertPermission('monitoring/command/downtime/delete');
$delDowntimeForm = new DeleteDowntimeCommandForm();
$delDowntimeForm->setAction(
Url::fromPath('monitoring/downtime/show')
->setParam('downtime_id', $this->downtime->id)
);
$delDowntimeForm->handleRequest();
return $delDowntimeForm;
}
}

View File

@ -0,0 +1,130 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
use Icinga\Data\Filter\Filter;
use Icinga\Module\Monitoring\Controller;
use Icinga\Module\Monitoring\Object\Service;
use Icinga\Module\Monitoring\Object\Host;
use Icinga\Module\Monitoring\Forms\Command\Object\DeleteDowntimesCommandForm;
use Icinga\Web\Url;
/**
* Display detailed information about a downtime
*/
class Monitoring_DowntimesController extends Controller
{
/**
* The fetched downtimes
*
* @var array
*/
protected $downtimes;
/**
* A filter matching all current downtimes
*
* @var Filter
*/
protected $filter;
/**
* Fetch all downtimes matching the current filter and add tabs
*
* @throws Zend_Controller_Action_Exception
*/
public function init()
{
$this->filter = Filter::fromQueryString(str_replace(
'downtime_id',
'downtime_internal_id',
(string)$this->params
));
$this->downtimes = $this->backend->select()->from('downtime', array(
'id' => 'downtime_internal_id',
'objecttype' => 'downtime_objecttype',
'comment' => 'downtime_comment',
'author_name' => 'downtime_author_name',
'start' => 'downtime_start',
'scheduled_start' => 'downtime_scheduled_start',
'scheduled_end' => 'downtime_scheduled_end',
'end' => 'downtime_end',
'duration' => 'downtime_duration',
'is_flexible' => 'downtime_is_flexible',
'is_fixed' => 'downtime_is_fixed',
'is_in_effect' => 'downtime_is_in_effect',
'entry_time' => 'downtime_entry_time',
'host_state' => 'downtime_host_state',
'service_state' => 'downtime_service_state',
'host_name',
'host',
'service',
'service_description',
'host_display_name',
'service_display_name'
))->addFilter($this->filter)->getQuery()->fetchAll();
if (false === $this->downtimes) {
throw new Zend_Controller_Action_Exception(
$this->translate('Downtime not found')
);
}
$this->getTabs()->add(
'downtimes',
array(
'title' => $this->translate(
'Display detailed information about multiple downtimes.'
),
'icon' => 'plug',
'label' => $this->translate('Downtimes'),
'url' =>'monitoring/downtimes/show'
)
)->activate('downtimes');
foreach ($this->downtimes as $downtime) {
if (isset($downtime->service_description)) {
$downtime->isService = true;
} else {
$downtime->isService = false;
}
if ($downtime->isService) {
$downtime->stateText = Service::getStateText($downtime->service_state);
} else {
$downtime->stateText = Host::getStateText($downtime->host_state);
}
}
}
/**
* Display the detail view for a downtime list
*/
public function showAction()
{
$this->view->downtimes = $this->downtimes;
$this->view->listAllLink = Url::fromPath('monitoring/list/downtimes')
->setQueryString($this->filter->toQueryString());
$this->view->removeAllLink = Url::fromPath('monitoring/downtimes/delete-all')
->setParams($this->params);
}
/**
* Display the form for removing a downtime list
*/
public function deleteAllAction()
{
$this->assertPermission('monitoring/command/downtime/delete');
$this->view->downtimes = $this->downtimes;
$this->view->listAllLink = Url::fromPath('monitoring/list/downtimes')
->setQueryString($this->filter->toQueryString());
$delDowntimeForm = new DeleteDowntimesCommandForm();
$delDowntimeForm->setTitle($this->view->translate('Remove all Downtimes'));
$delDowntimeForm->addDescription(sprintf(
$this->translate('Confirm removal of %d downtimes.'),
count($this->downtimes)
));
$delDowntimeForm->setRedirectUrl(Url::fromPath('monitoring/list/downtimes'));
$delDowntimeForm->setDowntimes($this->downtimes)->handleRequest();
$this->view->delDowntimeForm = $delDowntimeForm;
}
}

View File

@ -1,6 +1,7 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
use Icinga\Exception\MissingParameterException;
use Icinga\Module\Monitoring\Forms\Command\Object\AcknowledgeProblemCommandForm;
use Icinga\Module\Monitoring\Forms\Command\Object\AddCommentCommandForm;
use Icinga\Module\Monitoring\Forms\Command\Object\ProcessCheckResultCommandForm;
@ -26,12 +27,22 @@ class Monitoring_HostController extends MonitoredObjectController
*/
public function init()
{
if ($this->params->get('host') === null) {
throw new MissingParameterException(
$this->translate('Required parameter \'%s\' is missing'),
'host'
);
}
$host = new Host($this->backend, $this->params->get('host'));
$this->applyRestriction('monitoring/hosts/filter', $host);
if ($host->fetch() === false) {
throw new Zend_Controller_Action_Exception($this->translate('Host not found'));
throw new Zend_Controller_Action_Exception(
sprintf($this->translate('Host \'%s\' not found'), $this->params->get('host')),
404
);
}
$this->object = $host;
$this->createTabs();

View File

@ -15,6 +15,7 @@ use Icinga\Module\Monitoring\Object\Host;
use Icinga\Module\Monitoring\Object\HostList;
use Icinga\Web\Url;
use Icinga\Web\Widget\Chart\InlinePie;
use Icinga\Web\Widget\Tabextension\DashboardAction;
class Monitoring_HostsController extends Controller
{
@ -26,7 +27,7 @@ class Monitoring_HostsController extends Controller
public function init()
{
$hostList = new HostList($this->backend);
$hostList->setFilter(Filter::fromQueryString((string) $this->params));
$hostList->setFilter(Filter::fromQueryString((string) $this->params->without('view')));
$this->hostList = $hostList;
}
@ -80,7 +81,7 @@ class Monitoring_HostsController extends Controller
'label' => $this->translate('Hosts'),
'url' => Url::fromRequest()
)
)->activate('show');
)->extend(new DashboardAction())->activate('show');
$this->setAutorefreshInterval(15);
$checkNowForm = new CheckNowCommandForm();
$checkNowForm
@ -123,7 +124,7 @@ class Monitoring_HostsController extends Controller
}
if ((bool) $host->in_downtime === true) {
$objectsInDowntime[] = $host;
$downtimeFilterExpressions[] = Filter::where('downtime_host', $host->getName());
$downtimeFilterExpressions[] = Filter::where('host_name', $host->getName());
}
++$hostStates[$host::getStateText($host->state)];
}

View File

@ -9,7 +9,6 @@ use Icinga\Web\Url;
use Icinga\Web\Widget\Tabextension\DashboardAction;
use Icinga\Web\Widget\Tabextension\OutputFormat;
use Icinga\Web\Widget\Tabs;
use Icinga\Web\Widget\SortBox;
use Icinga\Data\Filter\Filter;
use Icinga\Web\Widget;
use Icinga\Module\Monitoring\Forms\StatehistoryForm;
@ -21,12 +20,8 @@ class Monitoring_ListController extends Controller
*/
public function init()
{
parent::init();
$this->createTabs();
$this->view->compact = $this->_request->getParam('view') === 'compact';
if ($this->_request->getParam('view') === 'inline') {
$this->view->compact = true;
$this->view->inline = true;
}
}
/**
@ -47,25 +42,6 @@ class Monitoring_ListController extends Controller
return $query;
}
protected function hasBetterUrl()
{
$request = $this->getRequest();
$url = Url::fromRequest();
if ($this->getRequest()->isPost()) {
if ($request->getPost('sort')) {
$url->setParam('sort', $request->getPost('sort'));
if ($request->getPost('dir')) {
$url->setParam('dir', $request->getPost('dir'));
} else {
$url->removeParam('dir');
}
return $url;
}
}
return false;
}
/**
* Overwrite the backend to use (used for testing)
*
@ -81,10 +57,6 @@ class Monitoring_ListController extends Controller
*/
public function hostsAction()
{
if ($url = $this->hasBetterUrl()) {
return $this->redirectNow($url);
}
// Handle soft and hard states
if (strtolower($this->params->shift('stateType', 'soft')) === 'hard') {
$stateColumn = 'host_hard_state';
@ -123,19 +95,9 @@ class Monitoring_ListController extends Controller
'host_current_check_attempt',
'host_max_check_attempts'
), $this->extraColumns()));
$this->filterQuery($query);
$this->applyRestriction('monitoring/hosts/filter', $query);
$this->setupSortControl(array(
'host_severity' => $this->translate('Severity'),
'host_state' => $this->translate('Current State'),
'host_display_name' => $this->translate('Hostname'),
'host_address' => $this->translate('Address'),
'host_last_check' => $this->translate('Last Check')
));
$this->view->hosts = $query->paginate();
$this->view->hosts = $query;
$this->view->stats = $this->backend->select()->from('statusSummary', array(
'hosts_total',
@ -148,6 +110,16 @@ class Monitoring_ListController extends Controller
'hosts_unreachable_unhandled',
'hosts_pending',
))->getQuery()->fetchRow();
$this->setupLimitControl();
$this->setupPaginationControl($this->view->hosts);
$this->setupSortControl(array(
'host_severity' => $this->translate('Severity'),
'host_state' => $this->translate('Current State'),
'host_display_name' => $this->translate('Hostname'),
'host_address' => $this->translate('Address'),
'host_last_check' => $this->translate('Last Check')
), $query);
}
/**
@ -155,10 +127,6 @@ class Monitoring_ListController extends Controller
*/
public function servicesAction()
{
if ($url = $this->hasBetterUrl()) {
return $this->redirectNow($url);
}
// Handle soft and hard states
if (strtolower($this->params->shift('stateType', 'soft')) === 'hard') {
$stateColumn = 'service_hard_state';
@ -170,10 +138,8 @@ class Monitoring_ListController extends Controller
$this->addTitleTab('services', $this->translate('Services'), $this->translate('List services'));
$this->view->showHost = true;
if ($host = $this->_getParam('host')) {
if (strpos($host, '*') === false) {
$this->view->showHost = false;
}
if (strpos($this->params->get('host_name', '*'), '*') === false) {
$this->view->showHost = false;
}
$this->setAutorefreshInterval(10);
@ -213,11 +179,12 @@ class Monitoring_ListController extends Controller
'max_check_attempts' => 'service_max_check_attempts'
), $this->extraColumns());
$query = $this->backend->select()->from('serviceStatus', $columns);
$this->filterQuery($query);
$this->applyRestriction('monitoring/services/filter', $query);
$this->view->services = $query;
$this->setupLimitControl();
$this->setupPaginationControl($this->view->services);
$this->setupSortControl(array(
'service_severity' => $this->translate('Service Severity'),
'service_state' => $this->translate('Current Service State'),
@ -228,15 +195,7 @@ class Monitoring_ListController extends Controller
'host_display_name' => $this->translate('Hostname'),
'host_address' => $this->translate('Host Address'),
'host_last_check' => $this->translate('Last Host Check')
));
$limit = $this->params->get('limit');
$this->view->limit = $limit;
if ($limit === 0) {
$this->view->services = $query->getQuery()->fetchAll();
} else {
// TODO: Workaround, paginate should be able to fetch limit from new params
$this->view->services = $query->paginate($this->params->get('limit'));
}
), $query);
$this->view->stats = $this->backend->select()->from('statusSummary', array(
'services_total',
@ -255,7 +214,6 @@ class Monitoring_ListController extends Controller
'services_unknown_handled',
'services_pending',
))->getQuery()->fetchRow();
}
/**
@ -263,16 +221,14 @@ class Monitoring_ListController extends Controller
*/
public function downtimesAction()
{
if ($url = $this->hasBetterUrl()) {
return $this->redirectNow($url);
}
$this->addTitleTab('downtimes', $this->translate('Downtimes'), $this->translate('List downtimes'));
$this->setAutorefreshInterval(12);
$query = $this->backend->select()->from('downtime', array(
'id' => 'downtime_internal_id',
'objecttype' => 'downtime_objecttype',
'comment' => 'downtime_comment',
'author' => 'downtime_author',
'author_name' => 'downtime_author_name',
'start' => 'downtime_start',
'scheduled_start' => 'downtime_scheduled_start',
'scheduled_end' => 'downtime_scheduled_end',
@ -282,16 +238,18 @@ class Monitoring_ListController extends Controller
'is_fixed' => 'downtime_is_fixed',
'is_in_effect' => 'downtime_is_in_effect',
'entry_time' => 'downtime_entry_time',
'host' => 'host_name',
'service' => 'service_description',
'host_state' => 'downtime_host_state',
'service_state' => 'downtime_service_state',
'host_name',
'service_description',
'host_display_name',
'service_display_name'
));
$this->filterQuery($query);
$this->view->downtimes = $query;
$this->setupLimitControl();
$this->setupPaginationControl($this->view->downtimes);
$this->setupSortControl(array(
'downtime_is_in_effect' => $this->translate('Is In Effect'),
'host_display_name' => $this->translate('Host'),
@ -303,12 +261,11 @@ class Monitoring_ListController extends Controller
'downtime_scheduled_start' => $this->translate('Scheduled Start'),
'downtime_scheduled_end' => $this->translate('Scheduled End'),
'downtime_duration' => $this->translate('Duration')
));
$this->view->downtimes = $query->paginate();
), $query);
if ($this->Auth()->hasPermission('monitoring/command/downtime/delete')) {
$this->view->delDowntimeForm = new DeleteDowntimeCommandForm();
$this->view->delDowntimeForm->handleRequest();
}
}
@ -317,38 +274,37 @@ class Monitoring_ListController extends Controller
*/
public function notificationsAction()
{
if ($url = $this->hasBetterUrl()) {
return $this->redirectNow($url);
}
$this->addTitleTab(
'notifications',
$this->translate('Notifications'),
$this->translate('List notifications')
);
$this->setAutorefreshInterval(15);
$query = $this->backend->select()->from('notification', array(
'host',
'service',
'host_name',
'service_description',
'notification_output',
'notification_contact',
'notification_contact_name',
'notification_start_time',
'notification_state',
'host_display_name',
'service_display_name'
));
$this->filterQuery($query);
$this->view->notifications = $query->paginate();
$this->view->notifications = $query;
$this->setupLimitControl();
$this->setupPaginationControl($this->view->notifications);
$this->setupSortControl(array(
'notification_start_time' => $this->translate('Notification Start')
));
), $query);
}
public function contactsAction()
{
if ($url = $this->hasBetterUrl()) {
return $this->redirectNow($url);
}
$this->addTitleTab('contacts', $this->translate('Contacts'), $this->translate('List contacts'));
$query = $this->backend->select()->from('contact', array(
'contact_name',
'contact_id',
@ -370,8 +326,10 @@ class Monitoring_ListController extends Controller
'contact_notify_host_downtime',
));
$this->filterQuery($query);
$this->view->contacts = $query->paginate();
$this->view->contacts = $query;
$this->setupLimitControl();
$this->setupPaginationControl($this->view->contacts);
$this->setupSortControl(array(
'contact_name' => $this->translate('Name'),
'contact_alias' => $this->translate('Alias'),
@ -379,14 +337,11 @@ class Monitoring_ListController extends Controller
'contact_pager' => $this->translate('Pager Address / Number'),
'contact_notify_service_timeperiod' => $this->translate('Service Notification Timeperiod'),
'contact_notify_host_timeperiod' => $this->translate('Host Notification Timeperiod')
));
), $query);
}
public function eventgridAction()
{
if ($url = $this->hasBetterUrl()) {
return $this->redirectNow($url);
}
$this->addTitleTab('eventgrid', $this->translate('Event Grid'), $this->translate('Show the Event Grid'));
$form = new StatehistoryForm();
@ -426,14 +381,12 @@ class Monitoring_ListController extends Controller
public function contactgroupsAction()
{
if ($url = $this->hasBetterUrl()) {
return $this->redirectNow($url);
}
$this->addTitleTab(
'contactgroups',
$this->translate('Contact Groups'),
$this->translate('List contact groups')
);
$query = $this->backend->select()->from('contactgroup', array(
'contactgroup_name',
'contactgroup_alias',
@ -441,7 +394,7 @@ class Monitoring_ListController extends Controller
'contact_alias',
'contact_email',
'contact_pager',
))->order('contactgroup_alias');
));
$this->filterQuery($query);
// Fetch and prepare all contact groups:
@ -458,32 +411,37 @@ class Monitoring_ListController extends Controller
}
// TODO: Find a better naming
$this->view->groupData = $groupData;
$this->setupSortControl(array(
'contactgroup_name' => $this->translate('Contactgroup Name'),
'contactgroup_alias' => $this->translate('Contactgroup Alias')
), $query);
}
public function commentsAction()
{
if ($url = $this->hasBetterUrl()) {
return $this->redirectNow($url);
}
$this->addTitleTab('comments', $this->translate('Comments'), $this->translate('List comments'));
$this->setAutorefreshInterval(12);
$query = $this->backend->select()->from('comment', array(
'id' => 'comment_internal_id',
'objecttype' => 'comment_objecttype',
'comment' => 'comment_data',
'author' => 'comment_author',
'author' => 'comment_author_name',
'timestamp' => 'comment_timestamp',
'type' => 'comment_type',
'persistent' => 'comment_is_persistent',
'expiration' => 'comment_expiration',
'host' => 'comment_host',
'service' => 'comment_service',
'host_name',
'service_description',
'host_display_name',
'service_display_name'
));
$this->filterQuery($query);
$this->view->comments = $query->paginate();
$this->view->comments = $query;
$this->setupLimitControl();
$this->setupPaginationControl($this->view->comments);
$this->setupSortControl(
array(
'comment_timestamp' => $this->translate('Comment Timestamp'),
@ -491,27 +449,27 @@ class Monitoring_ListController extends Controller
'service_display_name' => $this->translate('Service'),
'comment_type' => $this->translate('Comment Type'),
'comment_expiration' => $this->translate('Expiration')
)
),
$query
);
if ($this->Auth()->hasPermission('monitoring/command/comment/delete')) {
$this->view->delCommentForm = new DeleteCommentCommandForm();
$this->view->delCommentForm->handleRequest();
}
}
public function servicegroupsAction()
{
if ($url = $this->hasBetterUrl()) {
return $this->redirectNow($url);
}
$this->addTitleTab(
'servicegroups',
$this->translate('Service Groups'),
$this->translate('List service groups')
);
$this->setAutorefreshInterval(12);
$query = $this->backend->select()->from('groupsummary', array(
'servicegroup',
'servicegroup_name',
'servicegroup_alias',
'hosts_up',
'hosts_unreachable_handled',
@ -540,7 +498,10 @@ class Monitoring_ListController extends Controller
// TODO(el): Can't default to the sort rules of the data view because it's meant for both host groups and
// service groups. We should separate them.
$this->filterQuery($query);
$this->view->servicegroups = $query->paginate();
$this->view->servicegroups = $query;
$this->setupLimitControl();
$this->setupPaginationControl($this->view->servicegroups);
$this->setupSortControl(array(
'services_severity' => $this->translate('Severity'),
'servicegroup_alias' => $this->translate('Service Group Name'),
@ -550,18 +511,16 @@ class Monitoring_ListController extends Controller
'services_critical' => $this->translate('Services CRITICAL'),
'services_warning' => $this->translate('Services WARNING'),
'services_pending' => $this->translate('Services PENDING')
));
), $query);
}
public function hostgroupsAction()
{
if ($url = $this->hasBetterUrl()) {
return $this->redirectNow($url);
}
$this->addTitleTab('hostgroups', $this->translate('Host Groups'), $this->translate('List host groups'));
$this->setAutorefreshInterval(12);
$query = $this->backend->select()->from('groupsummary', array(
'hostgroup',
'hostgroup_name',
'hostgroup_alias',
'hosts_up',
'hosts_unreachable_handled',
@ -569,6 +528,12 @@ class Monitoring_ListController extends Controller
'hosts_down_handled',
'hosts_down_unhandled',
'hosts_pending',
'hosts_up_last_state_change',
'hosts_pending_last_state_change',
'hosts_down_last_state_change_handled',
'hosts_unreachable_last_state_change_handled',
'hosts_down_last_state_change_unhandled',
'hosts_unreachable_last_state_change_unhandled',
'services_ok',
'services_unknown_handled',
'services_unknown_unhandled',
@ -590,7 +555,10 @@ class Monitoring_ListController extends Controller
// TODO(el): Can't default to the sort rules of the data view because it's meant for both host groups and
// service groups. We should separate them.
$this->filterQuery($query);
$this->view->hostgroups = $query->paginate();
$this->view->hostgroups = $query;
$this->setupLimitControl();
$this->setupPaginationControl($this->view->hostgroups);
$this->setupSortControl(array(
'services_severity' => $this->translate('Severity'),
'hostgroup_alias' => $this->translate('Host Group Name'),
@ -600,14 +568,11 @@ class Monitoring_ListController extends Controller
'services_critical' => $this->translate('Services CRITICAL'),
'services_warning' => $this->translate('Services WARNING'),
'services_pending' => $this->translate('Services PENDING')
));
), $query);
}
public function eventhistoryAction()
{
if ($url = $this->hasBetterUrl()) {
return $this->redirectNow($url);
}
$this->addTitleTab(
'eventhistory',
$this->translate('Event Overview'),
@ -625,24 +590,21 @@ class Monitoring_ListController extends Controller
'attempt',
'max_attempts',
'output',
'type',
'host',
'service'
'type'
));
$this->filterQuery($query);
$this->view->history = $query;
$this->setupLimitControl();
$this->setupPaginationControl($this->view->history);
$this->setupSortControl(array(
'timestamp' => $this->translate('Occurence')
));
$this->view->history = $query->paginate();
), $query);
}
public function servicegridAction()
{
if ($url = $this->hasBetterUrl()) {
return $this->redirectNow($url);
}
$this->addTitleTab('servicegrid', $this->translate('Service Grid'), $this->translate('Show the Service Grid'));
$this->setAutorefreshInterval(15);
$query = $this->backend->select()->from('serviceStatus', array(
@ -656,7 +618,7 @@ class Monitoring_ListController extends Controller
$this->setupSortControl(array(
'host_name' => $this->translate('Hostname'),
'service_description' => $this->translate('Service description')
));
), $query);
$pivot = $query->pivot('service_description', 'host_name');
$this->view->pivot = $pivot;
$this->view->horizontalPaginator = $pivot->paginateXAxis();
@ -667,17 +629,17 @@ class Monitoring_ListController extends Controller
{
$editor = Widget::create('filterEditor')
->setQuery($query)
->preserveParams('limit', 'sort', 'dir', 'format', 'view', 'backend', 'stateType', 'addColumns')
->preserveParams(
'limit', 'sort', 'dir', 'format', 'view', 'backend',
'stateType', 'addColumns', '_dev'
)
->ignoreParams('page')
->handleRequest($this->getRequest());
$query->applyFilter($editor->getFilter());
$this->view->filterEditor = $editor;
$this->setupFilterControl($editor);
$this->view->filter = $editor->getFilter();
if ($sort = $this->params->get('sort')) {
$query->order($sort, $this->params->get('dir'));
}
$this->handleFormatRequest($query);
return $query;
}
@ -694,21 +656,6 @@ class Monitoring_ListController extends Controller
return $columns;
}
/**
* Create a sort control box at the 'sortControl' view parameter
*
* @param array $columns An array containing the sort columns, with the
* submit value as the key and the value as the label
*/
private function setupSortControl(array $columns)
{
$this->view->sortControl = new SortBox(
'sortbox-' . $this->getRequest()->getActionName(),
$columns
);
$this->view->sortControl->applyRequest($this->getRequest());
}
protected function addTitleTab($action, $title, $tip)
{
$this->getTabs()->add($action, array(
@ -726,15 +673,6 @@ class Monitoring_ListController extends Controller
*/
private function createTabs()
{
$tabs = $this->getTabs();
if (in_array($this->_request->getActionName(), array(
'hosts',
'services',
'eventhistory',
'eventgrid',
'notifications'
))) {
$tabs->extend(new OutputFormat())->extend(new DashboardAction());
}
$this->getTabs()->extend(new OutputFormat())->extend(new DashboardAction());
}
}

View File

@ -1,6 +1,7 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
use Icinga\Web\Widget\Tabextension\DashboardAction;
use Icinga\Module\Monitoring\Controller;
use Icinga\Module\Monitoring\Forms\Command\Instance\DisableNotificationsExpireCommandForm;
use Icinga\Module\Monitoring\Forms\Command\Instance\ToggleInstanceFeaturesCommandForm;
@ -29,7 +30,7 @@ class Monitoring_ProcessController extends Controller
'label' => $this->translate('Monitoring Health'),
'url' =>'monitoring/process/info'
)
);
)->extend(new DashboardAction());
}
/**
@ -48,8 +49,10 @@ class Monitoring_ProcessController extends Controller
array(
'is_currently_running',
'process_id',
'endpoint_name',
'program_start_time',
'status_update_time',
'program_version',
'last_command_check',
'last_log_rotation',
'global_service_event_handler',

View File

@ -1,6 +1,7 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
use Icinga\Exception\MissingParameterException;
use Icinga\Module\Monitoring\Forms\Command\Object\AcknowledgeProblemCommandForm;
use Icinga\Module\Monitoring\Forms\Command\Object\AddCommentCommandForm;
use Icinga\Module\Monitoring\Forms\Command\Object\ProcessCheckResultCommandForm;
@ -25,12 +26,22 @@ class Monitoring_ServiceController extends MonitoredObjectController
*/
public function init()
{
if ($this->params->get('host') === null || $this->params->get('service') === null) {
throw new MissingParameterException(
$this->translate('One of the required parameters \'%s\' is missing'),
'host or service'
);
}
$service = new Service($this->backend, $this->params->get('host'), $this->params->get('service'));
$this->applyRestriction('monitoring/services/filter', $service);
if ($service->fetch() === false) {
throw new Zend_Controller_Action_Exception($this->translate('Service not found'));
throw new Zend_Controller_Action_Exception(
sprintf($this->translate('Service \'%s\' not found'), $this->params->get('service')),
404
);
}
$this->object = $service;
$this->createTabs();

View File

@ -16,6 +16,7 @@ use Icinga\Module\Monitoring\Object\Service;
use Icinga\Module\Monitoring\Object\ServiceList;
use Icinga\Web\Url;
use Icinga\Web\Widget\Chart\InlinePie;
use Icinga\Web\Widget\Tabextension\DashboardAction;
class Monitoring_ServicesController extends Controller
{
@ -27,7 +28,9 @@ class Monitoring_ServicesController extends Controller
public function init()
{
$serviceList = new ServiceList($this->backend);
$serviceList->setFilter(Filter::fromQueryString((string) $this->params->without('service_problem', 'service_handled')));
$serviceList->setFilter(Filter::fromQueryString(
(string) $this->params->without(array('service_problem', 'service_handled', 'view'))
));
$this->serviceList = $serviceList;
}
@ -101,7 +104,7 @@ class Monitoring_ServicesController extends Controller
'label' => $this->translate('Services'),
'url' => Url::fromRequest()
)
)->activate('show');
)->extend(new DashboardAction())->activate('show');
$this->setAutorefreshInterval(15);
$checkNowForm = new CheckNowCommandForm();
$checkNowForm
@ -158,8 +161,8 @@ class Monitoring_ServicesController extends Controller
if ((bool) $service->in_downtime === true) {
$objectsInDowntime[] = $service;
$downtimeFilterExpressions[] = Filter::matchAll(
Filter::where('downtime_host', $service->getHost()->getName()),
Filter::where('downtime_service', $service->getName())
Filter::where('host_name', $service->getHost()->getName()),
Filter::where('service_description', $service->getName())
);
}
++$serviceStates[$service::getStateText($service->state)];

View File

@ -1,7 +1,6 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
use Icinga\Application\Benchmark;
use Icinga\Module\Monitoring\Object\MonitoredObject;
use Icinga\Web\Hook;
use Icinga\Web\Url;
@ -10,8 +9,6 @@ use Icinga\Web\Widget\Tabextension\OutputFormat;
use Icinga\Web\Widget\Tabextension\DashboardAction;
use Icinga\Module\Monitoring\Backend;
use Icinga\Module\Monitoring\Controller;
use Icinga\Module\Monitoring\Object\Host;
use Icinga\Module\Monitoring\Object\Service;
/**
* Class Monitoring_ShowController
@ -73,9 +70,12 @@ class Monitoring_ShowController extends Controller
{
$this->getTabs()->activate('history');
$this->view->object->fetchEventHistory();
$this->view->history = $this->view->object->eventhistory->getQuery()->paginate($this->params->get('limit', 50));
$this->view->history = $this->view->object->eventhistory;
$this->handleFormatRequest($this->view->object->eventhistory);
$this->fetchHostStats();
$this->setupLimitControl(50);
$this->setupPaginationControl($this->view->history, 50);
}
public function servicesAction()
@ -115,11 +115,11 @@ class Monitoring_ShowController extends Controller
public function contactAction()
{
$contactName = $this->getParam('contact');
$contactName = $this->getParam('contact_name');
if (! $contactName) {
throw new Zend_Controller_Action_Exception(
$this->translate('The parameter `contact\' is required'),
$this->translate('The parameter `contact_name\' is required'),
404
);
}
@ -145,9 +145,7 @@ class Monitoring_ShowController extends Controller
'contact_notify_host_flapping',
'contact_notify_host_downtime',
));
$query->where('contact_name', $contactName);
$contact = $query->getQuery()->fetchRow();
if ($contact) {
@ -156,13 +154,13 @@ class Monitoring_ShowController extends Controller
'command_name'
))->where('contact_id', $contact->contact_id);
$this->view->commands = $commands->paginate();
$this->view->commands = $commands;
$notifications = $this->backend->select()->from('notification', array(
'host',
'service',
'host_name',
'service_description',
'notification_output',
'notification_contact',
'notification_contact_name',
'notification_start_time',
'notification_state',
'host_display_name',
@ -170,9 +168,9 @@ class Monitoring_ShowController extends Controller
));
$notifications->where('contact_object_id', $contact->contact_object_id);
$this->view->compact = true;
$this->view->notifications = $notifications->paginate();
$this->view->notifications = $notifications;
$this->setupLimitControl();
$this->setupPaginationControl($this->view->notifications);
}
$this->view->contact = $contact;

View File

@ -2,6 +2,7 @@
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
use Icinga\Module\Monitoring\Controller as MonitoringController;
use Icinga\Web\Widget\Tabextension\DashboardAction;
use Icinga\Web\Url;
class Monitoring_TacticalController extends MonitoringController
@ -18,7 +19,7 @@ class Monitoring_TacticalController extends MonitoringController
'label' => $this->translate('Tactical Overview'),
'url' => Url::fromRequest()
)
)->activate('tactical_overview');
)->extend(new DashboardAction())->activate('tactical_overview');
$this->view->statusSummary = $this->backend->select()->from(
'statusSummary',

View File

@ -10,6 +10,7 @@ use Icinga\Module\Monitoring\Controller;
use Icinga\Module\Monitoring\Timeline\TimeLine;
use Icinga\Module\Monitoring\Timeline\TimeRange;
use Icinga\Module\Monitoring\Web\Widget\SelectBox;
use Icinga\Web\Widget\Tabextension\DashboardAction;
class Monitoring_TimelineController extends Controller
{
@ -22,7 +23,7 @@ class Monitoring_TimelineController extends Controller
'label' => $this->translate('Timeline'),
'url' => Url::fromRequest()
)
)->activate('timeline');
)->extend(new DashboardAction())->activate('timeline');
$this->view->title = $this->translate('Timeline');
// TODO: filter for hard_states (precedence adjustments necessary!)

View File

@ -215,8 +215,14 @@ class ToggleInstanceFeaturesCommandForm extends CommandForm
->setFeature($feature)
->setEnabled($enabled);
$this->getTransport($this->request)->send($toggleFeature);
if ($this->status->{$feature} != $enabled) {
Notification::success($enabled
? $this->translate('Enabling feature..')
: $this->translate('Disabling feature..')
);
}
}
Notification::success($this->translate('Toggling feature..'));
return true;
}
}

View File

@ -4,12 +4,13 @@
namespace Icinga\Module\Monitoring\Forms\Command\Object;
use Icinga\Module\Monitoring\Command\Object\DeleteCommentCommand;
use Icinga\Module\Monitoring\Forms\Command\CommandForm;
use Icinga\Web\Notification;
/**
* Form for deleting host or service comments
*/
class DeleteCommentCommandForm extends ObjectsCommandForm
class DeleteCommentCommandForm extends CommandForm
{
/**
* (non-PHPDoc)
@ -26,23 +27,34 @@ class DeleteCommentCommandForm extends ObjectsCommandForm
*/
public function createElements(array $formData = array())
{
$this->addElements(array(
$this->addElements(
array(
'hidden',
'comment_id',
array(
'required' => true,
'decorators' => array('ViewHelper')
)
),
array(
'hidden',
'redirect',
'hidden',
'comment_id',
array(
'required' => true,
'validators' => array('NotEmpty'),
'decorators' => array('ViewHelper')
)
),
array(
'decorators' => array('ViewHelper')
'hidden',
'comment_is_service',
array(
'filters' => array('Boolean'),
'decorators' => array('ViewHelper')
)
),
array(
'hidden',
'redirect',
array(
'decorators' => array('ViewHelper')
)
)
)
));
);
return $this;
}
@ -74,14 +86,10 @@ class DeleteCommentCommandForm extends ObjectsCommandForm
*/
public function onSuccess()
{
foreach ($this->objects as $object) {
/** @var \Icinga\Module\Monitoring\Object\MonitoredObject $object */
$delComment = new DeleteCommentCommand();
$delComment
->setObject($object)
->setCommentId($this->getElement('comment_id')->getValue());
$this->getTransport($this->request)->send($delComment);
}
$cmd = new DeleteCommentCommand();
$cmd->setIsService($this->getElement('comment_is_service')->getValue())
->setCommentId($this->getElement('comment_id')->getValue());
$this->getTransport($this->request)->send($cmd);
$redirect = $this->getElement('redirect')->getValue();
if (! empty($redirect)) {
$this->setRedirectUrl($redirect);

View File

@ -0,0 +1,88 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Monitoring\Forms\Command\Object;
use Icinga\Module\Monitoring\Command\Object\DeleteCommentCommand;
use \Icinga\Module\Monitoring\Forms\Command\CommandForm;
use Icinga\Web\Notification;
/**
* Form for deleting host or service comments
*/
class DeleteCommentsCommandForm extends CommandForm
{
/**
* The comments deleted on success
*
* @var array
*/
protected $comments;
/**
* (non-PHPDoc)
* @see \Zend_Form::init() For the method documentation.
*/
public function init()
{
$this->setAttrib('class', 'inline');
}
/**
* (non-PHPDoc)
* @see \Icinga\Web\Form::createElements() For the method documentation.
*/
public function createElements(array $formData = array())
{
$this->addElements(array(
array(
'hidden',
'redirect',
array('decorators' => array('ViewHelper'))
)
));
return $this;
}
/**
* (non-PHPDoc)
* @see \Icinga\Web\Form::getSubmitLabel() For the method documentation.
*/
public function getSubmitLabel()
{
return $this->translatePlural('Remove', 'Remove All', count($this->downtimes));
}
/**
* (non-PHPDoc)
* @see \Icinga\Web\Form::onSuccess() For the method documentation.
*/
public function onSuccess()
{
foreach ($this->comments as $comment) {
$cmd = new DeleteCommentCommand();
$cmd->setCommentId($comment->id)
->setIsService(isset($comment->service_description));
$this->getTransport($this->request)->send($cmd);
}
$redirect = $this->getElement('redirect')->getValue();
if (! empty($redirect)) {
$this->setRedirectUrl($redirect);
}
Notification::success($this->translate('Deleting comment..'));
return true;
}
/**
* Set the comments to be deleted upon success
*
* @param array $comments
*
* @return this fluent interface
*/
public function setComments(array $comments)
{
$this->comments = $comments;
return $this;
}
}

View File

@ -4,12 +4,13 @@
namespace Icinga\Module\Monitoring\Forms\Command\Object;
use Icinga\Module\Monitoring\Command\Object\DeleteDowntimeCommand;
use \Icinga\Module\Monitoring\Forms\Command\CommandForm;
use Icinga\Web\Notification;
/**
* Form for deleting host or service downtimes
*/
class DeleteDowntimeCommandForm extends ObjectsCommandForm
class DeleteDowntimeCommandForm extends CommandForm
{
/**
* (non-PHPDoc)
@ -19,33 +20,44 @@ class DeleteDowntimeCommandForm extends ObjectsCommandForm
{
$this->setAttrib('class', 'inline');
}
/**
* (non-PHPDoc)
* @see \Icinga\Web\Form::createElements() For the method documentation.
*/
public function createElements(array $formData = array())
{
$this->addElements(array(
$this->addElements(
array(
'hidden',
'downtime_id',
array(
'required' => true,
'decorators' => array('ViewHelper')
)
),
array(
'hidden',
'redirect',
'hidden',
'downtime_id',
array(
'required' => true,
'validators' => array('NotEmpty'),
'decorators' => array('ViewHelper')
)
),
array(
'decorators' => array('ViewHelper')
'hidden',
'downtime_is_service',
array(
'filters' => array('Boolean'),
'decorators' => array('ViewHelper')
)
),
array(
'hidden',
'redirect',
array(
'decorators' => array('ViewHelper')
)
)
)
));
);
return $this;
}
/**
* (non-PHPDoc)
* @see \Icinga\Web\Form::addSubmitButton() For the method documentation.
@ -67,26 +79,23 @@ class DeleteDowntimeCommandForm extends ObjectsCommandForm
);
return $this;
}
/**
* (non-PHPDoc)
* @see \Icinga\Web\Form::onSuccess() For the method documentation.
* @see \Icinga\Web\Form::onSuccess() For the method documentation.
*/
public function onSuccess()
{
foreach ($this->objects as $object) {
/** @var \Icinga\Module\Monitoring\Object\MonitoredObject $object */
$delDowntime = new DeleteDowntimeCommand();
$delDowntime
->setObject($object)
->setDowntimeId($this->getElement('downtime_id')->getValue());
$this->getTransport($this->request)->send($delDowntime);
}
$cmd = new DeleteDowntimeCommand();
$cmd->setDowntimeId($this->getElement('downtime_id')->getValue());
$cmd->setIsService($this->getElement('downtime_is_service')->getValue());
$this->getTransport($this->request)->send($cmd);
$redirect = $this->getElement('redirect')->getValue();
if (! empty($redirect)) {
$this->setRedirectUrl($redirect);
}
Notification::success($this->translate('Deleting downtime..'));
Notification::success($this->translate('Deleting downtime.'));
return true;
}
}

View File

@ -0,0 +1,88 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Monitoring\Forms\Command\Object;
use Icinga\Module\Monitoring\Command\Object\DeleteDowntimeCommand;
use \Icinga\Module\Monitoring\Forms\Command\CommandForm;
use Icinga\Web\Notification;
/**
* Form for deleting host or service downtimes
*/
class DeleteDowntimesCommandForm extends CommandForm
{
/**
* The downtimes to delete on success
*
* @var array
*/
protected $downtimes;
/**
* (non-PHPDoc)
* @see \Zend_Form::init() For the method documentation.
*/
public function init()
{
$this->setAttrib('class', 'inline');
}
/**
* (non-PHPDoc)
* @see \Icinga\Web\Form::createElements() For the method documentation.
*/
public function createElements(array $formData = array())
{
$this->addElements(array(
array(
'hidden',
'redirect',
array('decorators' => array('ViewHelper'))
)
));
return $this;
}
/**
* (non-PHPDoc)
* @see \Icinga\Web\Form::getSubmitLabel() For the method documentation.
*/
public function getSubmitLabel()
{
return $this->translatePlural('Remove', 'Remove All', count($this->downtimes));
}
/**
* (non-PHPDoc)
* @see \Icinga\Web\Form::onSuccess() For the method documentation.
*/
public function onSuccess()
{
foreach ($this->downtimes as $downtime) {
$delDowntime = new DeleteDowntimeCommand();
$delDowntime->setDowntimeId($downtime->id);
$delDowntime->setIsService(isset($downtime->service_description));
$this->getTransport($this->request)->send($delDowntime);
}
$redirect = $this->getElement('redirect')->getValue();
if (! empty($redirect)) {
$this->setRedirectUrl($redirect);
}
Notification::success($this->translate('Deleting downtime.'));
return true;
}
/**
* Set the downtimes to be deleted upon success
*
* @param type $downtimes
*
* @return $this
*/
public function setDowntimes(array $downtimes)
{
$this->downtimes = $downtimes;
return $this;
}
}

View File

@ -17,29 +17,20 @@ class SendCustomNotificationCommandForm extends ObjectsCommandForm
public function init()
{
$this->addDescription(
$this->translate(
'This command is used to send custom notifications for hosts or'
. ' services.'
)
$this->translate('This command is used to send custom notifications about hosts or services.')
);
}
/**
* (non-PHPDoc)
* @see \Icinga\Web\Form::getSubmitLabel() For the method documentation.
* {@inheritdoc}
*/
public function getSubmitLabel()
{
return $this->translatePlural(
'Send custom notification',
'Send custom notifications',
count($this->objects)
);
return $this->translatePlural('Send custom notification', 'Send custom notifications', count($this->objects));
}
/**
* (non-PHPDoc)
* @see \Icinga\Web\Form::createElements() For the method documentation.
* {@inheritdoc}
*/
public function createElements(array $formData = array())
{
@ -64,9 +55,8 @@ class SendCustomNotificationCommandForm extends ObjectsCommandForm
'label' => $this->translate('Forced'),
'value' => false,
'description' => $this->translate(
'If you check this option, a notification is sent'
. 'regardless of the current time and whether'
. ' notifications are enabled.'
'If you check this option, the notification is sent out regardless of time restrictions and'
. ' whether or not notifications are enabled.'
)
)
),
@ -77,8 +67,7 @@ class SendCustomNotificationCommandForm extends ObjectsCommandForm
'label' => $this->translate('Broadcast'),
'value' => false,
'description' => $this->translate(
'If you check this option, a notification is sent to'
. ' all normal and escalated contacts.'
'If you check this option, the notification is sent out to all normal and escalated contacts.'
)
)
)
@ -87,24 +76,24 @@ class SendCustomNotificationCommandForm extends ObjectsCommandForm
}
/**
* (non-PHPDoc)
* @see \Icinga\Web\Form::onSuccess() For the method documentation.
* {@inheritdoc}
*/
public function onSuccess()
{
foreach ($this->objects as $object) {
/** @var \Icinga\Module\Monitoring\Object\MonitoredObject $object */
$comment = new SendCustomNotificationCommand();
$comment->setObject($object);
$comment->setComment($this->getElement('comment')->getValue());
$comment->setAuthor($this->request->getUser()->getUsername());
$comment->setForced($this->getElement('forced')->isChecked());
$comment->setBroadcast($this->getElement('broadcast')->isChecked());
$this->getTransport($this->request)->send($comment);
$notification = new SendCustomNotificationCommand();
$notification
->setObject($object)
->setComment($this->getElement('comment')->getValue())
->setAuthor($this->request->getUser()->getUsername())
->setForced($this->getElement('forced')->isChecked())
->setBroadcast($this->getElement('broadcast')->isChecked());
$this->getTransport($this->request)->send($notification);
}
Notification::success($this->translatePlural(
'Send custom notification..',
'Send custom notifications..',
'Sending custom notification..',
'Sending custom notifications..',
count($this->objects)
));
return true;

View File

@ -30,7 +30,7 @@ class ToggleObjectFeaturesCommandForm extends ObjectsCommandForm
*/
public function createElements(array $formData = array())
{
$toggleDisabled = $this->hasPermission('monitoring/command/feature/instance') ? null : '';
$toggleDisabled = $this->hasPermission('monitoring/command/feature/object') ? null : '';
$this->addElements(array(
array(
'checkbox',

View File

@ -3,6 +3,10 @@
namespace Icinga\Module\Monitoring\Forms\Config;
use Exception;
use Icinga\Data\ConfigObject;
use Icinga\Data\ResourceFactory;
use Icinga\Web\Form;
use InvalidArgumentException;
use Icinga\Application\Config;
use Icinga\Exception\ConfigurationError;
@ -271,4 +275,63 @@ class BackendConfigForm extends ConfigForm
)
);
}
/**
* Validate the ido instance schema resource
*
* @param Form $form
* @param ConfigObject $resourceConfig
*
* @return bool Whether validation succeeded or not
*/
public static function isValidIdoSchema(Form $form, ConfigObject $resourceConfig)
{
try {
$resource = ResourceFactory::createResource($resourceConfig);
$result = $resource->select()->from('icinga_dbversion', array('version'));
$result->fetchOne();
} catch (Exception $e) {
$form->addError(
$form->translate(
'IDO schema validation failed, it looks like that the IDO schema is missing in the given database.'
)
);
return false;
}
return true;
}
/**
* Validate the ido instance availability
*
* @param Form $form
* @param ConfigObject $resourceConfig
*
* @return bool Whether validation succeeded or not
*/
public static function isValidIdoInstance(Form $form, ConfigObject $resourceConfig)
{
$resource = ResourceFactory::createResource($resourceConfig);
$result = $resource->select()->from('icinga_instances', array('instance_name'));
$instances = $result->fetchAll();
if (count($instances) === 1) {
return true;
} elseif (count($instances) > 1) {
$form->warning(
$form->translate(
'IDO instance validation failed, because there are multiple instances available.'
)
);
return false;
}
$form->error(
$form->translate(
'IDO instance validation failed, because there is no IDO instance available.'
)
);
return false;
}
}

View File

@ -3,6 +3,8 @@
namespace Icinga\Module\Monitoring\Forms\Setup;
use Icinga\Data\ConfigObject;
use Icinga\Module\Monitoring\Forms\Config\BackendConfigForm;
use Icinga\Web\Form;
use Icinga\Forms\Config\Resource\DbResourceForm;
@ -53,8 +55,21 @@ class IdoResourcePage extends Form
}
if (false === isset($data['skip_validation']) || $data['skip_validation'] == 0) {
if (false === DbResourceForm::isValidResource($this)) {
$this->addSkipValidationCheckbox();
$configObject = new ConfigObject($this->getValues());
if (false === DbResourceForm::isValidResource($this, $configObject)) {
$this->addSkipValidationCheckbox($this->translate(
'Check this to not to validate connectivity with the given database server'
));
return false;
} elseif (false === BackendConfigForm::isValidIdoSchema($this, $configObject)) {
$this->addSkipValidationCheckbox($this->translate(
'Check this to not to validate the ido schema'
));
return false;
} elseif (false === BackendConfigForm::isValidIdoInstance($this, $configObject)) {
$this->addSkipValidationCheckbox($this->translate(
'Check this to not to validate the ido instance'
));
return false;
}
}
@ -65,17 +80,21 @@ class IdoResourcePage extends Form
/**
* Add a checkbox to the form by which the user can skip the connection validation
*/
protected function addSkipValidationCheckbox()
protected function addSkipValidationCheckbox($description = '')
{
if (empty($description)) {
$description = $this->translate(
'Proceed without any further (custom) validation'
);
}
$this->addElement(
'checkbox',
'skip_validation',
array(
'required' => true,
'label' => $this->translate('Skip Validation'),
'description' => $this->translate(
'Check this to not to validate connectivity with the given database server'
)
'description' => $description
)
);
}

View File

@ -15,8 +15,12 @@ class Zend_View_Helper_Customvar extends Zend_View_Helper_Abstract
public function customvar($struct)
{
if (is_string($struct) || is_int($struct) || is_float($struct)) {
return $this->view->escape((string) $struct);
if (is_scalar($struct)) {
return $this->view->escape(
is_string($struct)
? $struct
: var_export($struct, true)
);
} elseif (is_array($struct)) {
return $this->renderArray($struct);
} elseif (is_object($struct)) {
@ -38,7 +42,7 @@ class Zend_View_Helper_Customvar extends Zend_View_Helper_Abstract
protected function renderObject($object)
{
if (empty($object)) {
if (0 === count((array) $object)) {
return '{}';
}
$out = "{<ul>\n";

View File

@ -1,12 +1,13 @@
<?php if (! $this->compact): ?>
<div class="controls">
<?= $this->tabs ?>
<div style="margin: 1em;" class="dontprint">
<?= $this->tabs; ?>
<div style="float: right;" class="dontprint">
<?= $intervalBox; ?>
</div>
<?= $this->widget('limiter') ?>
<?= $this->paginationControl($notifications, null, null, array('preserve' => $this->preserve)) ?>
<?= $this->limiter; ?>
<?= $this->paginator; ?>
</div>
<?php endif ?>
<div class="content alertsummary">
<!-- <h1><?= $this->translate('Alert summary'); ?></h1> -->
@ -59,8 +60,7 @@
<div class="alertsummary-flex">
<?= $this->partial('list/notifications.phtml', array(
'notifications' => $this->recentAlerts,
'compact' => true,
'inline' => true
'compact' => true
)); ?>
</div>
</div>
@ -71,8 +71,7 @@
<div class="alertsummary-flex">
<?= $this->partial('list/notifications.phtml', array(
'notifications' => $this->notifications,
'compact' => true,
'inline' => true
'compact' => true
)); ?>
</div>
</div>

View File

@ -0,0 +1,11 @@
<div class="controls">
<?php if (! $this->compact): ?>
<?= $this->tabs; ?>
<?php endif ?>
<?= $this->render('partials/downtime/downtime-header.phtml'); ?>
</div>
<div class="content object-command">
<?= $delDowntimeForm; ?>
</div>

View File

@ -0,0 +1,81 @@
<div class="controls">
<?php if (! $this->compact): ?>
<?= $this->tabs; ?>
<?php endif ?>
<div data-base-target='_next'>
<?= $this->render('partials/comment/comment-header.phtml'); ?>
</div>
</div>
<div class="content">
<h3><?= $this->translate('Comment detail information') ?></h3>
<table class="avp">
<tbody>
<tr data-base-target='_next'>
<?php if ($this->comment->objecttype === 'service'): ?>
<th> <?= $this->translate('Service') ?> </th>
<td>
<?= $this->icon('service', $this->translate('Service')); ?>
<?= $this->link()->service(
$this->comment->service_description,
$this->comment->service_display_name,
$this->comment->host_name,
$this->comment->host_display_name
);
?>
</td>
<?php else: ?>
<th> <?= $this->translate('Host') ?> </th>
<td>
<?= $this->icon('host', $this->translate('Host')); ?>
<?= $this->link()->host(
$this->comment->host_name,
$this->comment->host_display_name
);
?>
</td>
<?php endif ?>
</tr>
<tr>
<th><?= $this->translate('Author') ?></th>
<td><?= $this->icon('user', $this->translate('User')) ?> <?= $this->escape($this->comment->author) ?></td>
</tr>
<tr>
<th><?= $this->translate('Persistent') ?></th>
<td><?= $this->escape($this->comment->persistent) ? $this->translate('Yes') : $this->translate('No') ?></td>
</tr>
<tr>
<th><?= $this->translate('Created') ?></th>
<td><?= date('d.m.y H:i' ,$this->escape($this->comment->timestamp)) ?></td>
</tr>
<tr>
<th><?= $this->translate('Expires') ?></th>
<td>
<?= $this->comment->expiration ? sprintf(
$this->translate('This comment expires on %s at %s.'),
date('d.m.y', $this->comment->expiration),
date('H:i', $this->comment->expiration)
) : $this->translate('This comment does not expire.');
?>
</td>
</tr>
<?php if (isset($delCommentForm)): // Form is unset if the current user lacks the respective permission ?>
<tr class="newsection">
<th><?= $this->translate('Commands') ?></th>
<td>
<?= $delCommentForm ?>
</td>
</tr>
<?php endif ?>
</tbody>
</table>
</div>

View File

@ -0,0 +1,12 @@
<div class="controls">
<?php if (! $this->compact): ?>
<?= $this->tabs; ?>
<?php endif ?>
<?= $this->render('partials/comment/comments-header.phtml'); ?>
</div>
<div class="content object-command">
<?= $delCommentForm ?>
</div>

View File

@ -0,0 +1,34 @@
<div class="controls">
<?php if (! $this->compact): ?>
<?= $this->tabs; ?>
<?php endif ?>
<div data-base-target='_next'>
<?= $this->render('partials/comment/comments-header.phtml'); ?>
</div>
</div>
<div class="content">
<h3><?= $this->icon('reschedule') ?> <?= $this->translate('Commands') ?> </h3>
<p>
<?= sprintf(
$this->translate('Issue commands to all %s selected comments.'),
'<b>' . count($comments) . '</b>'
)
?>
<div>
<?= $this->qlink(
sprintf(
$this->translate('Remove all %d scheduled comments'),
count($comments)
),
$removeAllLink,
null,
array(
'icon' => 'trash',
'title' => $this->translate('Remove all selected comments.')
)
) ?>
</div>
</p>
</div>

View File

@ -0,0 +1,11 @@
<div class="controls">
<?php if (! $this->compact): ?>
<?= $this->tabs; ?>
<?php endif ?>
<?= $this->render('partials/downtime/downtime-header.phtml'); ?>
</div>
<div class="content object-command">
<?= $delDowntimeForm; ?>
</div>

View File

@ -0,0 +1,121 @@
<div class="controls">
<?php if (! $this->compact): ?>
<?= $this->tabs; ?>
<?php endif ?>
<?= $this->render('partials/downtime/downtime-header.phtml'); ?>
</div>
<div class="content">
<h3><?= $this->translate('Downtime detail information') ?></h3>
<table class="avp">
<tbody>
<tr>
<th>
<?= $this->isService ? $this->translate('Service') : $this->translate('Host') ?>
</th>
<td data-base-target="_next">
<?php if ($this->isService): ?>
<?php
$link = $this->link()->service(
$downtime->service_description,
$downtime->service_display_name,
$downtime->host_name,
$downtime->host_display_name
);
$icon = $this->icon('service', $this->translate('Service'));
?>
<?php else: ?>
<?php
$icon = $this->icon('host', $this->translate('Host'));
$link = $this->link()->host($downtime->host_name, $downtime->host_display_name)
?>
<?php endif ?>
<?= $icon ?>
<?= $link ?>
</td>
</tr>
<tr title="<?= $this->translate('The name of the person who scheduled this downtime'); ?>">
<th><?= $this->translate('Author') ?></th>
<td><?= $this->icon('user', $this->translate('User')) ?> <?= $this->escape($this->downtime->author_name) ?></td>
</tr>
<tr title="<?= $this->translate('A comment, as entered by the author, associated with the scheduled downtime'); ?>">
<th><?= $this->translate('Comment') ?></th>
<td><?= $this->icon('comment', $this->translate('Comment')) ?> <?= $this->escape($this->downtime->comment) ?></td>
</tr>
<tr title="<?= $this->translate('Date and time this downtime was entered'); ?>">
<th><?= $this->translate('Entry Time') ?></th>
<td> <?= date('d.m.y H:i' ,$this->escape($this->downtime->entry_time)) ?></td>
</tr>
<tr class="newsection">
<th><?= $this->escape(
$this->downtime->is_flexible ?
$this->translate('Flexible') : $this->translate('Fixed')
); ?></th>
<td>
<?= $this->escape(
$this->downtime->is_flexible ?
$this->translate('Flexible downtimes have a hard start and end time,'
. ' but also an additional restriction on the duration in which '
. ' the host or service may actually be down.') :
$this->translate('Fixed downtimes have a static start and end time.')
); ?>
</td>
</tr>
<tr title="<?= $this->translate('The date/time the scheduled downtime is'
. ' supposed to start. If this is a flexible (non-fixed) downtime, '
. 'this refers to the earliest possible time that the downtime'
. ' can start'); ?>">
<th><?= $this->translate('Scheduled start') ?></th>
<td><?= date('d.m.y H:i', $this->downtime->scheduled_start) ?></td>
</tr>
<tr title="<?= $this->translate('The date/time the scheduled downtime is '
. 'supposed to end. If this is a flexible (non-fixed) downtime, '
. 'this refers to the last possible time that the downtime can '
. 'start'); ?>">
<th><?= $this->translate('Scheduled end') ?></th>
<td><?= date('d.m.y H:i', $this->downtime->scheduled_end) ?></td>
</tr>
<?php if ($this->downtime->is_flexible): ?>
<tr title="<?= $this->translate('Indicates the number of seconds that the '
. 'scheduled downtime should last. This is usually only needed if'
. ' this is a flexible downtime, which can start at a variable '
. 'time, but lasts for the specified duration'); ?>">
<th tit><?= $this->translate('Duration') ?></th>
<td><?= $this->format()->duration($this->escape($this->downtime->duration)); ?></td>
</tr>
<tr title="<?= $this->translate('he date/time the scheduled downtime was'
. ' actually started'); ?>">
<th><?= $this->translate('Actual start time') ?></th>
<td><?= date('d.m.y H:i', $downtime->start); ?></td>
</tr>
<tr title="<?= $this->translate('The date/time the scheduled downtime '
. 'actually ended'); ?>">
<th><?= $this->translate('Actual end time') ?></th>
<td><?= date('d.m.y H:i', $downtime->end); ?></td>
</tr>
<?php endif; ?>
<tr class="newsection">
<th><?= $this->translate('In effect') ?></th>
<td>
<?= $this->escape(
$this->downtime->is_in_effect ?
$this->translate('Yes') : $this->translate('No')
);
?>
</td>
</tr>
<?php if (isset($delDowntimeForm)): // Form is unset if the current user lacks the respective permission ?>
<tr class="newsection">
<th><?= $this->translate('Commands') ?></th>
<td>
<?= $delDowntimeForm ?>
</td>
</tr>
<?php endif ?>
</tbody>
</table>
</div>

View File

@ -0,0 +1,12 @@
<div class="controls">
<?php if (! $this->compact): ?>
<?= $this->tabs; ?>
<?php endif ?>
<?= $this->render('partials/downtime/downtimes-header.phtml'); ?>
</div>
<div class="content object-command">
<?= $delDowntimeForm ?>
</div>

View File

@ -0,0 +1,33 @@
<div class="controls">
<?php if (! $this->compact): ?>
<?= $this->tabs; ?>
<?php endif ?>
<?= $this->render('partials/downtime/downtimes-header.phtml'); ?>
</p>
</div>
<div class="content">
<h3><?= $this->icon('reschedule') ?> <?= $this->translate('Commands') ?> </h3>
<p>
<?= sprintf(
$this->translate('Issue commands to all %s selected downtimes.'),
'<b>' . count($downtimes) . '</b>'
)
?>
<div>
<?= $this->qlink(
sprintf(
$this->translate('Remove all %d scheduled downtimes'),
count($downtimes)
),
$removeAllLink,
null,
array(
'icon' => 'trash',
'title' => $this->translate('Remove all selected downtimes.')
)
) ?>
</div>
</p>
</div>

View File

@ -1,4 +1,7 @@
<div class="controls">
<?php if (! $this->compact): ?>
<?= $this->tabs; ?>
<?php endif ?>
<?= $this->render('partials/host/object-header.phtml') ?>
<?= $this->render('partials/host/servicesummary.phtml') ?>
</div>

View File

@ -1,9 +1,12 @@
<div class="controls">
<?php if (! $this->compact): ?>
<?= $tabs; ?>
<?php endif ?>
<?= $this->render('partials/host/objects-header.phtml'); ?>
</div>
<div class="content">
<?php if (($hostCount = count($objects)) === 0): ?>
<?= $this->translate('No hosts matching the filter'); ?>
<?= $this->translate('No hosts found matching the filter'); ?>
<?php else: ?>
<h3><?= sprintf($this->translatePlural('%u Host', '%u Hosts', $hostCount), $hostCount); ?></h3>
<div><?= $this->qlink(

View File

@ -1,66 +1,70 @@
<?php if (false === $this->compact): ?>
<?php if (! $this->compact): ?>
<div class="controls">
<?= $this->tabs->render($this); ?>
<div style="margin: 1em" class="dontprint">
<?= $this->translate('Sort by'); ?> <?= $this->sortControl->render($this); ?>
<?= $this->tabs; ?>
<div class="dontprint">
<?= $this->render('list/components/selectioninfo.phtml'); ?>
</div>
<?= $this->widget('limiter', array('url' => $this->url, 'max' => $comments->count())); ?>
<?= $this->paginationControl($comments, null, null, array('preserve' => $this->preserve)); ?>
<div class="tinystatesummary">
<?= count($comments) ?> <?= $this->translate('Comments') ?>:
</div>
<?= $this->sortBox; ?>
<?= $this->limiter; ?>
<?= $this->paginator; ?>
<?= $this->filterEditor; ?>
</div>
<?php endif ?>
<div class="content">
<?php if (count($comments) === 0): ?>
<?= $this->translate('No comments matching the filter'); ?>
</div>
<?php return; endif ?>
<?php
<table data-base-target="_next" class="action comments">
if (count($comments) === 0) {
echo $this->translate('No comments found matching the filter') . '</div>';
return;
}
?>
<table data-base-target="_next"
class="action comments multiselect"
data-icinga-multiselect-url="/icingaweb2/monitoring/comments/show"
data-icinga-multiselect-data="comment_id">
<tbody>
<?php foreach ($comments as $comment): ?>
<?php
switch ($comment->type) {
case 'flapping':
$icon = 'flapping';
$title = $this->translate('Flapping');
$tooltip = $this->translate('Comment was caused by a flapping host or service.');
break;
case 'comment':
$icon = 'user';
$title = $this->translate('User Comment');
$tooltip = $this->translate('Comment was created by an user.');
break;
case 'downtime':
$icon = 'plug';
$title = $this->translate('Downtime');
$tooltip = $this->translate('Comment was caused by a downtime.');
case 'ack':
$icon = 'ok';
$title = $this->translate('Acknowledgement');
$tooltip = $this->translate('Comment was caused by an acknowledgement.');
}
?>
<?php foreach ($comments as $comment):
$this->comment = $comment; ?>
<tr class="state invalid">
<td class="state" style="width: 12em;">
<?= $this->icon($icon, $tooltip) ?>
<br>
<strong><?= $this->escape($title); ?></strong>
<br>
<?= $this->prefixedTimeSince($comment->timestamp); ?>
<?= $this->render('partials/comment/comment-description.phtml'); ?>
</td>
<td>
<?php if ($comment->objecttype === 'service'): ?>
<?= $this->icon('service', $this->translate('Service')); ?>
<?= $this->link()->service(
$comment->service, $comment->service_display_name, $comment->host, $comment->host_display_name
) ?>
<?= $this->qlink(
sprintf(
$this->translate('%s on %s', 'Service running on host'),
$comment->service_display_name,
$comment->host_display_name
),
'monitoring/comment/show',
array('comment_id' => $comment->id),
array('title' => sprintf(
$this->translate('Show detailed information for comment on %s for %s'),
$comment->service_display_name,
$comment->host_display_name
))) ?>
<?php else: ?>
<?= $this->icon('host', $this->translate('Host')); ?>
<?= $this->link()->host($comment->host, $comment->host_display_name) ?>
<?= $this->qlink(
$comment->host_display_name,
'monitoring/comment/show',
array('comment_id' => $comment->id),
array('title' => sprintf(
$this->translate('Show detailed information for comment on %s'),
$comment->host_display_name
))) ?>
<?php endif ?>
<br>
<?= $this->icon('comment', $this->translate('Comment')); ?> <?= isset($comment->author)
? '[' . $comment->author . '] '
? '[' . $this->escape($comment->author) . '] '
: '';
?><?= $this->escape($comment->comment); ?>
<br>
@ -79,12 +83,12 @@
<td style="width: 2em" data-base-target="self">
<?php
$delCommentForm = clone $delCommentForm;
$delCommentForm->populate(array('comment_id' => $comment->id, 'redirect' => $this->url));
if ($comment->objecttype === 'host') {
$delCommentForm->setAction($this->url('monitoring/host/delete-comment', array('host' => $comment->host)));
} else {
$delCommentForm->setAction($this->url('monitoring/service/delete-comment', array('host' => $comment->host, 'service' => $comment->service)));
}
$delCommentForm->populate(
array(
'comment_id' => $comment->id,
'comment_is_service' => isset($comment->service_description)
)
);
echo $delCommentForm;
?>
</td>

View File

@ -1,17 +1,22 @@
<?php if (!$this->compact): ?>
<?php if (! $this->compact): ?>
<div class="controls">
<?= $this->tabs ?>
<?= $this->tabs; ?>
<?= $this->sortBox; ?>
<?= $this->limiter; ?>
<?= $this->paginator; ?>
<?= $this->filterEditor; ?>
</div>
<?php endif ?>
<div class="content">
<div class="boxview" data-base-target="_next">
<?php
if (count($groupData) === 0) {
echo mt('monitoring', 'No contacts matching the filter');
}
foreach ($groupData as $groupName => $groupInfo): ?>
if (count($groupData) === 0) {
echo $this->translate('No contactgroups found matching the filter') . '</div>';
return;
}
?>
<div class="boxview" data-base-target="_next">
<?php foreach ($groupData as $groupName => $groupInfo): ?>
<div class="box contactgroup">
<h2><?= $groupInfo['alias']; ?></h2>
<?php if ($groupInfo['alias'] !== $groupName): ?>
@ -24,7 +29,7 @@ foreach ($groupData as $groupName => $groupInfo): ?>
<?= $this->qlink(
$c->contact_alias,
'monitoring/show/contact',
array('contact' => $c->contact_name),
array('contact_name' => $c->contact_name),
array('title' => sprintf(
$this->translate('Show detailed information about %s'),
$c->contact_alias

View File

@ -1,24 +1,27 @@
<?php if (! $this->compact): ?>
<div class="controls">
<?= $this->tabs ?>
<div style="margin: 1em">
<?= $this->sortControl->render($this); ?>
</div>
<?= $this->paginationControl($contacts, null, null, array('preserve' => $this->preserve)); ?>
<?= $this->tabs; ?>
<?= $this->sortBox; ?>
<?= $this->limiter; ?>
<?= $this->paginator; ?>
<?= $this->filterEditor; ?>
</div>
<?php endif ?>
<div data-base-target="_next" class="content contacts">
<?php
if (count($contacts) === 0) {
echo $this->translate('No contacts matching the filter');
return;
}
foreach ($contacts as $contact): ?>
<?php
if (count($contacts) === 0) {
echo $this->translate('No contacts found matching the filter') . '</div>';
return;
}
?>
<?php foreach ($contacts as $contact): ?>
<div class="contact">
<?= $this->img('/static/gravatar', array('email' => $contact->contact_email)); ?>
<strong><?= $this->qlink(
$contact->contact_name,
'monitoring/show/contact',
array('contact' => $contact->contact_name),
array('contact_name' => $contact->contact_name),
array('title' => sprintf(
$this->translate('Show detailed information about %s'),
$contact->contact_alias

View File

@ -1,36 +1,39 @@
<?php
use Icinga\Module\Monitoring\Object\Host;
use Icinga\Module\Monitoring\Object\Service;
?>
<?php if (false === $this->compact): ?>
if (! $this->compact): ?>
<div class="controls">
<?= $this->tabs->render($this); ?>
<div style="margin: 1em" class="dontprint">
<?= $this->translate('Sort by'); ?> <?= $this->sortControl->render($this); ?>
<?php if (! $this->filterEditor): ?>
<?= $this->filterPreview ?>
<?php endif; ?>
</div>
<?= $this->widget('limiter', array('url' => $this->url, 'max' => $downtimes->count())); ?>
<?= $this->paginationControl($downtimes, null, null, array('preserve' => $this->preserve)); ?>
<?= $this->tabs; ?>
<div class="dontprint">
<?= $this->render('list/components/selectioninfo.phtml'); ?>
</div>
<div class="tinystatesummary">
<?= count($downtimes) ?> <?= $this->translate('Downtimes') ?>
</div>
<?= $this->sortBox; ?>
<?= $this->limiter; ?>
<?= $this->paginator; ?>
<?= $this->filterEditor; ?>
</div>
<?php endif ?>
<div class="content">
<?= $this->filterEditor ?>
<?php if (count($downtimes) === 0): ?>
<?= $this->translate('No active downtimes'); ?>
</div>
<?php return; endif ?>
<?php
<table data-base-target="_next" class="action">
if (count($downtimes) === 0) {
echo $this->translate('No downtimes found matching the filter,'
. ' maybe the downtime already expired.') . '</div>';
return;
}
?>
<table data-base-target="_next"
class="action multiselect"
data-icinga-multiselect-url="/icingaweb2/monitoring/downtimes/show"
data-icinga-multiselect-data="downtime_id">
<tbody>
<?php foreach ($downtimes as $downtime): ?>
<?php
if (isset($downtime->service)) {
if (isset($downtime->service_description)) {
$isService = true;
$stateName = Service::getStateText($downtime->service_state);
} else {
@ -54,23 +57,30 @@ use Icinga\Module\Monitoring\Object\Service;
?>
</td>
<td>
<?php if ($isService): ?>
<?= $this->icon('service', $this->translate('Service')); ?>
<?= $this->link()->service(
$downtime->service, $downtime->service_display_name, $downtime->host, $downtime->host_display_name
) ?>
<?php else: ?>
<?= $this->icon('host', $this->translate('Host')); ?>
<?= $this->link()->host($downtime->host, $downtime->host_display_name) ?>
<?php endif ?>
<?php
if ($isService) {
echo $this->icon('service');
} else {
echo $this->icon('host');
}
?>
<?= $this->qlink(
sprintf($this->translate('%s on %s', 'Service running on host'), $downtime->service_display_name, $downtime->host_display_name),
'monitoring/downtime/show',
array('downtime_id' => $downtime->id),
array('title' => sprintf(
$this->translate('Show detailed information for downtime on %s for %s'),
$downtime->service_display_name,
$downtime->host_display_name
))) ?>
<br>
<?= $this->icon('comment', $this->translate('Comment')); ?> [<?= $this->escape($downtime->author) ?>] <?= $this->escape($downtime->comment) ?>
<?= $this->icon('comment', $this->translate('Comment')); ?> [<?= $this->escape($downtime->author_name) ?>] <?= $this->escape($downtime->comment) ?>
<br>
<small>
<?php if ($downtime->is_flexible): ?>
<?php if ($downtime->is_in_effect): ?>
<?= sprintf(
isset($downtime->service)
$isService
? $this->translate('This flexible service downtime was started on %s at %s and lasts for %s until %s at %s.')
: $this->translate('This flexible host downtime was started on %s at %s and lasts for %s until %s at %s.'),
date('d.m.y', $downtime->start),
@ -81,7 +91,7 @@ use Icinga\Module\Monitoring\Object\Service;
); ?>
<?php else: ?>
<?= sprintf(
isset($downtime->service)
$isService
? $this->translate('This flexible service downtime has been scheduled to start between %s - %s and to last for %s.')
: $this->translate('This flexible host downtime has been scheduled to start between %s - %s and to last for %s.'),
date('d.m.y H:i', $downtime->scheduled_start),
@ -92,7 +102,7 @@ use Icinga\Module\Monitoring\Object\Service;
<?php else: ?>
<?php if ($downtime->is_in_effect): ?>
<?= sprintf(
isset($downtime->service)
$isService
? $this->translate('This fixed service downtime was started on %s at %s and expires on %s at %s.')
: $this->translate('This fixed host downtime was started on %s at %s and expires on %s at %s.'),
date('d.m.y', $downtime->start),
@ -102,7 +112,7 @@ use Icinga\Module\Monitoring\Object\Service;
); ?>
<?php else: ?>
<?= sprintf(
isset($downtime->service)
$isService
? $this->translate('This fixed service downtime has been scheduled to start on %s at %s and to end on %s at %s.')
: $this->translate('This fixed host downtime has been scheduled to start on %s at %s and to end on %s at %s.'),
date('d.m.y', $downtime->scheduled_start),
@ -118,12 +128,12 @@ use Icinga\Module\Monitoring\Object\Service;
<td style="width: 2em" data-base-target="self">
<?php
$delDowntimeForm = clone $delDowntimeForm;
$delDowntimeForm->populate(array('downtime_id' => $downtime->id, 'redirect' => $this->url));
if (! isset($downtime->service)) {
$delDowntimeForm->setAction($this->url('monitoring/host/delete-downtime', array('host' => $downtime->host)));
} else {
$delDowntimeForm->setAction($this->url('monitoring/service/delete-downtime', array('host' => $downtime->host, 'service' => $downtime->service)));
}
$delDowntimeForm->populate(
array(
'downtime_id' => $downtime->id,
'downtime_is_service' => isset($downtime->service_description)
)
);
echo $delDowntimeForm;
?>
</td>

View File

@ -1,21 +1,25 @@
<?php
use Icinga\Data\Filter\Filter;
use Icinga\Web\Widget\Chart\HistoryColorGrid;
?>
<? if (! $compact): ?>
<div class="controls">
<?= $this->tabs->render($this); ?>
<div class="fake-controls">
<?= $form ?>
</div>
</div>
<? endif; ?>
if (! $this->compact): ?>
<div class="controls">
<?= $this->tabs; ?>
<?= $this->sortBox; ?>
<?= $this->limiter; ?>
<?= $this->paginator; ?>
<?= $this->filterEditor; ?>
<?= $form; ?>
</div>
<?php endif ?>
<div class="content" data-base-target="_next">
<?php
if (count($summary) === 0) {
echo $this->translate('No state changes in the selected time period.') . '</div>';
return;
}
$settings = array(
'cnt_up' => array(
'tooltip' => $this->translate('%d hosts ok on %s'),
@ -63,11 +67,8 @@ $to = intval($form->getValue('to', time()));
if ($to - $from > 315360000) {
$from = $to - 315360000;
}
$data = array();
if (count($summary) === 0) {
echo $this->translate('No state changes in the selected time period.');
}
$data = array();
foreach ($summary as $entry) {
$day = $entry->day;
$value = $entry->$column;

View File

@ -1,32 +1,23 @@
<?php
use Icinga\Module\Monitoring\Object\Host;
use Icinga\Module\Monitoring\Object\Service;
?>
<?php if (false === $this->compact): ?>
if (! $this->compact): ?>
<div class="controls">
<?= $this->tabs ?>
<div style="margin: 1em" class="dontprint">
<div style="float: right">
<?= $this->translate('Sort by') ?> <?= $this->sortControl ?>
</div>
</div>
<?= $this->widget('limiter', array('url' => $this->url, 'max' => $this->history->count())); ?>
<?= $this->paginationControl($history, null, null, array('preserve' => $this->preserve)); ?>
<?= $this->tabs; ?>
<?= $this->sortBox; ?>
<?= $this->limiter; ?>
<?= $this->paginator; ?>
<?= $this->filterEditor; ?>
</div>
<?php endif ?>
<div class="content">
<?= $this->filterEditor ?>
<?php if (empty($history)): ?>
<?= $this->translate('No history events matching the filter') ?>
</div>
<?php return; endif ?>
<?php
if (count($history) === 0) {
echo $this->translate('No history events found matching the filter') . '</div>';
return;
}
?>
<table data-base-target="_next" class="action">
<tbody>
<?php foreach ($history as $event): ?>
@ -34,7 +25,7 @@ use Icinga\Module\Monitoring\Object\Service;
$icon = 'help';
$title = $event->type;
$stateName = 'invalid';
$isService = isset($event->service);
$isService = isset($event->service_description);
switch ($event->type) {
case 'notify':
$icon = 'bell';
@ -99,10 +90,10 @@ use Icinga\Module\Monitoring\Object\Service;
<td>
<?php if ($isService): ?>
<?= $this->link()->service(
$event->service, $event->service_display_name, $event->host, $event->host_display_name
$event->service_description, $event->service_display_name, $event->host_name, $event->host_display_name
) ?>
<?php else: ?>
<?= $this->link()->host($event->host, $event->host_display_name) ?>
<?= $this->link()->host($event->host_name, $event->host_display_name) ?>
<?php endif ?>
<br>
<div>

View File

@ -1,25 +1,24 @@
<?php if ($this->compact): ?>
<div class="content">
<?php else: ?>
<?php
use Icinga\Module\Monitoring\Object\Host;
if (! $this->compact): ?>
<div class="controls">
<?= $this->tabs ?>
<div style="margin: 1em;" class="dontprint">
<?= $this->translate('Sort by'); ?> <?= $this->sortControl->render($this); ?>
</div>
<?= $this->widget('limiter')->setMaxLimit(count($hostgroups)); ?>
<?= $this->paginationControl($hostgroups, null, null, array('preserve' => $this->preserve)); ?>
</div>
<div class="content">
<?= $this->tabs; ?>
<?= $this->sortBox; ?>
<?= $this->limiter; ?>
<?= $this->paginator; ?>
<?= $this->filterEditor; ?>
</div>
<?php endif ?>
<?php
if (count($hostgroups) === 0) {
echo $this->translate('No host groups matching the filter');
echo '</div>';
return;
}
?>
<table class="groupview" data-base-target="_next">
<div class="content">
<?php
if (count($hostgroups) === 0) {
echo $this->translate('No hostgroups found matching the filter') . '</div>';
return;
}
?>
<table class="groupview action" data-base-target="_next">
<thead>
<th><?= $this->translate('Last Problem'); ?></th>
<th><?= $this->translate('Host Group'); ?></th>
@ -27,62 +26,45 @@
<th><?= $this->translate('Service States'); ?></th>
</thead>
<tbody>
<?php foreach ($hostgroups as $h): ?>
<tr href="<?= $this->href('monitoring/list/hosts', array('hostgroup' => $h->hostgroup)) ?>">
<?php if ($h->services_critical_last_state_change_unhandled): ?>
<td class="state change critical unhandled">
<strong><?= $this->translate('CRITICAL'); ?></strong>
<?php foreach ($hostgroups as $h):
if ($h->hosts_down_unhandled) {
$handled = false;
$state = Host::STATE_DOWN;
$lastStateChange = $h->hosts_down_last_state_change_unhandled;
} elseif ($h->hosts_unreachable_unhandled) {
$handled = false;
$state = Host::STATE_UNREACHABLE;
$lastStateChange = $h->hosts_unreachable_last_state_change_unhandled;
} else {
$handled = true;
if ($h->hosts_down_handled) {
$state = Host::STATE_DOWN;
$lastStateChange = $h->hosts_down_last_state_change_handled;
} elseif ($h->hosts_unreachable_handled) {
$state = Host::STATE_UNREACHABLE;
$lastStateChange = $h->hosts_unreachable_last_state_change_handled;
} elseif ($h->hosts_up) {
$state = Host::STATE_UP;
$lastStateChange = $h->hosts_up_last_state_change;
} else {
$state = Host::STATE_PENDING;
$lastStateChange = $h->hosts_pending_last_state_change;
}
}
?>
<tr class="state <?= Host::getStateText($state) ?><?= $handled ? ' handled' : '' ?>" href="<?=
$this->href('monitoring/list/hosts', array('hostgroup_name' => $h->hostgroup_name))
?>">
<td class="state">
<strong><?= Host::getStateText($state, true); ?></strong>
<br>
<?= $this->prefixedTimeSince($h->services_critical_last_state_change_unhandled); ?>
<?= $this->prefixedTimeSince($lastStateChange); ?>
</td>
<?php elseif ($h->services_unknown_last_state_change_unhandled): ?>
<td class="state change unknown unhandled">
<strong><?= $this->translate('UNKNOWN'); ?></strong>
<br>
<?= $this->prefixedTimeSince($h->services_unknown_last_state_change_unhandled); ?>
</td>
<?php elseif ($h->services_warning_last_state_change_unhandled): ?>
<td class="state change warning unhandled">
<strong><?= $this->translate('WARNING'); ?></strong>
<br>
<?= $this->prefixedTimeSince($h->services_warning_last_state_change_unhandled); ?>
</td>
<?php elseif ($h->services_critical_last_state_change_handled): ?>
<td class="state change critical">
<strong><?= $this->translate('CRITICAL'); ?></strong>
<br>
<?= $this->prefixedTimeSince($h->services_critical_last_state_change_handled); ?>
</td>
<?php elseif ($h->services_unknown_last_state_change_handled): ?>
<td class="state change unknown">
<strong><?= $this->translate('UNKNOWN'); ?></strong>
<br>
<?= $this->prefixedTimeSince($h->services_unknown_last_state_change_handled); ?>
</td>
<?php elseif ($h->services_warning_last_state_change_handled): ?>
<td class="state change warning">
<strong><?= $this->translate('WARNING'); ?></strong>
<br>
<?= $this->prefixedTimeSince($h->services_warning_last_state_change_handled); ?>
</td>
<?php elseif ($h->services_ok_last_state_change): ?>
<td class="state change ok">
<strong><?= $this->translate('OK'); ?></strong>
<br>
<?= $this->prefixedTimeSince($h->services_ok_last_state_change); ?>
</td>
<?php else: ?>
<td class="state change pending">
<strong><?= $this->translate('PENDING'); ?></strong>
<br>
<?= $this->prefixedTimeSince($h->services_pending_last_state_change); ?>
</td>
<?php endif ?>
<td class="groupname">
<?= $this->qlink(
$h->hostgroup_alias,
'monitoring/list/hosts',
array('hostgroup' => $h->hostgroup),
array('hostgroup_name' => $h->hostgroup_name),
array('title' => sprintf($this->translate('List all hosts in the group "%s"'), $h->hostgroup_alias))
); ?>
</td>
@ -90,23 +72,23 @@
<?= $this->qlink(
$h->services_total,
'monitoring/list/services',
array('hostgroup' => $h->hostgroup),
array('hostgroup_name' => $h->hostgroup_name),
array('title' => sprintf(
$this->translate('List all services of all hosts in host group "%s"'),
$h->hostgroup_alias
))
); ?>
</td>
<td class="state">
<td>
<?php if ($h->services_ok): ?>
<span class="state ok">
<?= $this->qlink(
$h->services_ok,
'monitoring/list/services',
array(
'service_state' => 0,
'hostgroup' => $h->hostgroup,
'sort' => 'service_severity'
'service_state' => 0,
'hostgroup_name' => $h->hostgroup_name,
'sort' => 'service_severity'
),
array(
'title' => sprintf(
@ -132,7 +114,7 @@
'service_acknowledged' => 0,
'service_in_downtime' => 0,
'host_problem' => 0,
'hostgroup' => $h->hostgroup,
'hostgroup_name' => $h->hostgroup_name,
'sort' => 'service_severity'
),
array(
@ -156,7 +138,7 @@
array(
'service_state' => 2,
'service_handled' => 1,
'hostgroup' => $h->hostgroup,
'hostgroup_name' => $h->hostgroup_name,
'sort' => 'service_severity'
),
array(
@ -186,7 +168,7 @@
'service_acknowledged' => 0,
'service_in_downtime' => 0,
'host_problem' => 0,
'hostgroup' => $h->hostgroup,
'hostgroup_name' => $h->hostgroup_name,
'sort' => 'service_severity'
),
array(
@ -210,7 +192,7 @@
array(
'service_state' => 3,
'service_handled' => 1,
'hostgroup' => $h->hostgroup,
'hostgroup_name' => $h->hostgroup_name,
'sort' => 'service_severity'
),
array(
@ -240,7 +222,7 @@
'service_acknowledged' => 0,
'service_in_downtime' => 0,
'host_problem' => 0,
'hostgroup' => $h->hostgroup,
'hostgroup_name' => $h->hostgroup_name,
'sort' => 'service_severity'
),
array(
@ -264,7 +246,7 @@
array(
'service_state' => 1,
'service_handled' => 1,
'hostgroup' => $h->hostgroup,
'hostgroup_name' => $h->hostgroup_name,
'sort' => 'service_severity'
),
array(
@ -290,9 +272,9 @@
$h->services_pending,
'monitoring/list/services',
array(
'service_state' => 99,
'hostgroup' => $h->hostgroup,
'sort' => 'service_severity'
'service_state' => 99,
'hostgroup_name' => $h->hostgroup_name,
'sort' => 'service_severity'
),
array(
'title' => sprintf(

View File

@ -1,33 +1,25 @@
<?php
use Icinga\Module\Monitoring\Object\Host;
if ($this->compact): ?>
<div class="content">
<?php else: ?>
if (! $this->compact): ?>
<div class="controls">
<?= $this->tabs ?>
<div style="margin: 1em;" class="dontprint">
<?= $this->render('list/components/selectioninfo.phtml') ?>
<?= $this->render('list/components/hostssummary.phtml') ?>
<?= $this->translate('Sort by') ?> <?= $this->sortControl->render($this) ?>
<?= $this->tabs; ?>
<div class="dontprint">
<?= $this->render('list/components/selectioninfo.phtml'); ?>
<?= $this->render('list/components/hostssummary.phtml'); ?>
</div>
<?= $this->widget('limiter')->setMaxLimit($this->hosts->count()) ?>
<?= $this->paginationControl($hosts, null, null, array('preserve' => $this->preserve)) ?>
<?= $this->selectionToolbar('multi', $this->href('monitoring/hosts/show?' . $this->filter->toQueryString())) ?>
<?= $this->sortBox; ?>
<?= $this->limiter; ?>
<?= $this->paginator; ?>
<?= $this->selectionToolbar('multi', $this->href('monitoring/hosts/show?' . $this->filter->toQueryString())); ?>
<?= $this->filterEditor; ?>
</div>
<?php endif ?>
<div class="content">
<?= $this->filterEditor ?>
<?php
endif;
if ($hosts->count() === 0) {
echo $this->translate('No hosts matching the filter');
if (! $this->compact) {
echo '</div>';
}
if (count($hosts) === 0) {
echo $this->translate('No hosts found matching the filter') . '</div>';
return;
}
?>

View File

@ -1,30 +1,28 @@
<?php
use Icinga\Module\Monitoring\Object\Host;
use Icinga\Module\Monitoring\Object\Service;
?>
<?php if (! $this->compact): ?>
if (! $this->compact): ?>
<div class="controls">
<?= $this->tabs ?>
<div class="dontprint" style="margin: 1em;">
<?= $this->translate('Sort by') ?> <?= $this->sortControl->render($this) ?>
</div>
<?= $this->widget('limiter') ?>
<?= $this->paginationControl($notifications, null, null, array('preserve' => $this->preserve)) ?>
<?= $this->tabs; ?>
<?= $this->sortBox; ?>
<?= $this->limiter; ?>
<?= $this->paginator; ?>
<?= $this->filterEditor; ?>
</div>
<?php endif ?>
<div class="content">
<?php if (count($notifications) === 0): ?>
<?= $this->translate('No notifications matching the filter') ?>
<?php return; endif ?>
<?php
if (count($notifications) === 0) {
echo $this->translate('No notifications found matching the filter') . '</div>';
return;
}
?>
<table data-base-target="_next" class="action">
<tbody>
<?php foreach ($notifications as $notification):
if (isset($notification->service)) {
if (isset($notification->service_description)) {
$isService = true;
$stateName = Service::getStateText($notification->notification_state);
} else {
@ -44,14 +42,14 @@ use Icinga\Module\Monitoring\Object\Service;
<?php if ($isService): ?>
<?= $this->icon('service', $this->translate('Service')); ?>
<?= $this->link()->service(
$notification->service,
$notification->service_description,
$notification->service_display_name,
$notification->host,
$notification->host_name,
$notification->host_display_name
) ?>
<?php else: ?>
<?= $this->icon('host', $this->translate('Host')); ?>
<?= $this->link()->host($notification->host, $notification->host_display_name) ?>
<?= $this->link()->host($notification->host_name, $notification->host_display_name) ?>
<?php endif ?>
<br>
<?= $this->escape($this->ellipsis($notification->notification_output, 10000)) ?>
@ -61,9 +59,9 @@ use Icinga\Module\Monitoring\Object\Service;
<?= sprintf(
$this->translate('Sent to %s'),
$this->qlink(
$notification->notification_contact,
$notification->notification_contact_name,
'monitoring/show/contact',
array('contact' => $notification->notification_contact)
array('contact_name' => $notification->notification_contact_name)
)
) ?>
</small>

View File

@ -1,28 +1,28 @@
<?php
use Icinga\Module\Monitoring\Object\Service;
?>
<?php if (!$this->compact): ?>
if (! $this->compact): ?>
<div class="controls">
<?= $this->tabs; ?>
<div style="margin: 1em;" class="dontprint">
<?= $this->translate('Sort by'); ?> <?= $this->sortControl; ?>
</div>
<?= $this->sortBox; ?>
<?= $this->limiter; ?>
<?= $this->paginator; ?>
<?= $this->filterEditor; ?>
</div>
<?php endif ?>
<div class="content" data-base-target="_next">
<table class="pivot servicestates">
<?php
$hasHeader = false;
$pivotData = $this->pivot->toArray();
if (count($pivotData) === 0) {
echo $this->translate('No services found matching the filter') . '</div>';
return;
}
$hostFilter = '(host_name=' . implode('|host_name=', array_keys($pivotData)) . ')';
?>
<?php if (count($pivotData) === 0): ?>
<?= $this->translate('No Services matching the filter'); ?>
<?php endif ?>
<table class="pivot servicestates">
<?php foreach ($pivotData as $host_name => $serviceStates): ?>
<?php if (!$hasHeader): ?>
<thead>

View File

@ -1,24 +1,20 @@
<?php if ($this->compact): ?>
<div class="content">
<?php else: ?>
<?php if (! $this->compact): ?>
<div class="controls">
<?= $this->tabs ?>
<div style="margin: 1em;" class="dontprint">
<?= $this->translate('Sort by'); ?> <?= $this->sortControl->render($this); ?>
</div>
<?= $this->widget('limiter')->setMaxLimit(count($servicegroups)); ?>
<?= $this->paginationControl($servicegroups, null, null, array('preserve' => $this->preserve)); ?>
</div>
<div class="content">
<?= $this->tabs; ?>
<?= $this->sortBox; ?>
<?= $this->limiter; ?>
<?= $this->paginator; ?>
<?= $this->filterEditor; ?>
</div>
<?php endif ?>
<?php
if (count($servicegroups) === 0) {
echo $this->translate('No service groups matching the filter');
echo '</div>';
return;
}
?>
<div class="content">
<?php
if (count($servicegroups) === 0) {
echo $this->translate('No servicegroups found matching the filter') . '</div>';
return;
}
?>
<table class="groupview" data-base-target="_next">
<thead>
<th><?= $this->translate('Last Problem'); ?></th>
@ -28,7 +24,7 @@
</thead>
<tbody>
<?php foreach ($servicegroups as $s): ?>
<tr href="<?= $this->href('monitoring/list/services', array('servicegroup' => $s->servicegroup)); ?>">
<tr href="<?= $this->href('monitoring/list/services', array('servicegroup_name' => $s->servicegroup_name)); ?>">
<?php if ($s->services_critical_last_state_change_unhandled): ?>
<td class="state change critical unhandled">
<strong><?= $this->translate('CRITICAL'); ?></strong>
@ -82,7 +78,7 @@
<?= $this->qlink(
$s->servicegroup_alias,
'monitoring/list/services',
array('servicegroup' => $s->servicegroup),
array('servicegroup_name' => $s->servicegroup_name),
array('title' => sprintf($this->translate('List all services in the group "%s"'), $s->servicegroup_alias))
); ?>
</td>
@ -96,9 +92,9 @@
$s->services_ok,
'monitoring/list/services',
array(
'service_state' => 0,
'servicegroup' => $s->servicegroup,
'sort' => 'service_severity'
'service_state' => 0,
'servicegroup_name' => $s->servicegroup_name,
'sort' => 'service_severity'
),
array(
'title' => sprintf(
@ -124,7 +120,7 @@
'service_acknowledged' => 0,
'service_in_downtime' => 0,
'host_problem' => 0,
'servicegroup' => $s->servicegroup,
'servicegroup_name' => $s->servicegroup_name,
'sort' => 'service_severity'
),
array(
@ -148,7 +144,7 @@
array(
'service_state' => 2,
'service_handled' => 1,
'servicegroup' => $s->servicegroup,
'servicegroup_name' => $s->servicegroup_name,
'sort' => 'service_severity'
),
array(
@ -178,7 +174,7 @@
'service_acknowledged' => 0,
'service_in_downtime' => 0,
'host_problem' => 0,
'servicegroup' => $s->servicegroup,
'servicegroup_name' => $s->servicegroup_name,
'sort' => 'service_severity'
),
array(
@ -202,7 +198,7 @@
array(
'service_state' => 3,
'service_handled' => 1,
'servicegroup' => $s->servicegroup,
'servicegroup_name' => $s->servicegroup_name,
'sort' => 'service_severity'
),
array(
@ -232,7 +228,7 @@
'service_acknowledged' => 0,
'service_in_downtime' => 0,
'host_problem' => 0,
'servicegroup' => $s->servicegroup,
'servicegroup_name' => $s->servicegroup_name,
'sort' => 'service_severity'
),
array(
@ -256,7 +252,7 @@
array(
'service_state' => 1,
'service_handled' => 1,
'servicegroup' => $s->servicegroup,
'servicegroup_name' => $s->servicegroup_name,
'sort' => 'service_severity'
),
array(
@ -282,9 +278,9 @@
$s->services_pending,
'monitoring/list/services',
array(
'service_state' => 99,
'servicegroup' => $s->servicegroup,
'sort' => 'service_severity'
'service_state' => 99,
'servicegroup_name' => $s->servicegroup_name,
'sort' => 'service_severity'
),
array(
'title' => sprintf(

View File

@ -4,41 +4,33 @@ use Icinga\Module\Monitoring\Object\Service;
$selfUrl = 'monitoring/list/services';
if (!$this->compact): ?>
if (! $this->compact): ?>
<div class="controls">
<?= $this->tabs ?>
<div style="margin: 1em;" class="dontprint">
<?= $this->render('list/components/selectioninfo.phtml') ?>
<?= $this->render('list/components/servicesummary.phtml') ?>
<div style="float: right">
<?= $this->translate('Sort by') ?> <?= $this->sortControl ?>
<?= $this->tabs; ?>
<div class="dontprint">
<?= $this->render('list/components/selectioninfo.phtml'); ?>
<?= $this->render('list/components/servicesummary.phtml'); ?>
</div>
<?= $this->sortBox; ?>
<?= $this->limiter; ?>
<?= $this->paginator; ?>
<?= $this->filterEditor; ?>
</div>
</div>
<?php if ($this->limit === 0): ?>
<?= $this->widget('limiter') ?>
<?php else: ?>
<?= $this->widget('limiter')->setCurrentPageCount($this->services->count()) ?>
<?= $this->paginationControl($services, null, null, array('preserve' => $this->preserve)) ?>
<?php endif ?>
</div>
<div class="content">
<?= $this->filterEditor ?>
<?php else: ?>
<?php
<div class="content">
<?php endif ?>
if (count($services) === 0) {
echo $this->translate('No services found matching the filter') . '</div>';
return;
}
?>
<table data-base-target="_next"
class="action multiselect <?php if ($this->compact): ?> compact<?php endif ?>" style="table-layout: auto;"
data-icinga-multiselect-url="<?= $this->href("monitoring/services/show") ?>"
data-icinga-multiselect-data="service,host">
<tbody>
<?php
if (count($services) === 0) {
echo mt('monitoring', 'No services matching the filter');
}
foreach ($services as $service):
<?php foreach ($services as $service):
$serviceLink = $this->href(
'monitoring/service/show',
array(

View File

@ -0,0 +1,27 @@
<?php
switch ($comment->type) {
case 'flapping':
$icon = 'flapping';
$title = $this->translate('Flapping');
$tooltip = $this->translate('Comment was caused by a flapping host or service.');
break;
case 'comment':
$icon = 'user';
$title = $this->translate('User Comment');
$tooltip = $this->translate('Comment was created by an user.');
break;
case 'downtime':
$icon = 'plug';
$title = $this->translate('Downtime');
$tooltip = $this->translate('Comment was caused by a downtime.');
break;
case 'ack':
$icon = 'ok';
$title = $this->translate('Acknowledgement');
$tooltip = $this->translate('Comment was caused by an acknowledgement.');
break;
}
?>
<strong><?= $this->escape($title); ?></strong><br>
<?= $this->icon($icon, $tooltip) ?>
<?= $this->prefixedTimeSince($comment->timestamp); ?>

View File

@ -0,0 +1,18 @@
<?php if ($comment->objecttype === 'service'): ?>
<?= $this->icon('service', $this->translate('Service')); ?>
<?= $this->link()->service(
$comment->service_description,
$comment->service_display_name,
$comment->host_name,
$comment->host_display_name
); ?>
<?php else: ?>
<?= $this->icon('host', $this->translate('Host')); ?>
<?= $this->link()->host($comment->host_name, $comment->host_display_name); ?>
<?php endif ?>
<br>
<?= $this->icon('comment', $this->translate('Comment')); ?> <?= isset($comment->author)
? '[' . $this->escape($comment->author) . '] '
: '';
?><?= $this->escape($comment->comment); ?>

View File

@ -0,0 +1,10 @@
<table class="action">
<tr class="state invalid">
<td class="state" style="width: 12em;">
<?= $this->render('partials/comment/comment-description.phtml'); ?>
</td>
<td>
<?= $this->render('partials/comment/comment-detail.phtml'); ?>
</td>
</tr>
</table>

View File

@ -0,0 +1,30 @@
<table class="action">
<?php $i = 0; foreach ($comments as $comment):
if (++ $i > 5) {
continue;
}
$this->comment = $comment;
?>
<tr class="state invalid">
<td class="state" style="width: 12em;">
<?= $this->render('partials/comment/comment-description.phtml'); ?>
</td>
<td>
<?= $this->render('partials/comment/comment-detail.phtml'); ?>
</td>
</tr>
<?php endforeach; ?>
</table>
<p>
<?= $this->qlink(
sprintf($this->translate('List all %d comments …'), count($comments)),
$listAllLink,
null,
array(
'title' => $this->translate('List all'),
'data-base-target' => "_next"
)
) ?>
</p>

View File

@ -0,0 +1,67 @@
<table class="action">
<tr class="state <?= $stateName; ?><?= $downtime->is_in_effect ? ' handled' : ''; ?>">
<td class="state">
<strong><?= $downtime->is_in_effect ? $this->translate('Expires') : $this->translate('Starts'); ?></strong>
<br>
<?=
$this->dateTimeRenderer(
($downtime->is_in_effect ? $downtime->end : $downtime->start),
true
)->render(
$this->translate('on %s', 'datetime'),
$this->translate('at %s', 'time'),
$this->translate('in %s', 'timespan')
);
?>
</td>
<td>
<small>
<?php if ($downtime->is_flexible): ?>
<?php if ($downtime->is_in_effect): ?>
<?= sprintf(
$this->isService
? $this->translate('This flexible service downtime was started on %s at %s and lasts for %s until %s at %s.')
: $this->translate('This flexible host downtime was started on %s at %s and lasts for %s until %s at %s.'),
date('d.m.y', $downtime->start),
date('H:i', $downtime->start),
$this->format()->duration($downtime->duration),
date('d.m.y', $downtime->end),
date('H:i', $downtime->end)
); ?>
<?php else: ?>
<?= sprintf(
$this->isService
? $this->translate('This flexible service downtime has been scheduled to start between %s - %s and to last for %s.')
: $this->translate('This flexible host downtime has been scheduled to start between %s - %s and to last for %s.'),
date('d.m.y H:i', $downtime->scheduled_start),
date('d.m.y H:i', $downtime->scheduled_end),
$this->format()->duration($downtime->duration)
); ?>
<?php endif ?>
<?php else: ?>
<?php if ($downtime->is_in_effect): ?>
<?= sprintf(
$this->isService
? $this->translate('This fixed service downtime was started on %s at %s and expires on %s at %s.')
: $this->translate('This fixed host downtime was started on %s at %s and expires on %s at %s.'),
date('d.m.y', $downtime->start),
date('H:i', $downtime->start),
date('d.m.y', $downtime->end),
date('H:i', $downtime->end)
); ?>
<?php else: ?>
<?= sprintf(
$this->isService
? $this->translate('This fixed service downtime has been scheduled to start on %s at %s and to end on %s at %s.')
: $this->translate('This fixed host downtime has been scheduled to start on %s at %s and to end on %s at %s.'),
date('d.m.y', $downtime->scheduled_start),
date('H:i', $downtime->scheduled_start),
date('d.m.y', $downtime->scheduled_end),
date('H:i', $downtime->scheduled_end)
); ?>
<?php endif ?>
<?php endif ?>
</small>
</td>
</tr>
</table>

View File

@ -0,0 +1,92 @@
<table class="action">
<tbody>
<?php $i = 0; foreach ($downtimes as $downtime):
if (++ $i > 5) {
continue;
} ?>
<tr class="state <?= $downtime->stateText ?>">
<td class="state">
<strong><?= $downtime->is_in_effect ? $this->translate('Expires') : $this->translate('Starts'); ?></strong>
<br>
<?=
$this->dateTimeRenderer(
($downtime->is_in_effect ? $downtime->end : $downtime->start),
true
)->render(
$this->translate('on %s', 'datetime'),
$this->translate('at %s', 'time'),
$this->translate('in %s', 'timespan')
);
?>
</td>
<td class="name oneline">
<?php if ($downtime->isService): ?>
<?= $this->icon('service', $this->translate('Service')) ?>
<b><?= $downtime->service ?> on <?= $downtime->host_name ?>.</b>
<?php else: ?>
<?= $this->icon('host', $this->translate('Host')) ?>
<b><?= $downtime->host_name ?>.</b>
<?php endif; ?>
<?php if ($downtime->is_flexible): ?>
<?php if ($downtime->is_in_effect): ?>
<?= sprintf(
$this->isService
? $this->translate('This flexible service downtime was started on %s at %s and lasts for %s until %s at %s.')
: $this->translate('This flexible host downtime was started on %s at %s and lasts for %s until %s at %s.'),
date('d.m.y', $downtime->start),
date('H:i', $downtime->start),
$this->format()->duration($downtime->duration),
date('d.m.y', $downtime->end),
date('H:i', $downtime->end)
); ?>
<?php else: ?>
<?= sprintf(
$this->isService
? $this->translate('This flexible service downtime has been scheduled to start between %s - %s and to last for %s.')
: $this->translate('This flexible host downtime has been scheduled to start between %s - %s and to last for %s.'),
date('d.m.y H:i', $downtime->scheduled_start),
date('d.m.y H:i', $downtime->scheduled_end),
$this->format()->duration($downtime->duration)
); ?>
<?php endif ?>
<?php else: ?>
<?php if ($downtime->is_in_effect): ?>
<?= sprintf(
$this->isService
? $this->translate('This fixed service downtime was started on %s at %s and expires on %s at %s.')
: $this->translate('This fixed host downtime was started on %s at %s and expires on %s at %s.'),
date('d.m.y', $downtime->start),
date('H:i', $downtime->start),
date('d.m.y', $downtime->end),
date('H:i', $downtime->end)
); ?>
<?php else: ?>
<?= sprintf(
$this->isService
? $this->translate('This fixed service downtime has been scheduled to start on %s at %s and to end on %s at %s.')
: $this->translate('This fixed host downtime has been scheduled to start on %s at %s and to end on %s at %s.'),
date('d.m.y', $downtime->scheduled_start),
date('H:i', $downtime->scheduled_start),
date('d.m.y', $downtime->scheduled_end),
date('H:i', $downtime->scheduled_end)
); ?>
<?php endif ?>
<?php endif ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<p>
<?= $this->qlink(
sprintf($this->translate('List all %d downtimes …'), count($downtimes)),
$listAllLink,
null,
array(
'title' => $this->translate('List all'),
'data-base-target' => "_next"
)
) ?>
</p>

View File

@ -1,11 +1,7 @@
<?php
use Icinga\Module\Monitoring\Object\Host;
?>
<?php if (! $this->compact): ?>
<?= $tabs; ?>
<?php endif ?>
<table class="objectstate">
<tr class="state <?= Host::getStateText($object->host_state); ?><?= $object->host_handled ? ' handled' : ''; ?>">
<td class="state">

View File

@ -1,6 +1,3 @@
<?php if (! $this->compact): ?>
<?= $tabs; ?>
<?php endif ?>
<?php if (($hostCount = count($objects)) > 0): ?>
<div class="hbox-item">
<strong><?= sprintf($this->translatePlural('Host (%u)', 'Hosts (%u)', $hostCount), $hostCount); ?></strong>

View File

@ -1,12 +1,8 @@
<?php
use Icinga\Module\Monitoring\Object\Host;
use Icinga\Module\Monitoring\Object\Service;
?>
<?php if (! $this->compact): ?>
<?= $tabs; ?>
<?php endif ?>
<table class="objectstate">
<tr class="state <?= Host::getStateText($object->host_state); ?><?= $object->host_handled ? ' handled' : ''; ?>">
<td class="state">

Some files were not shown because too many files have changed in this diff Show More