diff --git a/.puppet/hiera/common.yaml b/.puppet/hiera/common.yaml index 0a85ba63a..d7802181f 100644 --- a/.puppet/hiera/common.yaml +++ b/.puppet/hiera/common.yaml @@ -1,7 +1,8 @@ --- -icingaweb2::config: /etc/icingaweb -icingaweb2::log: /var/log/icingaweb/icingaweb.log -icingaweb2::web_path: icingaweb -icingaweb2::db_user: icingaweb -icingaweb2::db_pass: icingaweb -icingaweb2::db_name: icingaweb +icingaweb2::config: /etc/icingaweb2 +icingaweb2::log: /var/log/icingaweb2/icingaweb2.log +icingaweb2::web_path: icingaweb2 +icingaweb2::db_user: icingaweb2 +icingaweb2::db_pass: icingaweb2 +icingaweb2::db_name: icingaweb2 +icingaweb2::group: icingaweb2 diff --git a/.puppet/manifests/site.pp b/.puppet/manifests/site.pp index 08120d911..043f24dbb 100644 --- a/.puppet/manifests/site.pp +++ b/.puppet/manifests/site.pp @@ -13,5 +13,5 @@ node default { source => 'puppet:////vagrant/.puppet/files/etc/profile.d/env.sh' } @user { vagrant: ensure => present } - User <| title == vagrant |> { groups +> icingaweb } + User <| title == vagrant |> { groups +> hiera('icingaweb2::group') } } diff --git a/.puppet/modules/icinga2_pgsql/manifests/init.pp b/.puppet/modules/icinga2_pgsql/manifests/init.pp index 2326449af..95bc71034 100644 --- a/.puppet/modules/icinga2_pgsql/manifests/init.pp +++ b/.puppet/modules/icinga2_pgsql/manifests/init.pp @@ -11,7 +11,8 @@ class icinga2_pgsql { password => 'icinga2', schemafile => '/usr/share/icinga2-ido-pgsql/schema/pgsql.sql', } - -> icinga2::feature { 'ido-pgsql': - source => 'puppet:///modules/icinga2_pgsql', - } +# Because Icinga 2 does not handle more than one IDO connection properly, The ido-pgsql will not be enabled by default. +# -> icinga2::feature { 'ido-pgsql': +# source => 'puppet:///modules/icinga2_pgsql', +# } } diff --git a/.puppet/modules/icingaweb2/manifests/config.pp b/.puppet/modules/icingaweb2/manifests/config.pp index 473d89d06..625c47b7a 100644 --- a/.puppet/modules/icingaweb2/manifests/config.pp +++ b/.puppet/modules/icingaweb2/manifests/config.pp @@ -1,14 +1,15 @@ class icingaweb2::config ( - $config = hiera('icingaweb2::config') + $config = hiera('icingaweb2::config'), + $web_group = hiera('icingaweb2::group') ) { - group { 'icingaweb': + group { $web_group: ensure => present, } file { [ "${config}", "${config}/enabledModules", "${config}/modules", "${config}/preferences" ]: ensure => directory, owner => 'root', - group => 'icingaweb', + group => $web_group, mode => '2770', } } diff --git a/.puppet/modules/icingaweb2/manifests/config/general.pp b/.puppet/modules/icingaweb2/manifests/config/general.pp index c2daec83f..8ccea172f 100644 --- a/.puppet/modules/icingaweb2/manifests/config/general.pp +++ b/.puppet/modules/icingaweb2/manifests/config/general.pp @@ -1,14 +1,15 @@ define icingaweb2::config::general ( $source, - $config = hiera('icingaweb2::config'), - $replace = true + $config = hiera('icingaweb2::config'), + $web_group = hiera('icingaweb2::group'), + $replace = true ) { include icingaweb2::config file { "${config}/${name}.ini": content => template("${source}/${name}.ini.erb"), owner => 'root', - group => 'icingaweb', + group => $web_group, mode => 0660, replace => $replace, } diff --git a/.puppet/modules/icingaweb2/manifests/config/module.pp b/.puppet/modules/icingaweb2/manifests/config/module.pp index 69e5abd6b..19db02250 100644 --- a/.puppet/modules/icingaweb2/manifests/config/module.pp +++ b/.puppet/modules/icingaweb2/manifests/config/module.pp @@ -1,8 +1,9 @@ define icingaweb2::config::module ( $module, $source, - $config = hiera('icingaweb2::config'), - $replace = true + $config = hiera('icingaweb2::config'), + $web_group = hiera('icingaweb2::group'), + $replace = true ) { include icingaweb2::config @@ -10,7 +11,7 @@ define icingaweb2::config::module ( file { "${config}/modules/${module}": ensure => directory, owner => 'root', - group => 'icingaweb', + group => $web_group, mode => '2770', } } @@ -18,7 +19,7 @@ define icingaweb2::config::module ( file { "${config}/modules/${module}/${name}.ini": source => "${source}/modules/${module}/${name}.ini", owner => 'root', - group => 'icingaweb', + group => $web_group, mode => 0660, replace => $replace, } diff --git a/.puppet/modules/pgsql/templates/pg_hba.conf.erb b/.puppet/modules/pgsql/templates/pg_hba.conf.erb index f6fb19ebf..ca98bebd8 100644 --- a/.puppet/modules/pgsql/templates/pg_hba.conf.erb +++ b/.puppet/modules/pgsql/templates/pg_hba.conf.erb @@ -71,6 +71,11 @@ local icinga icinga trust host icinga icinga 127.0.0.1/32 trust host icinga icinga ::1/128 trust +# icinga2 +local icinga2 icinga2 trust +host icinga2 icinga2 127.0.0.1/32 trust +host icinga2 icinga2 ::1/128 trust + # icinga_unittest local icinga_unittest icinga_unittest trust host icinga_unittest icinga_unittest 127.0.0.1/32 trust @@ -81,6 +86,11 @@ local icingaweb icingaweb trust host icingaweb icingaweb 127.0.0.1/32 trust host icingaweb icingaweb ::1/128 trust +# icingaweb2 +local <%= scope.function_hiera(['icingaweb2::db_user']) %> <%= scope.function_hiera(['icingaweb2::db_user']) %> trust +host <%= scope.function_hiera(['icingaweb2::db_user']) %> <%= scope.function_hiera(['icingaweb2::db_user']) %> 127.0.0.1/32 trust +host <%= scope.function_hiera(['icingaweb2::db_user']) %> <%= scope.function_hiera(['icingaweb2::db_user']) %> ::1/128 trust + # "local" is for Unix domain socket connections only local all all ident # IPv4 local connections: diff --git a/.puppet/modules/php_imagick/manifests/init.pp b/.puppet/modules/php_imagick/manifests/init.pp new file mode 100644 index 000000000..5ef0453af --- /dev/null +++ b/.puppet/modules/php_imagick/manifests/init.pp @@ -0,0 +1,29 @@ +# Class: php_imagick +# +# This class installs the ImageMagick PHP module. +# +# Parameters: +# +# Actions: +# +# Requires: +# +# php +# +# Sample Usage: +# +# include php_imagick +# +class php_imagick { + include php + + $php_imagick = $::operatingsystem ? { + /(Debian|Ubuntu)/ => 'php5-imagick', + /(RedHat|CentOS|Fedora)/ => 'php-pecl-imagick', + /(SLES|OpenSuSE)/ => 'php5-imagick', + } + + package { $php_imagick: + ensure => latest, + } +} diff --git a/.puppet/profiles/icingaweb2_dev/manifests/init.pp b/.puppet/profiles/icingaweb2_dev/manifests/init.pp index 379f75247..b8bea040f 100644 --- a/.puppet/profiles/icingaweb2_dev/manifests/init.pp +++ b/.puppet/profiles/icingaweb2_dev/manifests/init.pp @@ -1,13 +1,15 @@ class icingaweb2_dev ( - $config = hiera('icingaweb2::config'), - $log = hiera('icingaweb2::log'), - $web_path = hiera('icingaweb2::web_path'), - $db_user = hiera('icingaweb2::db_user'), - $db_pass = hiera('icingaweb2::db_pass'), - $db_name = hiera('icingaweb2::db_name'), + $config = hiera('icingaweb2::config'), + $log = hiera('icingaweb2::log'), + $web_path = hiera('icingaweb2::web_path'), + $db_user = hiera('icingaweb2::db_user'), + $db_pass = hiera('icingaweb2::db_pass'), + $db_name = hiera('icingaweb2::db_name'), + $web_group = hiera('icingaweb2::group'), ) { include apache include php + include php_imagick include icingaweb2::config include icingacli include icinga_packages @@ -19,7 +21,7 @@ class icingaweb2_dev ( } # TODO(el): icinga-gui is not a icingaweb2_dev package - package { [ 'php-pdo', 'php-ldap', 'php-phpunit-PHPUnit', 'icinga-gui' ]: + package { [ 'php-gd', 'php-intl', 'php-pdo', 'php-ldap', 'php-phpunit-PHPUnit', 'icinga-gui' ]: ensure => latest, notify => Service['apache'], require => Class['icinga_packages'], @@ -28,7 +30,7 @@ class icingaweb2_dev ( Exec { path => '/usr/local/bin:/usr/bin:/bin' } # TODO(el): Enabling/disabling modules should be a resource - User <| alias == apache |> { groups +> 'icingaweb' } + User <| alias == apache |> { groups +> $web_group } -> exec { 'enable-monitoring-module': command => 'icingacli module enable monitoring', user => 'apache', @@ -50,7 +52,7 @@ class icingaweb2_dev ( file { $log_dir: ensure => directory, owner => 'root', - group => 'icingaweb', + group => $web_group, mode => '2775' } diff --git a/.puppet/profiles/icingaweb2_dev/templates/authentication.ini.erb b/.puppet/profiles/icingaweb2_dev/templates/authentication.ini.erb index f28395e18..87f9f53ed 100644 --- a/.puppet/profiles/icingaweb2_dev/templates/authentication.ini.erb +++ b/.puppet/profiles/icingaweb2_dev/templates/authentication.ini.erb @@ -1,5 +1,5 @@ [autologin] -backend = autologin +backend = external [icingaweb-mysql] backend = db diff --git a/README.md b/README.md index 16eb1444a..55e4e77ee 100644 --- a/README.md +++ b/README.md @@ -2,267 +2,26 @@ ## Table of Contents -0. [General Information](#general information) +0. [About](#about) 1. [Installation](#installation) 2. [Support](#support) -3. [Vagrant - Virtual development environment](#vagrant) -## General Information +## About -`Icinga Web 2` is the next generation monitoring web interface, framework -and CLI tool developed by the [Icinga Project](https://www.icinga.org/community/team/). +**Icinga Web 2** is the next generation open source monitoring web interface, framework +and command-line interface developed by the [Icinga Project](https://www.icinga.org/), supporting Icinga 2, +Icinga Core and any other monitoring backend compatible with the Livestatus Protocol. -Responsive and fast, rewritten from scratch supporting multiple backends and -providing a CLI tool. Compatible with Icinga Core 2.x and 1.x. - -Check the Icinga website for some [insights](https://www.icinga.org/icinga/screenshots/icinga-web-2/). - -> **Note** -> -> `Icinga Web 2` is still in development and not meant for production deployment. -> Watch the [development roadmap](https://dev.icinga.org/projects/icingaweb2/roadmap) -> and [Icinga website](https://www.icinga.org/) for release schedule updates! +![Icinga Web 2](https://www.icinga.org/wp-content/uploads/2014/06/service_detail.png "Icinga Web 2") ## Installation -Please navigate to [doc/installation.md](doc/installation.md) for updated details. +For installing Icinga Web 2 please read [doc/installation.md](doc/installation.md). ## Support -Please head over to the [community support channels](https://www.icinga.org/icinga/faq/get-help/) -in case of questions, bugs, etc. - -Please make sure to provide the following details: - -* OS, distribution, version -* PHP and/or MySQL/PostgreSQL version -* Which browser and its version -* Screenshot and problem description - - -## Vagrant - -### Requirements - -* Vagrant 1.2+ -* Virtualbox 4.2.16+ -* a fairly powerful hardware (quad core, 4gb ram, fast hdd) - -> **Note** -> -> The deployment of the virtual machine is tested against Vagrant starting with version 1.2. -> Unfortunately older versions will not work. - -### General - -The Icinga Web 2 project ships with a Vagrant virtual machine that integrates -the source code with various services and example data in a controlled -environment. This enables developers and users to test Livestatus, status.dat, -MySQL and PostgreSQL backends as well as the LDAP authentication. All you -have to do is install Vagrant and run: - - vagrant up - -> **Note** -> -> The first boot of the vm takes a fairly long time because -> you'll download a plain CentOS base box and Vagrant will automatically -> provision the environment on the first go. - -After you should be able to browse [localhost:8080/icingaweb](http://localhost:8080/icingaweb). - -### Environment - -**Forwarded ports**: - - - - - - - - - - - - - - - - - -
ProctocolLocal port (virtual machine host)Remote port (the virtual machine)
SSH222222
HTTP808080
- -**Installed packages**: - -* Apache2 with PHP enabled -* PHP with MySQL and PostgreSQL libraries -* MySQL server and client software -* PostgreSQL server and client software -* [Icinga prerequisites](http://docs.icinga.org/latest/en/quickstart-idoutils.html#installpackages) -* OpenLDAP servers and clients - -**Installed users and groups**: - -* User icinga with group icinga and icinga-cmd -* Webserver user added to group icinga-cmd - -**Installed software**: - -* Icinga with IDOUtils using a MySQL database -* Icinga with IDOUtils using a PostgreSQL database -* Icinga 2 - -**Installed files**: - -* `/usr/share/icinga/htpasswd.users` account information for logging into the Icinga classic web interface for both icinga instances -* `/usr/lib64/nagios/plugins` Monitoring Plugins for all Icinga instances - -#### Icinga with IDOUtils using a MySQL database - -**Installation path**: `/usr/local/icinga-mysql` - -**Services**: - -* `icinga-mysql` -* `ido2db-mysql` - -Connect to the **icinga mysql database** using the following command: - - mysql -u icinga -p icinga icinga - -Access the **Classic UI** (CGIs) via [localhost:8080/icinga-mysql](http://localhost:8080/icinga-mysql). -For **logging into** the Icinga classic web interface use user *icingaadmin* with password *icinga*. - -#### Icinga with IDOUtils using a PostgreSQL database - -**Installation path**: `/usr/local/icinga-pgsql` - -**Services**: - -* `icinga-pgsql` -* `ido2db-pgsql` - -Connect to the **icinga mysql database** using the following command: - - sudo -u postgres psql -U icinga -d icinga - -Access the **Classic UI** (CGIs) via [localhost:8080/icinga-pgsql](http://localhost:8080/icinga-pgsql). -For **logging into** the Icinga classic web interface use user *icingaadmin* with password *icinga*. - -#### Monitoring Test Config - -Test config is added to both the MySQL and PostgreSQL Icinga instance utilizing the Perl module -**Monitoring::Generator::TestConfig** to generate test config to **/usr/local/share/misc/monitoring_test_config** -which is then copied to **/etc/conf.d/test_config/**. -Configuration can be adjusted and recreated with **/usr/local/share/misc/monitoring_test_config/recreate.pl**. -**Note** that you have to run - - vagrant provision - -in the host after any modification to the script just mentioned. - -#### MK Livestatus - -MK Livestatus is added to the Icinga installation using a MySQL database. - -**Installation path**: - -* `/usr/local/icinga-mysql/bin/unixcat` -* `/usr/local/icinga-mysql/lib/mk-livestatus/livecheck` -* `/usr/local/icinga-mysql/lib/mk-livestatus/livestatus.o` -* `/usr/local/icinga-mysql/etc/modules/mk-livestatus.cfg` -* `/usr/local/icinga-mysql/var/rw/live` - -**Example usage**: - - echo "GET hosts" | /usr/local/icinga-mysql/bin/unixcat /usr/local/icinga-mysql/var/rw/live - -#### LDAP example data - -The environment includes a openldap server with example data. *Domain* suffix is **dc=icinga,dc=org**. -Administrator (*rootDN*) of the slapd configuration database is **cn=admin,cn=config** and the -administrator (*rootDN*) of our database instance is **cn=admin,dc=icinga,dc=org**. Both share -the *password* `admin`. - -Examples to query the slapd configuration database: - - ldapsearch -x -W -LLL -D cn=admin,cn=config -b cn=config dn - ldapsearch -Y EXTERNAL -H ldapi:/// -LLL -b cn=config dn - -Examples to query our database instance: - - ldapsearch -x -W -LLL -D cn=admin,dc=icinga,dc=org -b dc=icinga,dc=org dn - ldapsearch -Y EXTERNAL -H ldapi:/// -LLL -b dc=icinga,dc=org dn - -This is what the **dc=icinga,dc=org** *DIT* looks like: - -> dn: dc=icinga,dc=org -> -> dn: ou=people,dc=icinga,dc=org -> -> dn: ou=groups,dc=icinga,dc=org -> -> dn: cn=Users,ou=groups,dc=icinga,dc=org -> cn: Users -> uniqueMember: cn=Jon Doe,ou=people,dc=icinga,dc=org -> uniqueMember: cn=Jane Smith,ou=people,dc=icinga,dc=org -> uniqueMember: cn=John Q. Public,ou=people,dc=icinga,dc=org -> uniqueMember: cn=Richard Roe,ou=people,dc=icinga,dc=org -> -> dn: cn=John Doe,ou=people,dc=icinga,dc=org -> cn: John Doe -> uid: jdoe -> -> dn: cn=Jane Smith,ou=people,dc=icinga,dc=org -> cn: Jane Smith -> uid: jsmith -> -> dn: cn=John Q. Public,ou=people,dc=icinga,dc=org -> cn: John Q. Public -> uid: jqpublic -> -> dn: cn=Richard Roe,ou=people,dc=icinga,dc=org -> cn: Richard Roe -> uid: rroe - -All users share the password `password`. - -#### Testing the code - -All software required to run tests is installed in the virtual machine. -In order to run all tests you have to execute the following commands: - - vagrant ssh -c /vagrant/test/php/runtests - vagrant ssh -c /vagrant/test/php/checkswag - vagrant ssh -c /vagrant/test/js/runtests - vagrant ssh -c /vagrant/test/js/checkswag - vagrant ssh -c /vagrant/test/frontend/runtests - -`runtests` will execute unit and regression tests and `checkswag` will report -code style issues. - -#### Icinga 2 - -Installed from the Icinga [snapshot package repository](http://packages.icinga.org/epel/). -The configuration is located in `/etc/icinga2`. - -**Example usage**: - - /etc/init.d/icinga2 (start|stop|restart|reload) - - -## Log into Icinga Web 2 - -If you've configure LDAP as authentication backend (which is the default) use the following login credentials: - -> **Username**: jdoe -> **Password**: password - -Have a look at [LDAP example data](#ldap example data) for more accounts. - -Using MySQL as backend: - -> **Username**: icingaadmin -> **Password**: icinga +If you come across problems at some time, the [community support channels](https://support.icinga.org/) +are good places to ask for advice from other users and give some in return. +For status updates check the [Icinga website](https://www.icinga.org/) and the +[Icinga Web 2 development roadmap](https://dev.icinga.org/projects/icingaweb2/roadmap). diff --git a/Vagrantfile b/Vagrantfile index 28b69cab9..1e5e3a073 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -4,7 +4,6 @@ VAGRANTFILE_API_VERSION = "2" VAGRANT_REQUIRED_VERSION = "1.5.0" -# Require 1.2.x at least if ! defined? Vagrant.require_version if Gem::Version.new(Vagrant::VERSION) < Gem::Version.new(VAGRANT_REQUIRED_VERSION) puts "Vagrant >= " + VAGRANT_REQUIRED_VERSION + " required. Your version is " + Vagrant::VERSION diff --git a/application/controllers/AuthenticationController.php b/application/controllers/AuthenticationController.php index 00dae1c6d..4e70894a1 100644 --- a/application/controllers/AuthenticationController.php +++ b/application/controllers/AuthenticationController.php @@ -4,16 +4,17 @@ # namespace Icinga\Application\Controllers; -use Icinga\Authentication\Backend\AutoLoginBackend; -use Icinga\Web\Controller\ActionController; -use Icinga\Forms\Authentication\LoginForm; -use Icinga\Authentication\AuthChain; use Icinga\Application\Config; +use Icinga\Application\Icinga; use Icinga\Application\Logger; +use Icinga\Authentication\AuthChain; +use Icinga\Authentication\Backend\ExternalBackend; use Icinga\Exception\AuthenticationException; -use Icinga\Exception\NotReadableError; use Icinga\Exception\ConfigurationError; +use Icinga\Exception\NotReadableError; +use Icinga\Forms\Authentication\LoginForm; use Icinga\User; +use Icinga\Web\Controller\ActionController; use Icinga\Web\Url; /** @@ -33,10 +34,12 @@ class AuthenticationController extends ActionController */ public function loginAction() { - if (@file_exists(Config::resolvePath('setup.token')) && !@file_exists(Config::resolvePath('config.ini'))) { + $icinga = Icinga::app(); + if ($icinga->setupTokenExists() && $icinga->requiresSetup()) { $this->redirectNow(Url::fromPath('setup')); } + $triedOnlyExternalAuth = null; $auth = $this->Auth(); $this->view->form = $form = new LoginForm(); $this->view->title = $this->translate('Icingaweb Login'); @@ -80,7 +83,7 @@ class AuthenticationController extends ActionController } foreach ($chain as $backend) { - if ($backend instanceof AutoLoginBackend) { + if ($backend instanceof ExternalBackend) { continue; } ++$backendsTried; @@ -124,7 +127,8 @@ class AuthenticationController extends ActionController } elseif ($request->isGet()) { $user = new User(''); foreach ($chain as $backend) { - if ($backend instanceof AutoLoginBackend) { + $triedOnlyExternalAuth = $triedOnlyExternalAuth === null; + if ($backend instanceof ExternalBackend) { $authenticated = $backend->authenticate($user); if ($authenticated === true) { $auth->setAuthenticated($user); @@ -132,6 +136,8 @@ class AuthenticationController extends ActionController Url::fromPath(Url::fromRequest()->getParam('redirect', 'dashboard')) ); } + } else { + $triedOnlyExternalAuth = false; } } } @@ -139,7 +145,8 @@ class AuthenticationController extends ActionController $this->view->errorInfo = $e->getMessage(); } - $this->view->configMissing = is_dir(Config::$configDir) === false; + $this->view->requiresExternalAuth = $triedOnlyExternalAuth && !$auth->isAuthenticated(); + $this->view->requiresSetup = Icinga::app()->requiresSetup(); } /** diff --git a/application/controllers/PreferenceController.php b/application/controllers/PreferenceController.php index 7acab7c25..832f57644 100644 --- a/application/controllers/PreferenceController.php +++ b/application/controllers/PreferenceController.php @@ -7,7 +7,6 @@ use Icinga\Web\Url; use Icinga\Web\Widget\Tab; use Icinga\Application\Config; use Icinga\Forms\PreferenceForm; -use Icinga\Exception\ConfigurationError; use Icinga\User\Preferences\PreferencesStore; /** @@ -40,14 +39,13 @@ class PreferenceController extends BasePreferenceController public function indexAction() { $storeConfig = Config::app()->getSection('preferences'); - if ($storeConfig->isEmpty()) { - throw new ConfigurationError(t('You need to configure how to store preferences first.')); - } $user = $this->getRequest()->getUser(); $form = new PreferenceForm(); $form->setPreferences($user->getPreferences()); - $form->setStore(PreferencesStore::create($storeConfig, $user)); + if ($storeConfig->get('store', 'ini') !== 'none') { + $form->setStore(PreferencesStore::create($storeConfig, $user)); + } $form->handleRequest(); $this->view->form = $form; diff --git a/application/fonts/icingaweb.md b/application/fonts/icingaweb.md new file mode 100644 index 000000000..5699f07b2 --- /dev/null +++ b/application/fonts/icingaweb.md @@ -0,0 +1,9 @@ +# fontello-ifont font files moved + +New target is: public/font + +The font directory has been moved to the public structure because of +Internet Explorer version 8 compatibility. The common way for browsers is to +include the binary embeded font type in the javascript. IE8 falls back and +include one of the provided font sources. Therefore it is important to have +the font files available public and exported by the HTTP server. diff --git a/application/forms/Authentication/LoginForm.php b/application/forms/Authentication/LoginForm.php index a6d69d15a..8be455dcc 100644 --- a/application/forms/Authentication/LoginForm.php +++ b/application/forms/Authentication/LoginForm.php @@ -18,7 +18,7 @@ class LoginForm extends Form public function init() { $this->setName('form_login'); - $this->setSubmitLabel(t('Login')); + $this->setSubmitLabel($this->translate('Login')); } /** @@ -31,8 +31,8 @@ class LoginForm extends Form 'username', array( 'required' => true, - 'label' => t('Username'), - 'placeholder' => t('Please enter your username...'), + 'label' => $this->translate('Username'), + 'placeholder' => $this->translate('Please enter your username...'), 'class' => false === isset($formData['username']) ? 'autofocus' : '' ) ); @@ -41,8 +41,8 @@ class LoginForm extends Form 'password', array( 'required' => true, - 'label' => t('Password'), - 'placeholder' => t('...and your password'), + 'label' => $this->translate('Password'), + 'placeholder' => $this->translate('...and your password'), 'class' => isset($formData['username']) ? 'autofocus' : '' ) ); diff --git a/application/forms/Config/Authentication/DbBackendForm.php b/application/forms/Config/Authentication/DbBackendForm.php index 572a09c2e..d3a5af51d 100644 --- a/application/forms/Config/Authentication/DbBackendForm.php +++ b/application/forms/Config/Authentication/DbBackendForm.php @@ -53,8 +53,8 @@ class DbBackendForm extends Form 'name', array( 'required' => true, - 'label' => t('Backend Name'), - 'description' => t( + 'label' => $this->translate('Backend Name'), + 'description' => $this->translate( 'The name of this authentication provider that is used to differentiate it from others' ), ) @@ -64,8 +64,10 @@ class DbBackendForm extends Form 'resource', array( 'required' => true, - 'label' => t('Database Connection'), - 'description' => t('The database connection to use for authenticating with this provider'), + 'label' => $this->translate('Database Connection'), + 'description' => $this->translate( + 'The database connection to use for authenticating with this provider' + ), 'multiOptions' => false === empty($this->resources) ? array_combine($this->resources, $this->resources) : array() @@ -107,11 +109,11 @@ class DbBackendForm extends Form try { $dbUserBackend = new DbUserBackend(ResourceFactory::createResource($form->getResourceConfig())); if ($dbUserBackend->count() < 1) { - $form->addError(t('No users found under the specified database backend')); + $form->addError($form->translate('No users found under the specified database backend')); return false; } } catch (Exception $e) { - $form->addError(sprintf(t('Using the specified backend failed: %s'), $e->getMessage())); + $form->addError(sprintf($form->translate('Using the specified backend failed: %s'), $e->getMessage())); return false; } diff --git a/application/forms/Config/Authentication/AutologinBackendForm.php b/application/forms/Config/Authentication/ExternalBackendForm.php similarity index 73% rename from application/forms/Config/Authentication/AutologinBackendForm.php rename to application/forms/Config/Authentication/ExternalBackendForm.php index a21d2c006..51000b2d2 100644 --- a/application/forms/Config/Authentication/AutologinBackendForm.php +++ b/application/forms/Config/Authentication/ExternalBackendForm.php @@ -8,16 +8,16 @@ use Zend_Validate_Callback; use Icinga\Web\Form; /** - * Form class for adding/modifying autologin authentication backends + * Form class for adding/modifying authentication backends of type "external" */ -class AutologinBackendForm extends Form +class ExternalBackendForm extends Form { /** * Initialize this form */ public function init() { - $this->setName('form_config_authbackend_autologin'); + $this->setName('form_config_authbackend_external'); } /** @@ -30,8 +30,8 @@ class AutologinBackendForm extends Form 'name', array( 'required' => true, - 'label' => t('Backend Name'), - 'description' => t( + 'label' => $this->translate('Backend Name'), + 'description' => $this->translate( 'The name of this authentication provider that is used to differentiate it from others' ), 'validators' => array( @@ -52,9 +52,11 @@ class AutologinBackendForm extends Form 'text', 'strip_username_regexp', array( - 'label' => t('Filter Pattern'), - 'description' => t('The regular expression to use to strip specific parts off from usernames. Leave empty if you do not want to strip off anything'), - 'value' => '/\@[^$]+$/', + 'label' => $this->translate('Filter Pattern'), + 'description' => $this->translate( + 'The regular expression to use to strip specific parts off from usernames.' + . ' Leave empty if you do not want to strip off anything' + ), 'validators' => array( new Zend_Validate_Callback(function ($value) { return @preg_match($value, '') !== false; @@ -67,7 +69,7 @@ class AutologinBackendForm extends Form 'backend', array( 'disabled' => true, - 'value' => 'autologin' + 'value' => 'external' ) ); @@ -77,7 +79,7 @@ class AutologinBackendForm extends Form /** * Validate the configuration by creating a backend and requesting the user count * - * Returns always true as autologin backends are just "passive" backends. (The webserver authenticates users.) + * Returns always true as backends of type "external" are just "passive" backends. * * @param Form $form The form to fetch the configuration values from * diff --git a/application/forms/Config/Authentication/LdapBackendForm.php b/application/forms/Config/Authentication/LdapBackendForm.php index 9b48c3dbc..1b8fc3f11 100644 --- a/application/forms/Config/Authentication/LdapBackendForm.php +++ b/application/forms/Config/Authentication/LdapBackendForm.php @@ -54,8 +54,8 @@ class LdapBackendForm extends Form 'name', array( 'required' => true, - 'label' => t('Backend Name'), - 'description' => t( + 'label' => $this->translate('Backend Name'), + 'description' => $this->translate( 'The name of this authentication provider that is used to differentiate it from others' ) ) @@ -65,8 +65,8 @@ class LdapBackendForm extends Form 'resource', array( 'required' => true, - 'label' => t('LDAP Resource'), - 'description' => t('The resource to use for authenticating with this provider'), + 'label' => $this->translate('LDAP Resource'), + 'description' => $this->translate('The resource to use for authenticating with this provider'), 'multiOptions' => false === empty($this->resources) ? array_combine($this->resources, $this->resources) : array() @@ -77,8 +77,8 @@ class LdapBackendForm extends Form 'user_class', array( 'required' => true, - 'label' => t('LDAP User Object Class'), - 'description' => t('The object class used for storing users on the ldap server'), + 'label' => $this->translate('LDAP User Object Class'), + 'description' => $this->translate('The object class used for storing users on the ldap server'), 'value' => 'inetOrgPerson' ) ); @@ -87,8 +87,10 @@ class LdapBackendForm extends Form 'user_name_attribute', array( 'required' => true, - 'label' => t('LDAP User Name Attribute'), - 'description' => t('The attribute name used for storing the user name on the ldap server'), + 'label' => $this->translate('LDAP User Name Attribute'), + 'description' => $this->translate( + 'The attribute name used for storing the user name on the ldap server' + ), 'value' => 'uid' ) ); @@ -105,9 +107,11 @@ class LdapBackendForm extends Form 'base_dn', array( 'required' => false, - 'label' => t('Base DN'), - 'description' => t('The path where users can be found on the ldap server. ' . - ' Leave empty to select all users available on the specified resource.') + 'label' => $this->translate('Base DN'), + 'description' => $this->translate( + 'The path where users can be found on the ldap server. Leave ' . + 'empty to select all users available on the specified resource.' + ) ) ); return $this; @@ -146,7 +150,7 @@ class LdapBackendForm extends Form $form->addError($e->getMessage()); return false; } catch (Exception $e) { - $form->addError(sprintf(t('Unable to validate authentication: %s'), $e->getMessage())); + $form->addError(sprintf($form->translate('Unable to validate authentication: %s'), $e->getMessage())); return false; } diff --git a/application/forms/Config/AuthenticationBackendConfigForm.php b/application/forms/Config/AuthenticationBackendConfigForm.php index 12f407c69..de3093ada 100644 --- a/application/forms/Config/AuthenticationBackendConfigForm.php +++ b/application/forms/Config/AuthenticationBackendConfigForm.php @@ -14,7 +14,7 @@ use Icinga\Data\ResourceFactory; use Icinga\Exception\ConfigurationError; use Icinga\Forms\Config\Authentication\DbBackendForm; use Icinga\Forms\Config\Authentication\LdapBackendForm; -use Icinga\Forms\Config\Authentication\AutologinBackendForm; +use Icinga\Forms\Config\Authentication\ExternalBackendForm; class AuthenticationBackendConfigForm extends ConfigForm { @@ -31,7 +31,7 @@ class AuthenticationBackendConfigForm extends ConfigForm public function init() { $this->setName('form_config_authbackend'); - $this->setSubmitLabel(t('Save Changes')); + $this->setSubmitLabel($this->translate('Save Changes')); } /** @@ -67,10 +67,10 @@ class AuthenticationBackendConfigForm extends ConfigForm } elseif ($type === 'ldap') { $form = new LdapBackendForm(); $form->setResources(isset($this->resources['ldap']) ? $this->resources['ldap'] : array()); - } elseif ($type === 'autologin') { - $form = new AutologinBackendForm(); + } elseif ($type === 'external') { + $form = new ExternalBackendForm(); } else { - throw new InvalidArgumentException(sprintf(t('Invalid backend type "%s" provided'), $type)); + throw new InvalidArgumentException(sprintf($this->translate('Invalid backend type "%s" provided'), $type)); } return $form; @@ -91,9 +91,9 @@ class AuthenticationBackendConfigForm extends ConfigForm { $name = isset($values['name']) ? $values['name'] : ''; if (! $name) { - throw new InvalidArgumentException(t('Authentication backend name missing')); + throw new InvalidArgumentException($this->translate('Authentication backend name missing')); } elseif ($this->config->hasSection($name)) { - throw new InvalidArgumentException(t('Authentication backend already exists')); + throw new InvalidArgumentException($this->translate('Authentication backend already exists')); } unset($values['name']); @@ -114,11 +114,11 @@ class AuthenticationBackendConfigForm extends ConfigForm public function edit($name, array $values) { if (! $name) { - throw new InvalidArgumentException(t('Old authentication backend name missing')); + throw new InvalidArgumentException($this->translate('Old authentication backend name missing')); } elseif (! ($newName = isset($values['name']) ? $values['name'] : '')) { - throw new InvalidArgumentException(t('New authentication backend name missing')); + throw new InvalidArgumentException($this->translate('New authentication backend name missing')); } elseif (! $this->config->hasSection($name)) { - throw new InvalidArgumentException(t('Unknown authentication backend provided')); + throw new InvalidArgumentException($this->translate('Unknown authentication backend provided')); } $backendConfig = $this->config->getSection($name); @@ -144,9 +144,9 @@ class AuthenticationBackendConfigForm extends ConfigForm public function remove($name) { if (! $name) { - throw new InvalidArgumentException(t('Authentication backend name missing')); + throw new InvalidArgumentException($this->translate('Authentication backend name missing')); } elseif (! $this->config->hasSection($name)) { - throw new InvalidArgumentException(t('Unknown authentication backend provided')); + throw new InvalidArgumentException($this->translate('Unknown authentication backend provided')); } $backendConfig = $this->config->getSection($name); @@ -167,9 +167,9 @@ class AuthenticationBackendConfigForm extends ConfigForm public function move($name, $position) { if (! $name) { - throw new InvalidArgumentException(t('Authentication backend name missing')); + throw new InvalidArgumentException($this->translate('Authentication backend name missing')); } elseif (! $this->config->hasSection($name)) { - throw new InvalidArgumentException(t('Unknown authentication backend provided')); + throw new InvalidArgumentException($this->translate('Unknown authentication backend provided')); } $backendOrder = $this->config->keys(); @@ -208,10 +208,10 @@ class AuthenticationBackendConfigForm extends ConfigForm try { if ($authBackend === null) { // create new backend $this->add($this->getValues()); - $message = t('Authentication backend "%s" has been successfully created'); + $message = $this->translate('Authentication backend "%s" has been successfully created'); } else { // edit existing backend $this->edit($authBackend, $this->getValues()); - $message = t('Authentication backend "%s" has been successfully changed'); + $message = $this->translate('Authentication backend "%s" has been successfully changed'); } } catch (InvalidArgumentException $e) { Notification::error($e->getMessage()); @@ -237,11 +237,13 @@ class AuthenticationBackendConfigForm extends ConfigForm $authBackend = $this->request->getQuery('auth_backend'); if ($authBackend !== null) { if ($authBackend === '') { - throw new ConfigurationError(t('Authentication backend name missing')); + throw new ConfigurationError($this->translate('Authentication backend name missing')); } elseif (! $this->config->hasSection($authBackend)) { - throw new ConfigurationError(t('Unknown authentication backend provided')); + throw new ConfigurationError($this->translate('Unknown authentication backend provided')); } elseif ($this->config->getSection($authBackend)->backend === null) { - throw new ConfigurationError(sprintf(t('Backend "%s" has no `backend\' setting'), $authBackend)); + throw new ConfigurationError( + sprintf($this->translate('Backend "%s" has no `backend\' setting'), $authBackend) + ); } $configValues = $this->config->getSection($authBackend)->toArray(); @@ -249,15 +251,15 @@ class AuthenticationBackendConfigForm extends ConfigForm $configValues['name'] = $authBackend; $this->populate($configValues); } elseif (empty($this->resources)) { - $autologinBackends = array_filter( + $externalBackends = array_filter( $this->config->toArray(), function ($authBackendCfg) { - return isset($authBackendCfg['backend']) && $authBackendCfg['backend'] === 'autologin'; + return isset($authBackendCfg['backend']) && $authBackendCfg['backend'] === 'external'; } ); - if (false === empty($autologinBackends)) { - throw new ConfigurationError(t('Could not find any resources for authentication')); + if (false === empty($externalBackends)) { + throw new ConfigurationError($this->translate('Could not find any resources for authentication')); } } } @@ -276,8 +278,8 @@ class AuthenticationBackendConfigForm extends ConfigForm array( 'order' => 0, 'ignore' => true, - 'label' => t('Force Changes'), - 'description' => t('Check this box to enforce changes without connectivity validation') + 'label' => $this->translate('Force Changes'), + 'description' => $this->translate('Check this box to enforce changes without connectivity validation') ) ); } @@ -291,20 +293,20 @@ class AuthenticationBackendConfigForm extends ConfigForm $backendType = isset($formData['type']) ? $formData['type'] : null; if (isset($this->resources['db'])) { - $backendTypes['db'] = t('Database'); + $backendTypes['db'] = $this->translate('Database'); } if (isset($this->resources['ldap']) && ($backendType === 'ldap' || Platform::extensionLoaded('ldap'))) { $backendTypes['ldap'] = 'LDAP'; } - $autologinBackends = array_filter( + $externalBackends = array_filter( $this->config->toArray(), function ($authBackendCfg) { - return isset($authBackendCfg['backend']) && $authBackendCfg['backend'] === 'autologin'; + return isset($authBackendCfg['backend']) && $authBackendCfg['backend'] === 'external'; } ); - if ($backendType === 'autologin' || empty($autologinBackends)) { - $backendTypes['autologin'] = t('Autologin'); + if ($backendType === 'external' || empty($externalBackends)) { + $backendTypes['external'] = $this->translate('External'); } if ($backendType === null) { @@ -318,8 +320,10 @@ class AuthenticationBackendConfigForm extends ConfigForm 'ignore' => true, 'required' => true, 'autosubmit' => true, - 'label' => t('Backend Type'), - 'description' => t('The type of the resource to use for this authenticaton provider'), + 'label' => $this->translate('Backend Type'), + 'description' => $this->translate( + 'The type of the resource to use for this authenticaton provider' + ), 'multiOptions' => $backendTypes ) ); diff --git a/application/forms/Config/AuthenticationBackendReorderForm.php b/application/forms/Config/AuthenticationBackendReorderForm.php index 07200827a..a41224248 100644 --- a/application/forms/Config/AuthenticationBackendReorderForm.php +++ b/application/forms/Config/AuthenticationBackendReorderForm.php @@ -52,7 +52,7 @@ class AuthenticationBackendReorderForm extends ConfigForm try { if ($configForm->move($backendName, $position)->save()) { - Notification::success(t('Authentication order updated!')); + Notification::success($this->translate('Authentication order updated!')); } else { return false; } diff --git a/application/forms/Config/General/ApplicationConfigForm.php b/application/forms/Config/General/ApplicationConfigForm.php index 95ad22071..29b7b512e 100644 --- a/application/forms/Config/General/ApplicationConfigForm.php +++ b/application/forms/Config/General/ApplicationConfigForm.php @@ -4,10 +4,8 @@ namespace Icinga\Forms\Config\General; -use DateTimeZone; use Icinga\Application\Icinga; use Icinga\Data\ResourceFactory; -use Icinga\Util\Translator; use Icinga\Web\Form; @@ -33,10 +31,10 @@ class ApplicationConfigForm extends Form 'text', 'global_module_path', array( - 'label' => t('Module Path'), + 'label' => $this->translate('Module Path'), 'required' => true, 'value' => implode(':', Icinga::app()->getModuleManager()->getModuleDirs()), - 'description' => t( + 'description' => $this->translate( 'Contains the directories that will be searched for available modules, separated by ' . 'colons. Modules that don\'t exist in these directories can still be symlinked in ' . 'the module folder, but won\'t show up in the list of disabled modules.' @@ -46,19 +44,19 @@ class ApplicationConfigForm extends Form $this->addElement( 'select', - 'preferences_type', + 'preferences_store', array( 'required' => true, 'autosubmit' => true, - 'label' => t('User Preference Storage Type'), + 'label' => $this->translate('User Preference Storage Type'), 'multiOptions' => array( - 'ini' => t('File System (INI Files)'), - 'db' => t('Database'), - 'null' => t('Don\'t Store Preferences') + 'ini' => $this->translate('File System (INI Files)'), + 'db' => $this->translate('Database'), + 'none' => $this->translate('Don\'t Store Preferences') ) ) ); - if (isset($formData['preferences_type']) && $formData['preferences_type'] === 'db') { + if (isset($formData['preferences_store']) && $formData['preferences_store'] === 'db') { $backends = array(); foreach (ResourceFactory::getResourceConfigs()->toArray() as $name => $resource) { if ($resource['type'] === 'db') { @@ -72,7 +70,7 @@ class ApplicationConfigForm extends Form array( 'required' => true, 'multiOptions' => $backends, - 'label' => t('Database Connection') + 'label' => $this->translate('Database Connection') ) ); } diff --git a/application/forms/Config/General/LoggingConfigForm.php b/application/forms/Config/General/LoggingConfigForm.php index deed06011..997bd558a 100644 --- a/application/forms/Config/General/LoggingConfigForm.php +++ b/application/forms/Config/General/LoggingConfigForm.php @@ -4,7 +4,6 @@ namespace Icinga\Forms\Config\General; -use Icinga\Application\Icinga; use Icinga\Application\Logger; use Icinga\Web\Form; use Icinga\Web\Form\Validator\WritablePathValidator; @@ -31,12 +30,12 @@ class LoggingConfigForm extends Form array( 'required' => true, 'autosubmit' => true, - 'label' => t('Logging Type'), - 'description' => t('The type of logging to utilize.'), + 'label' => $this->translate('Logging Type'), + 'description' => $this->translate('The type of logging to utilize.'), 'multiOptions' => array( 'syslog' => 'Syslog', - 'file' => t('File', 'app.config.logging.type'), - 'none' => t('None', 'app.config.logging.type') + 'file' => $this->translate('File', 'app.config.logging.type'), + 'none' => $this->translate('None', 'app.config.logging.type') ) ) ); @@ -47,13 +46,13 @@ class LoggingConfigForm extends Form 'logging_level', array( 'required' => true, - 'label' => t('Logging Level'), - 'description' => t('The maximum logging level to emit.'), + 'label' => $this->translate('Logging Level'), + 'description' => $this->translate('The maximum logging level to emit.'), 'multiOptions' => array( - Logger::$levels[Logger::ERROR] => t('Error', 'app.config.logging.level'), - Logger::$levels[Logger::WARNING] => t('Warning', 'app.config.logging.level'), - Logger::$levels[Logger::INFO] => t('Information', 'app.config.logging.level'), - Logger::$levels[Logger::DEBUG] => t('Debug', 'app.config.logging.level') + Logger::$levels[Logger::ERROR] => $this->translate('Error', 'app.config.logging.level'), + Logger::$levels[Logger::WARNING] => $this->translate('Warning', 'app.config.logging.level'), + Logger::$levels[Logger::INFO] => $this->translate('Information', 'app.config.logging.level'), + Logger::$levels[Logger::DEBUG] => $this->translate('Debug', 'app.config.logging.level') ) ) ); @@ -65,9 +64,11 @@ class LoggingConfigForm extends Form 'logging_application', array( 'required' => true, - 'label' => t('Application Prefix'), - 'description' => t('The name of the application by which to prefix syslog messages.'), - 'value' => 'icingaweb', + 'label' => $this->translate('Application Prefix'), + 'description' => $this->translate( + 'The name of the application by which to prefix syslog messages.' + ), + 'value' => 'icingaweb2', 'validators' => array( array( 'Regex', @@ -91,8 +92,8 @@ class LoggingConfigForm extends Form // 'logging_facility', // array( // 'required' => true, -// 'label' => t('Facility'), -// 'description' => t('The syslog facility to utilize.'), +// 'label' => $this->translate('Facility'), +// 'description' => $this->translate('The syslog facility to utilize.'), // 'multiOptions' => array( // 'user' => 'LOG_USER' // ) @@ -104,9 +105,9 @@ class LoggingConfigForm extends Form 'logging_file', array( 'required' => true, - 'label' => t('File path'), - 'description' => t('The full path to the log file to write messages to.'), - 'value' => $this->getDefaultLogDir(), + 'label' => $this->translate('File path'), + 'description' => $this->translate('The full path to the log file to write messages to.'), + 'value' => '/var/log/icingaweb2/icingaweb2.log', 'validators' => array(new WritablePathValidator()) ) ); @@ -114,14 +115,4 @@ class LoggingConfigForm extends Form return $this; } - - /** - * Return the default logging directory for type 'file' - * - * @return string - */ - protected function getDefaultLogDir() - { - return realpath(Icinga::app()->getApplicationDir('../var/log/icingaweb.log')); - } } diff --git a/application/forms/Config/GeneralConfigForm.php b/application/forms/Config/GeneralConfigForm.php index 0d81bb96b..7e3357d7b 100644 --- a/application/forms/Config/GeneralConfigForm.php +++ b/application/forms/Config/GeneralConfigForm.php @@ -20,7 +20,7 @@ class GeneralConfigForm extends ConfigForm public function init() { $this->setName('form_config_general'); - $this->setSubmitLabel(t('Save Changes')); + $this->setSubmitLabel($this->translate('Save Changes')); } /** @@ -52,7 +52,7 @@ class GeneralConfigForm extends ConfigForm } if ($this->save()) { - Notification::success(t('New configuration has successfully been stored')); + Notification::success($this->translate('New configuration has successfully been stored')); } else { return false; } diff --git a/application/forms/Config/Resource/DbResourceForm.php b/application/forms/Config/Resource/DbResourceForm.php index 36e69e9e1..97dd951d1 100644 --- a/application/forms/Config/Resource/DbResourceForm.php +++ b/application/forms/Config/Resource/DbResourceForm.php @@ -41,8 +41,8 @@ class DbResourceForm extends Form 'name', array( 'required' => true, - 'label' => t('Resource Name'), - 'description' => t('The unique name of this resource') + 'label' => $this->translate('Resource Name'), + 'description' => $this->translate('The unique name of this resource') ) ); $this->addElement( @@ -50,8 +50,8 @@ class DbResourceForm extends Form 'db', array( 'required' => true, - 'label' => t('Database Type'), - 'description' => t('The type of SQL database'), + 'label' => $this->translate('Database Type'), + 'description' => $this->translate('The type of SQL database'), 'multiOptions' => $dbChoices ) ); @@ -60,8 +60,8 @@ class DbResourceForm extends Form 'host', array ( 'required' => true, - 'label' => t('Host'), - 'description' => t('The hostname of the database'), + 'label' => $this->translate('Host'), + 'description' => $this->translate('The hostname of the database'), 'value' => 'localhost' ) ); @@ -70,8 +70,8 @@ class DbResourceForm extends Form 'port', array( 'required' => true, - 'label' => t('Port'), - 'description' => t('The port to use'), + 'label' => $this->translate('Port'), + 'description' => $this->translate('The port to use'), 'value' => 3306 ) ); @@ -80,8 +80,8 @@ class DbResourceForm extends Form 'dbname', array( 'required' => true, - 'label' => t('Database Name'), - 'description' => t('The name of the database to use') + 'label' => $this->translate('Database Name'), + 'description' => $this->translate('The name of the database to use') ) ); $this->addElement( @@ -89,8 +89,8 @@ class DbResourceForm extends Form 'username', array ( 'required' => true, - 'label' => t('Username'), - 'description' => t('The user name to use for authentication') + 'label' => $this->translate('Username'), + 'description' => $this->translate('The user name to use for authentication') ) ); $this->addElement( @@ -99,8 +99,8 @@ class DbResourceForm extends Form array( 'required' => true, 'renderPassword' => true, - 'label' => t('Password'), - 'description' => t('The password to use for authentication') + 'label' => $this->translate('Password'), + 'description' => $this->translate('The password to use for authentication') ) ); @@ -132,7 +132,9 @@ class DbResourceForm extends Form $resource = ResourceFactory::createResource(new ConfigObject($form->getValues())); $resource->getConnection()->getConnection(); } catch (Exception $e) { - $form->addError(t('Connectivity validation failed, connection to the given resource not possible.')); + $form->addError( + $form->translate('Connectivity validation failed, connection to the given resource not possible.') + ); return false; } diff --git a/application/forms/Config/Resource/FileResourceForm.php b/application/forms/Config/Resource/FileResourceForm.php index 8e2920313..960926114 100644 --- a/application/forms/Config/Resource/FileResourceForm.php +++ b/application/forms/Config/Resource/FileResourceForm.php @@ -30,8 +30,8 @@ class FileResourceForm extends Form 'name', array( 'required' => true, - 'label' => t('Resource Name'), - 'description' => t('The unique name of this resource') + 'label' => $this->translate('Resource Name'), + 'description' => $this->translate('The unique name of this resource') ) ); $this->addElement( @@ -39,8 +39,8 @@ class FileResourceForm extends Form 'filename', array( 'required' => true, - 'label' => t('Filepath'), - 'description' => t('The filename to fetch information from'), + 'label' => $this->translate('Filepath'), + 'description' => $this->translate('The filename to fetch information from'), 'validators' => array(new ReadablePathValidator()) ) ); @@ -49,8 +49,8 @@ class FileResourceForm extends Form 'fields', array( 'required' => true, - 'label' => t('Pattern'), - 'description' => t('The regular expression by which to identify columns') + 'label' => $this->translate('Pattern'), + 'description' => $this->translate('The regular expression by which to identify columns') ) ); diff --git a/application/forms/Config/Resource/LdapResourceForm.php b/application/forms/Config/Resource/LdapResourceForm.php index 6641b96bb..3293546c5 100644 --- a/application/forms/Config/Resource/LdapResourceForm.php +++ b/application/forms/Config/Resource/LdapResourceForm.php @@ -32,8 +32,8 @@ class LdapResourceForm extends Form 'name', array( 'required' => true, - 'label' => t('Resource Name'), - 'description' => t('The unique name of this resource') + 'label' => $this->translate('Resource Name'), + 'description' => $this->translate('The unique name of this resource') ) ); $this->addElement( @@ -41,8 +41,10 @@ class LdapResourceForm extends Form 'hostname', array( 'required' => true, - 'label' => t('Host'), - 'description' => t('The hostname or address of the LDAP server to use for authentication'), + 'label' => $this->translate('Host'), + 'description' => $this->translate( + 'The hostname or address of the LDAP server to use for authentication' + ), 'value' => 'localhost' ) ); @@ -51,8 +53,8 @@ class LdapResourceForm extends Form 'port', array( 'required' => true, - 'label' => t('Port'), - 'description' => t('The port of the LDAP server to use for authentication'), + 'label' => $this->translate('Port'), + 'description' => $this->translate('The port of the LDAP server to use for authentication'), 'value' => 389 ) ); @@ -61,8 +63,10 @@ class LdapResourceForm extends Form 'root_dn', array( 'required' => true, - 'label' => t('Root DN'), - 'description' => t('Only the root and its child nodes will be accessible on this resource.') + 'label' => $this->translate('Root DN'), + 'description' => $this->translate( + 'Only the root and its child nodes will be accessible on this resource.' + ) ) ); $this->addElement( @@ -70,8 +74,8 @@ class LdapResourceForm extends Form 'bind_dn', array( 'required' => true, - 'label' => t('Bind DN'), - 'description' => t('The user dn to use for querying the ldap server') + 'label' => $this->translate('Bind DN'), + 'description' => $this->translate('The user dn to use for querying the ldap server') ) ); $this->addElement( @@ -80,8 +84,8 @@ class LdapResourceForm extends Form array( 'required' => true, 'renderPassword' => true, - 'label' => t('Bind Password'), - 'description' => t('The password to use for querying the ldap server') + 'label' => $this->translate('Bind Password'), + 'description' => $this->translate('The password to use for querying the ldap server') ) ); @@ -119,7 +123,9 @@ class LdapResourceForm extends Form throw new Exception(); } } catch (Exception $e) { - $form->addError(t('Connectivity validation failed, connection to the given resource not possible.')); + $form->addError( + $form->translate('Connectivity validation failed, connection to the given resource not possible.') + ); return false; } diff --git a/application/forms/Config/Resource/LivestatusResourceForm.php b/application/forms/Config/Resource/LivestatusResourceForm.php index d90600370..e893a4657 100644 --- a/application/forms/Config/Resource/LivestatusResourceForm.php +++ b/application/forms/Config/Resource/LivestatusResourceForm.php @@ -33,8 +33,8 @@ class LivestatusResourceForm extends Form 'name', array( 'required' => true, - 'label' => t('Resource Name'), - 'description' => t('The unique name of this resource') + 'label' => $this->translate('Resource Name'), + 'description' => $this->translate('The unique name of this resource') ) ); $this->addElement( @@ -42,9 +42,9 @@ class LivestatusResourceForm extends Form 'socket', array( 'required' => true, - 'label' => t('Socket'), - 'description' => t('The path to your livestatus socket used for querying monitoring data'), - 'value' => realpath(Icinga::app()->getApplicationDir() . '/../var/rw/livestatus') + 'label' => $this->translate('Socket'), + 'description' => $this->translate('The path to your livestatus socket used for querying monitoring data'), + 'value' => '/var/run/icinga2/cmd/livestatus' ) ); @@ -75,8 +75,10 @@ class LivestatusResourceForm extends Form try { $resource = ResourceFactory::createResource(new ConfigObject($form->getValues())); $resource->connect()->disconnect(); - } catch (Exception $e) { - $form->addError(t('Connectivity validation failed, connection to the given resource not possible.')); + } catch (Exception $_) { + $form->addError( + $form->translate('Connectivity validation failed, connection to the given resource not possible.') + ); return false; } diff --git a/application/forms/Config/ResourceConfigForm.php b/application/forms/Config/ResourceConfigForm.php index e7933c18f..67912142a 100644 --- a/application/forms/Config/ResourceConfigForm.php +++ b/application/forms/Config/ResourceConfigForm.php @@ -22,7 +22,7 @@ class ResourceConfigForm extends ConfigForm public function init() { $this->setName('form_config_resource'); - $this->setSubmitLabel(t('Save Changes')); + $this->setSubmitLabel($this->translate('Save Changes')); } /** @@ -43,7 +43,7 @@ class ResourceConfigForm extends ConfigForm } elseif ($type === 'file') { return new FileResourceForm(); } else { - throw new InvalidArgumentException(sprintf(t('Invalid resource type "%s" provided'), $type)); + throw new InvalidArgumentException(sprintf($this->translate('Invalid resource type "%s" provided'), $type)); } } @@ -62,9 +62,9 @@ class ResourceConfigForm extends ConfigForm { $name = isset($values['name']) ? $values['name'] : ''; if (! $name) { - throw new InvalidArgumentException(t('Resource name missing')); + throw new InvalidArgumentException($this->translate('Resource name missing')); } elseif ($this->config->hasSection($name)) { - throw new InvalidArgumentException(t('Resource already exists')); + throw new InvalidArgumentException($this->translate('Resource already exists')); } unset($values['name']); @@ -85,11 +85,11 @@ class ResourceConfigForm extends ConfigForm public function edit($name, array $values) { if (! $name) { - throw new InvalidArgumentException(t('Old resource name missing')); + throw new InvalidArgumentException($this->translate('Old resource name missing')); } elseif (! ($newName = isset($values['name']) ? $values['name'] : '')) { - throw new InvalidArgumentException(t('New resource name missing')); + throw new InvalidArgumentException($this->translate('New resource name missing')); } elseif (! $this->config->hasSection($name)) { - throw new InvalidArgumentException(t('Unknown resource provided')); + throw new InvalidArgumentException($this->translate('Unknown resource provided')); } $resourceConfig = $this->config->getSection($name); @@ -111,9 +111,9 @@ class ResourceConfigForm extends ConfigForm public function remove($name) { if (! $name) { - throw new InvalidArgumentException(t('Resource name missing')); + throw new InvalidArgumentException($this->translate('Resource name missing')); } elseif (! $this->config->hasSection($name)) { - throw new InvalidArgumentException(t('Unknown resource provided')); + throw new InvalidArgumentException($this->translate('Unknown resource provided')); } $resourceConfig = $this->config->getSection($name); @@ -143,10 +143,10 @@ class ResourceConfigForm extends ConfigForm try { if ($resource === null) { // create new resource $this->add($this->getValues()); - $message = t('Resource "%s" has been successfully created'); + $message = $this->translate('Resource "%s" has been successfully created'); } else { // edit existing resource $this->edit($resource, $this->getValues()); - $message = t('Resource "%s" has been successfully changed'); + $message = $this->translate('Resource "%s" has been successfully changed'); } } catch (InvalidArgumentException $e) { Notification::error($e->getMessage()); @@ -172,9 +172,9 @@ class ResourceConfigForm extends ConfigForm $resource = $this->request->getQuery('resource'); if ($resource !== null) { if ($resource === '') { - throw new ConfigurationError(t('Resource name missing')); + throw new ConfigurationError($this->translate('Resource name missing')); } elseif (! $this->config->hasSection($resource)) { - throw new ConfigurationError(t('Unknown resource provided')); + throw new ConfigurationError($this->translate('Unknown resource provided')); } $configValues = $this->config->getSection($resource)->toArray(); @@ -197,8 +197,8 @@ class ResourceConfigForm extends ConfigForm array( 'order' => 0, 'ignore' => true, - 'label' => t('Force Changes'), - 'description' => t('Check this box to enforce changes without connectivity validation') + 'label' => $this->translate('Force Changes'), + 'description' => $this->translate('Check this box to enforce changes without connectivity validation') ) ); } @@ -211,14 +211,14 @@ class ResourceConfigForm extends ConfigForm $resourceType = isset($formData['type']) ? $formData['type'] : 'db'; $resourceTypes = array( - 'file' => t('File'), + 'file' => $this->translate('File'), 'livestatus' => 'Livestatus', ); if ($resourceType === 'ldap' || Platform::extensionLoaded('ldap')) { $resourceTypes['ldap'] = 'LDAP'; } if ($resourceType === 'db' || Platform::hasMysqlSupport() || Platform::hasPostgresqlSupport()) { - $resourceTypes['db'] = t('SQL Database'); + $resourceTypes['db'] = $this->translate('SQL Database'); } $this->addElement( @@ -227,8 +227,8 @@ class ResourceConfigForm extends ConfigForm array( 'required' => true, 'autosubmit' => true, - 'label' => t('Resource Type'), - 'description' => t('The type of resource'), + 'label' => $this->translate('Resource Type'), + 'description' => $this->translate('The type of resource'), 'multiOptions' => $resourceTypes, 'value' => $resourceType ) diff --git a/application/forms/ConfirmRemovalForm.php b/application/forms/ConfirmRemovalForm.php index 02d7263df..6840db37d 100644 --- a/application/forms/ConfirmRemovalForm.php +++ b/application/forms/ConfirmRemovalForm.php @@ -17,6 +17,6 @@ class ConfirmRemovalForm extends Form public function init() { $this->setName('form_confirm_removal'); - $this->setSubmitLabel(t('Confirm Removal')); + $this->setSubmitLabel($this->translate('Confirm Removal')); } } diff --git a/application/forms/Dashboard/DashletForm.php b/application/forms/Dashboard/DashletForm.php index 6c38ff97e..e58ca8aba 100644 --- a/application/forms/Dashboard/DashletForm.php +++ b/application/forms/Dashboard/DashletForm.php @@ -26,7 +26,7 @@ class DashletForm extends Form { $this->setName('form_dashboard_addurl'); if (! $this->getSubmitLabel()) { - $this->setSubmitLabel(t('Add To Dashboard')); + $this->setSubmitLabel($this->translate('Add To Dashboard')); } $this->setAction(URL::fromRequest()); } @@ -66,9 +66,10 @@ class DashletForm extends Form 'url', array( 'required' => true, - 'label' => t('Url'), - 'description' => - t('Enter url being loaded in the dashlet. You can paste the full URL, including filters.') + 'label' => $this->translate('Url'), + 'description' => $this->translate( + 'Enter url being loaded in the dashlet. You can paste the full URL, including filters.' + ) ) ); $this->addElement( @@ -76,8 +77,8 @@ class DashletForm extends Form 'dashlet', array( 'required' => true, - 'label' => t('Dashlet Title'), - 'description' => t('Enter a title for the dashlet.') + 'label' => $this->translate('Dashlet Title'), + 'description' => $this->translate('Enter a title for the dashlet.') ) ); $this->addElement( @@ -95,9 +96,8 @@ class DashletForm extends Form 'pane', array( 'required' => true, - 'label' => t("New Dashboard Title"), - 'description' => - t('Enter a title for the new pane.') + 'label' => $this->translate("New Dashboard Title"), + 'description' => $this->translate('Enter a title for the new pane.') ) ); } else { @@ -106,10 +106,9 @@ class DashletForm extends Form 'pane', array( 'required' => true, - 'label' => t('Dashboard'), + 'label' => $this->translate('Dashboard'), 'multiOptions' => $panes, - 'description' => - t('Select a pane you want to add the dashlet.') + 'description' => $this->translate('Select a pane you want to add the dashlet.') ) ); } @@ -119,9 +118,9 @@ class DashletForm extends Form 'create_new_pane', array( 'required' => false, - 'label' => t('New dashboard'), + 'label' => $this->translate('New dashboard'), 'class' => 'autosubmit', - 'description' => t('Check this box if you want to add the dashlet to a new dashboard') + 'description' => $this->translate('Check this box if you want to add the dashlet to a new dashboard') ) ); } diff --git a/application/forms/LdapDiscoveryForm.php b/application/forms/LdapDiscoveryForm.php index 0fd0ea0d3..6a14c2ecd 100644 --- a/application/forms/LdapDiscoveryForm.php +++ b/application/forms/LdapDiscoveryForm.php @@ -26,8 +26,8 @@ class LdapDiscoveryForm extends Form 'domain', array( 'required' => true, - 'label' => t('Search Domain'), - 'description' => t('Search this domain for records of available servers.'), + 'label' => $this->translate('Search Domain'), + 'description' => $this->translate('Search this domain for records of available servers.'), ) ); @@ -36,7 +36,7 @@ class LdapDiscoveryForm extends Form 'note', 'additional_description', array( - 'value' => t('No Ldap servers found on this domain.' + 'value' => $this->translate('No Ldap servers found on this domain.' . ' You can try to specify host and port and try again, or just skip this step and ' . 'configure the server manually.' ) @@ -47,8 +47,8 @@ class LdapDiscoveryForm extends Form 'hostname', array( 'required' => false, - 'label' => t('Host'), - 'description' => t('IP or host name to search.'), + 'label' => $this->translate('Host'), + 'description' => $this->translate('IP or hostname to search.'), ) ); @@ -57,8 +57,8 @@ class LdapDiscoveryForm extends Form 'port', array( 'required' => false, - 'label' => t('Port'), - 'description' => t('Port', 389), + 'label' => $this->translate('Port'), + 'description' => $this->translate('Port', 389), ) ); } diff --git a/application/forms/PreferenceForm.php b/application/forms/PreferenceForm.php index e3cfdf319..ed20c58cd 100644 --- a/application/forms/PreferenceForm.php +++ b/application/forms/PreferenceForm.php @@ -86,7 +86,7 @@ class PreferenceForm extends Form */ public function onSuccess() { - $this->preferences = new Preferences($this->store->load()); + $this->preferences = new Preferences($this->store ? $this->store->load() : array()); $webPreferences = $this->preferences->get('icingaweb', array()); foreach ($this->getValues() as $key => $value) { @@ -103,11 +103,11 @@ class PreferenceForm extends Form Session::getSession()->user->setPreferences($this->preferences); try { - if ($this->getElement('btn_submit_preferences')->isChecked()) { + if ($this->store && $this->getElement('btn_submit_preferences')->isChecked()) { $this->save(); - Notification::success(t('Preferences successfully saved')); + Notification::success($this->translate('Preferences successfully saved')); } else { - Notification::success(t('Preferences successfully saved for the current session')); + Notification::success($this->translate('Preferences successfully saved for the current session')); } } catch (Exception $e) { Logger::error($e); @@ -142,13 +142,13 @@ class PreferenceForm extends Form public function createElements(array $formData) { $languages = array(); - $languages['autodetect'] = sprintf(t('Browser (%s)', 'preferences.form'), $this->getLocale()); + $languages['autodetect'] = sprintf($this->translate('Browser (%s)', 'preferences.form'), $this->getLocale()); foreach (Translator::getAvailableLocaleCodes() as $language) { $languages[$language] = $language; } $tzList = array(); - $tzList['autodetect'] = sprintf(t('Browser (%s)', 'preferences.form'), $this->getDefaultTimezone()); + $tzList['autodetect'] = sprintf($this->translate('Browser (%s)', 'preferences.form'), $this->getDefaultTimezone()); foreach (DateTimeZone::listIdentifiers() as $tz) { $tzList[$tz] = $tz; } @@ -158,8 +158,8 @@ class PreferenceForm extends Form 'language', array( 'required' => true, - 'label' => t('Your Current Language'), - 'description' => t('Use the following language to display texts and messages'), + 'label' => $this->translate('Your Current Language'), + 'description' => $this->translate('Use the following language to display texts and messages'), 'multiOptions' => $languages, 'value' => substr(setlocale(LC_ALL, 0), 0, 5) ) @@ -170,8 +170,8 @@ class PreferenceForm extends Form 'timezone', array( 'required' => true, - 'label' => t('Your Current Timezone'), - 'description' => t('Use the following timezone for dates and times'), + 'label' => $this->translate('Your Current Timezone'), + 'description' => $this->translate('Use the following timezone for dates and times'), 'multiOptions' => $tzList, 'value' => $this->getDefaultTimezone() ) @@ -182,29 +182,31 @@ class PreferenceForm extends Form 'show_benchmark', array( 'required' => true, - 'label' => t('Use benchmark') + 'label' => $this->translate('Use benchmark') ) ); - $this->addElement( - 'submit', - 'btn_submit_preferences', - array( - 'ignore' => true, - 'label' => t('Save to the Preferences'), - 'decorators' => array( - 'ViewHelper', - array('HtmlTag', array('tag' => 'div')) + if ($this->store) { + $this->addElement( + 'submit', + 'btn_submit_preferences', + array( + 'ignore' => true, + 'label' => $this->translate('Save to the Preferences'), + 'decorators' => array( + 'ViewHelper', + array('HtmlTag', array('tag' => 'div')) + ) ) - ) - ); + ); + } $this->addElement( 'submit', 'btn_submit_session', array( 'ignore' => true, - 'label' => t('Save for the current Session'), + 'label' => $this->translate('Save for the current Session'), 'decorators' => array( 'ViewHelper', array('HtmlTag', array('tag' => 'div')) diff --git a/application/forms/Security/RoleForm.php b/application/forms/Security/RoleForm.php index 0fb53e858..f32c0cab4 100644 --- a/application/forms/Security/RoleForm.php +++ b/application/forms/Security/RoleForm.php @@ -6,6 +6,7 @@ namespace Icinga\Forms\Security; use InvalidArgumentException; use LogicException; +use Zend_Form_Element; use Icinga\Application\Icinga; use Icinga\Forms\ConfigForm; use Icinga\Util\String; @@ -18,14 +19,14 @@ class RoleForm extends ConfigForm /** * Provided permissions by currently loaded modules * - * @var array + * @type array */ - protected $providedPermissions = array(); + protected $providedPermissions = array('*' => '*'); /** * Provided restrictions by currently loaded modules * - * @var array + * @type array */ protected $providedRestrictions = array(); @@ -35,14 +36,26 @@ class RoleForm extends ConfigForm */ public function init() { + $helper = new Zend_Form_Element('bogus'); foreach (Icinga::app()->getModuleManager()->getLoadedModules() as $module) { foreach ($module->getProvidedPermissions() as $permission) { - /** @var object $permission */ + /** @type object $permission */ $this->providedPermissions[$permission->name] = $permission->name . ': ' . $permission->description; } foreach ($module->getProvidedRestrictions() as $restriction) { - /** @var object $restriction */ - $this->providedRestrictions[$restriction->name] = $restriction->description; + /** @type object $restriction */ + $name = $helper->filterName($restriction->name); // Zend only permits alphanumerics, the underscore, + // the circumflex and any ASCII character in range + // \x7f to \xff (127 to 255) + while (isset($this->providedRestrictions[$name])) { + // Because Zend_Form_Element::filterName() replaces any not permitted character with the empty + // string we may have duplicate names, e.g. 're/striction' and 'restriction' + $name .= '_'; + } + $this->providedRestrictions[$name] = array( + 'description' => $restriction->description, + 'name' => $restriction->name + ); } } } @@ -59,8 +72,8 @@ class RoleForm extends ConfigForm 'name', array( 'required' => true, - 'label' => t('Role Name'), - 'description' => t('The name of the role'), + 'label' => $this->translate('Role Name'), + 'description' => $this->translate('The name of the role'), 'ignore' => true ), ), @@ -68,35 +81,37 @@ class RoleForm extends ConfigForm 'textarea', 'users', array( - 'label' => t('Users'), - 'description' => t('Comma-separated list of users that are assigned to the role') + 'label' => $this->translate('Users'), + 'description' => $this->translate('Comma-separated list of users that are assigned to the role') ), ), array( 'textarea', 'groups', array( - 'label' => t('Groups'), - 'description' => t('Comma-separated list of groups that are assigned to the role') + 'label' => $this->translate('Groups'), + 'description' => $this->translate('Comma-separated list of groups that are assigned to the role') ), ), array( 'multiselect', 'permissions', array( - 'label' => t('Permissions Set'), - 'description' => t('The permissions to grant. You may select more than one permission'), + 'label' => $this->translate('Permissions Set'), + 'description' => $this->translate( + 'The permissions to grant. You may select more than one permission' + ), 'multiOptions' => $this->providedPermissions ) ) )); - foreach ($this->providedRestrictions as $name => $description) { + foreach ($this->providedRestrictions as $name => $spec) { $this->addElement( 'text', $name, array( - 'label' => $name, - 'description' => $description + 'label' => $spec['name'], + 'description' => $spec['description'] ) ); } @@ -120,7 +135,7 @@ class RoleForm extends ConfigForm } if (! $this->config->hasSection($name)) { throw new InvalidArgumentException(sprintf( - t('Can\'t load role \'%s\'. Role does not exist'), + $this->translate('Can\'t load role \'%s\'. Role does not exist'), $name )); } @@ -129,6 +144,15 @@ class RoleForm extends ConfigForm ? String::trimSplit($role['permissions']) : null; $role['name'] = $name; + $restrictions = array(); + foreach ($this->providedRestrictions as $name => $spec) { + if (isset($role[$spec['name']])) { + // Translate restriction names to filtered element names + $restrictions[$name] = $role[$spec['name']]; + unset($role[$spec['name']]); + } + } + $role = array_merge($role, $restrictions); $this->populate($role); return $this; } @@ -152,7 +176,7 @@ class RoleForm extends ConfigForm } if ($this->config->hasSection($name)) { throw new InvalidArgumentException(sprintf( - t('Can\'t add role \'%s\'. Role already exists'), + $this->translate('Can\'t add role \'%s\'. Role already exists'), $name )); } @@ -178,7 +202,7 @@ class RoleForm extends ConfigForm } if (! $this->config->hasSection($name)) { throw new InvalidArgumentException(sprintf( - t('Can\'t remove role \'%s\'. Role does not exist'), + $this->translate('Can\'t remove role \'%s\'. Role does not exist'), $name )); } @@ -211,7 +235,7 @@ class RoleForm extends ConfigForm } else { if (! $this->config->hasSection($name)) { throw new InvalidArgumentException(sprintf( - t('Can\'t update role \'%s\'. Role does not exist'), + $this->translate('Can\'t update role \'%s\'. Role does not exist'), $name )); } @@ -230,6 +254,15 @@ class RoleForm extends ConfigForm if (isset($values['permissions'])) { $values['permissions'] = implode(', ', $values['permissions']); } + $restrictions = array(); + foreach ($this->providedRestrictions as $name => $spec) { + if (isset($values[$name])) { + // Translate filtered element names to restriction names + $restrictions[$spec['name']] = $values[$name]; + unset($values[$name]); + } + } + $values = array_merge($values, $restrictions); return $values; } } diff --git a/application/layouts/scripts/parts/navigation.phtml b/application/layouts/scripts/parts/navigation.phtml index bed44ba5f..dc56b9199 100644 --- a/application/layouts/scripts/parts/navigation.phtml +++ b/application/layouts/scripts/parts/navigation.phtml @@ -3,7 +3,6 @@ use Icinga\Web\Url; use Icinga\Web\Menu; use Icinga\Web\MenuRenderer; -use Icinga\Web\Widget\SearchDashboard; // Don't render a menu for unauthenticated users unless menu is auth aware if (! $this->auth()->isAuthenticated()) { @@ -11,15 +10,16 @@ if (! $this->auth()->isAuthenticated()) { } ?> - diff --git a/application/views/scripts/config/authentication/reorder.phtml b/application/views/scripts/config/authentication/reorder.phtml index 688d99f88..807f80efe 100644 --- a/application/views/scripts/config/authentication/reorder.phtml +++ b/application/views/scripts/config/authentication/reorder.phtml @@ -1,4 +1,4 @@ -
+
diff --git a/application/views/scripts/config/index.phtml b/application/views/scripts/config/index.phtml index dab0acc4f..1ffd120b4 100644 --- a/application/views/scripts/config/index.phtml +++ b/application/views/scripts/config/index.phtml @@ -1,4 +1,4 @@ -
+
tabs->render($this); ?>
diff --git a/application/views/scripts/config/logging.phtml b/application/views/scripts/config/logging.phtml deleted file mode 100644 index da6d886cc..000000000 --- a/application/views/scripts/config/logging.phtml +++ /dev/null @@ -1,35 +0,0 @@ -
-tabs->render($this); ?> -
- -
-form->getErrorMessages(); ?> - -messageBox)): ?> - messageBox->render() ?> - - -successMessage): ?> -
- - escape($this->successMessage); ?> -
- - - -
-

Errors occured when trying to save the project.

-

- The following errors occured when trying to save the configuration: -

-
    - -
  • escape($error) ?>
  • - -
-
- - -form ?> -
- diff --git a/application/views/scripts/config/module.phtml b/application/views/scripts/config/module.phtml index cd6ad5af8..e26ade195 100644 --- a/application/views/scripts/config/module.phtml +++ b/application/views/scripts/config/module.phtml @@ -1,4 +1,4 @@ -
+
tabs ?>

escape($module->getTitle()) ?>

diff --git a/application/views/scripts/config/resource.phtml b/application/views/scripts/config/resource.phtml index c5d4ca0fc..f93b2af82 100644 --- a/application/views/scripts/config/resource.phtml +++ b/application/views/scripts/config/resource.phtml @@ -1,4 +1,4 @@ -
+
diff --git a/application/views/scripts/layout/menu.phtml b/application/views/scripts/layout/menu.phtml index 83196d362..a1e13b060 100644 --- a/application/views/scripts/layout/menu.phtml +++ b/application/views/scripts/layout/menu.phtml @@ -5,7 +5,7 @@ use Icinga\Web\Widget\SearchDashboard; getPane('search')->hasDashlets()): ?>
diff --git a/application/views/scripts/roles/index.phtml b/application/views/scripts/roles/index.phtml index 67c957661..db4a6aef2 100644 --- a/application/views/scripts/roles/index.phtml +++ b/application/views/scripts/roles/index.phtml @@ -1,4 +1,4 @@ -
+

translate('Roles') ?>

@@ -30,7 +30,7 @@ without(...) or $role->shift(...) would be nice! - $restrictions = $role; + $restrictions = clone $role; unset($restrictions['users']); unset($restrictions['groups']); unset($restrictions['permissions']); diff --git a/doc/authentication.md b/doc/authentication.md index d36051e8f..542eb9934 100644 --- a/doc/authentication.md +++ b/doc/authentication.md @@ -24,7 +24,7 @@ For delegating authentication to the web server simply add `autologin` to your a ```` [autologin] -backend = autologin +backend = external ```` If your web server is not configured for authentication though the `autologin` section has no effect. diff --git a/doc/external_authentication.md b/doc/external_authentication.md index 240713038..15df1e1cf 100644 --- a/doc/external_authentication.md +++ b/doc/external_authentication.md @@ -1,90 +1,83 @@ -# Externel Authentication +# External Authentication -It is possible to use the authentication mechanism of the webserver, -instead of using the internal authentication-manager to -authenticate users. This might be useful if you only have very few users, and -user management over *.htaccess* is sufficient, or if you must use some other -authentication mechanism that is only available through your webserver. +It is possible to utilize the authentication mechanism of the webserver instead +of the internal authentication of Icinga Web 2 to authenticate users. This might +be useful if you only have very few users and user management over **.htaccess** +is not sufficient or if you are required to use some other authentication +mechanism that is only available by utilizing the webserver. -When external authentication is used, Icingaweb will entrust the -complete authentication process to the external authentication provider (the webserver): -The provider should take care of authenticating the user and declining -all requests with invalid or missing credentials. When the authentication -was succesful, it should provide the authenticated users name to its php-module -and Icingaweb will assume that the user is authorized to access the page. -Because of this it is very important that the webservers authentication is -configured correctly, as wrong configuration could lead to unauthorized -access to the site, or a broken login-process. +Icinga Web 2 will entrust the complete authentication process to the +authentication provider of the webserver, if external authentication is used. +So it is very important that the webserver's authentication is configured +correctly as wrong configuration might lead to unauthorized access or a +malfunction in the login-process. +## Using External Authentication -## Use External Authentication +External authentication in Icinga Web 2 requires the following preparations: -Using external authentication in Icingaweb requires two steps to work: +1. The external authentication must be set up properly to correctly + authenticate users +2. Icinga Web 2 must be configured to use external authentication -1. The external authentication must be set up correctly to always - authenticate the users. -2. Icingaweb must be configured to use the external authentication. +### Preparing the External Authentication Provider +This step depends heavily on the used webserver and authentication mechanism you +want to use. It is not possible to cover all possibillities and you should +probably read the documentation for your webserver to get detailed instructions +on how to set up authentication properly. -### Prepare the External Authentication Provider - -This step depends heavily on the used webserver and authentication -mechanism you want to use. It is not possible to cover all possibillities -and you should probably read the documentation for your webserver for -detailed instructions on how to set up authentication properly. - -In general, you need to make sure that: - - - All routes require authentication - - Only permitted users are allowed to authenticate +In general you need to make sure that: +- All routes require authentication +- Only permitted users are allowed to authenticate #### Example Configuration for Apache and HTTPDigestAuthentication -The following example will show how to enable external authentication in Apache using -*HTTP Digest Authentication*. +The following example will show how to enable external authentication in Apache +using *HTTP Digest Authentication*. -##### Create users +##### Creating users -To create users for a digest authentication we can use the tool *htdigest*. -We choose *.icingawebdigest* as a name for the created file, containing -the user credentials. +To create users for digest authentication you can use the tool *htdigest*. In +this example **.icingawebdigest** is the name of the file containing the user +credentials. -This command will create a new file with the user *jdoe*. *htdigest* -will prompt you for your password, after it has been executed. If you -want to add more users to the file you need to ommit the *-c* parameter -in all further commands to avoInid the file to be overwritten. +This command creates a new file with the user *jdoe*. *htdigest* will prompt +you for a password. If you want to add more users to the file you need to omit +the *-c* parameter in all following commands to not to overwrite the file. +```` +sudo htdigest -c /etc/icingaweb2/.icingawebdigest "Icinga Web 2" jdoe +```` - sudo htdigest -c /etc/httpd/conf.d/.icingawebdigest "Icingaweb 2" jdoe +##### Configuring the Webserver +The webserver should require authentication for all public Icinga Web 2 files. -##### Set up authentication +```` + + AuthType digest + AuthName "Icinga Web 2" + AuthDigestProvider file + AuthUserFile /etc/icingaweb2/.icingawebdigest + Require valid-user + +```` -The webserver should require authentication for all public icingaweb files. +### Preparing Icinga Web 2 +Once external authentication is set up correctly you need to configure Icinga +Web 2. In case you already completed the setup wizard it is likely that you are +now finished. - - AuthType digest - AuthName "Icingaweb 2" - AuthDigestProvider file - AuthUserFile /etc/httpd/conf.d/.icingawebdigest - Require valid-user - +To get Icinga Web 2 to use external authentication the file +**config/authentication.ini** is required. Just add the following section +called "autologin", or any name of your choice, and save your changes: - -### Prepare Icingaweb +```` +[autologin] +backend = external +```` -When the external authentication is set up correctly, we need -to configure IcingaWeb to use it as an authentication source. The -configuration key *authenticationMode* in the section *global* defines -if the authentication should be handled internally or externally. Since -we want to delegate the authentication to the Webserver we choose -"external" as the new value: - - - [global] - ; ... - authenticationMode = "external" - ; ... - +Congratulations! You are now logged in when visiting Icinga Web 2. \ No newline at end of file diff --git a/doc/installation.md b/doc/installation.md index 88c9c3650..170199832 100644 --- a/doc/installation.md +++ b/doc/installation.md @@ -6,7 +6,7 @@ system and distribution you are running. But it is also possible to install Icin ## Installing Requirements * A web server, e.g. Apache or nginx -* PHP >= 5.3.0 +* 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 * 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 @@ -26,7 +26,7 @@ repository either via git or http protocol using the following URLs: * http://git.icinga.org/icingaweb2.git There is also a browsable version available at -[gi.icinga.org](https://git.icinga.org/?p=icingaweb2.git;a=summary "Icinga Web 2 Git Repository"). +[git.icinga.org](https://git.icinga.org/?p=icingaweb2.git;a=summary "Icinga Web 2 Git Repository"). This version also offers snapshots for easy download which you can use if you do not have git present on your system. ```` @@ -38,25 +38,73 @@ git clone git://git.icinga.org/icingaweb2.git Choose a target directory and move Icinga Web 2 there. ```` -mv icingaweb2 /usr/share/icingaweb +mv icingaweb2 /usr/share/icingaweb2 ```` **Step 3: Configuring the Web Server** Use `icingacli` to generate web server configuration for either Apache or nginx. -*Apache* - +Apache: ```` -./bin/icingacli setup config webserver apache --document-root /usr/share/icingaweb/public +./bin/icingacli setup config webserver apache --document-root /usr/share/icingaweb2/public ```` -*nginx* - +nginx: ```` -./bin/icingacli setup config webserver nginx --document-root /usr/share/icingaweb/public +./bin/icingacli setup config webserver nginx --document-root /usr/share/icingaweb2/public ```` -**Step 4: Web Setup** +**Step 4: Preparing Web Setup** -Visit Icinga Web 2 in your browser and complete installation using 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. + +Add the system group `icingaweb2` in the first place. + +Fedora, RHEL, CentOS, SLES and OpenSUSE: +```` +groupadd -r icingaweb2 +```` + +Debian and Ubuntu: +```` +addgroup --system icingaweb2 +```` + +Add your web server's user to the system group `icingaweb2`: + +Fedora, RHEL and CentOS: +```` +usermod -a -G icingaweb2 apache +```` + +SLES and OpenSUSE: +```` +usermod -G icingaweb2 wwwrun +```` + +Debian and Ubuntu: +```` +usermod -a -G icingaweb2 wwwrun +```` + +Use `icingacli` to create the configuration directory which defaults to **/etc/icingaweb2**: +```` +./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`: +```` +./bin/icingacli setup token create +```` + +In case you do not remember the token you can show it using the `icingacli`: +```` +./bin/icingacli setup token show +```` + +**Step 5: Web Setup** + +Visit Icinga Web 2 in your browser and complete installation using the web setup: /icingaweb2/setup diff --git a/doc/vagrant.md b/doc/vagrant.md new file mode 100644 index 000000000..b1b98b436 --- /dev/null +++ b/doc/vagrant.md @@ -0,0 +1,52 @@ +# Vagrant + +## Requirements + +* Vagrant >= version 1.5 +* VirtualBox or Parallels + +> **Note:** The deployment of the virtual machine is tested against Vagrant starting with version 1.5. +> Unfortunately older versions will not work. + +## General + +The Icinga Web 2 project ships with a Vagrant virtual machine that integrates +the source code with various services and example data in a controlled +environment. This enables developers and users to test Livestatus, +MySQL and PostgreSQL backends as well as the LDAP authentication. All you +have to do is install Vagrant and run: + +```` +vagrant up +```` + +> **Note:** The first boot of the vm takes a fairly long time because +> you'll download a plain CentOS base box and Vagrant will automatically +> provision the environment on the first go. + +After you should be able to browse [localhost:8080/icingaweb2](http://localhost:8080/icingaweb2). + +## Log into Icinga Web 2 + +Both LDAP and a MySQL are configured as authentication backend. Please use one of the following login credentials: + +> LDAP: +>> **Username**: `jdoe` + +>> **Password**: `password` + +>MySQL: +>> **Username**: `icingaadmin` + +>> **Password**: `icinga` + + + +## Testing the Source Code + +All software required to run tests is installed in the virtual machine. +In order to run all tests you have to execute the following command: + +```` +vagrant ssh -c "icingacli test php unit" +```` diff --git a/icingaweb2.spec b/icingaweb2.spec index fb628f995..cd1ee485f 100644 --- a/icingaweb2.spec +++ b/icingaweb2.spec @@ -1,237 +1,271 @@ -#/** -# * This file is part of Icinga Web 2. -# * -# * Icinga Web 2 - Head for multiple monitoring backends. -# * Copyright (C) 2014 Icinga Development Team -# * -# * This program is free software; you can redistribute it and/or -# * modify it under the terms of the GNU General Public License -# * as published by the Free Software Foundation; either version 2 -# * of the License, or (at your option) any later version. -# * -# * This program is distributed in the hope that it will be useful, -# * but WITHOUT ANY WARRANTY; without even the implied warranty of -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# * GNU General Public License for more details. -# * -# * You should have received a copy of the GNU General Public License -# * along with this program; if not, write to the Free Software -# * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# * -# * @copyright 2014 Icinga Development Team -# * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 -# * @author Icinga Development Team -# * -# */ +%define revision 1.beta2 -%define revision 1 - -%define configdir %{_sysconfdir}/%{name} -%define sharedir %{_datadir}/%{name} -%define prefixdir %{_datadir}/%{name} -%define usermodparam -a -G -%define logdir %{_localstatedir}/log/%{name} -%define docdir %{sharedir}/doc - -%if "%{_vendor}" == "suse" -%define phpname php5 -%define phpzendname php5-ZendFramework -%define apache2modphpname apache2-mod_php5 -%endif -# SLE 11 = 1110 -%if 0%{?suse_version} == 1110 -%define phpname php53 -%define apache2modphpname apache2-mod_php53 -%define usermodparam -A -%endif - -%if "%{_vendor}" == "redhat" -%define phpname php -%define phpzendname php-ZendFramework -%endif - -# el5 requires newer php53 rather than php (5.1) -%if 0%{?el5} || 0%{?rhel} == 5 || "%{?dist}" == ".el5" -%define phpname php53 -%endif - -%if "%{_vendor}" == "suse" -%define apacheconfdir %{_sysconfdir}/apache2/conf.d -%define apacheuser wwwrun -%define apachegroup www -%define extcmdfile %{_localstatedir}/run/icinga2/cmd/icinga.cmd -%define livestatussocket %{_localstatedir}/run/icinga2/cmd/livestatus -%endif -%if "%{_vendor}" == "redhat" -%define apacheconfdir %{_sysconfdir}/httpd/conf.d -%define apacheuser apache -%define apachegroup apache -%define extcmdfile %{_localstatedir}/run/icinga2/cmd/icinga.cmd -%define livestatussocket %{_localstatedir}/run/icinga2/cmd/livestatus -%endif - -Summary: Open Source host, service and network monitoring Web UI Name: icingaweb2 -Version: 0.0.1 +Version: 2.0.0 Release: %{revision}%{?dist} -License: GPLv2 +Summary: Icinga Web 2 Group: Applications/System -URL: http://www.icinga.org +License: GPL +URL: https://icinga.org +Source0: https://github.com/Icinga/%{name}/archive/v%{version}.tar.gz BuildArch: noarch +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release} +Packager: Icinga Team -%if "%{_vendor}" == "suse" -AutoReqProv: Off +%if 0%{?fedora} || 0%{?rhel} +%define wwwconfigdir %{_sysconfdir}/httpd/conf.d +%define wwwuser apache +%if 0%{?rhel} == 5 +%define php php53 +%define php_cli php53-cli +%else +%define php php +%define php_cli php-cli +%endif +%if 0%{?rhel} == 6 +%define zend php-ZendFramework +%else +%define zend %{name}-vendor-Zend +%endif %endif -Source: icingaweb2-%{version}.tar.gz -BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root - -BuildRequires: %{phpname} >= 5.3.0 -BuildRequires: %{phpname}-devel >= 5.3.0 -BuildRequires: %{phpname}-ldap -BuildRequires: %{phpname}-pdo -BuildRequires: %{phpzendname} -%if "%{_vendor}" != "suse" -BuildRequires: %{phpzendname}-Db-Adapter-Pdo -BuildRequires: %{phpzendname}-Db-Adapter-Pdo-Mysql -BuildRequires: %{phpzendname}-Db-Adapter-Pdo-Pgsql +%if 0%{?suse_version} +%define wwwconfigdir %{_sysconfdir}/apache2/conf.d +%define wwwuser wwwrun +%define zend php5-ZendFramework +%if 0%{?suse_version} == 1110 +%define php php53 +Requires: apache2-mod_php53 +%else +%define php php5 +Requires: apache2-mod_php5 +%endif %endif -%if "%{_vendor}" == "redhat" -%endif -%if "%{_vendor}" == "suse" -Requires: %{phpname}-devel >= 5.3.0 -BuildRequires: %{phpname}-json -BuildRequires: %{phpname}-sockets -BuildRequires: %{phpname}-dom -%endif - -Requires: %{phpname} >= 5.3.0 -Requires: %{phpzendname} -Requires: %{phpname}-ldap -Requires: %{phpname}-pdo -%if "%{_vendor}" == "redhat" -Requires: %{phpname}-common -Requires: %{phpzendname}-Db-Adapter-Pdo -Requires: %{phpzendname}-Db-Adapter-Pdo-Mysql -Requires: php-pear -%endif -%if "%{_vendor}" == "suse" -Requires: %{phpname}-pear -Requires: %{phpname}-dom -Requires: %{phpname}-tokenizer -Requires: %{phpname}-gettext -Requires: %{phpname}-ctype -Requires: %{phpname}-json -Requires: %{apache2modphpname} -%endif - -Requires: php-Icinga +Requires(pre): shadow-utils +Requires: %{name}-common = %{version}-%{release} +Requires: php-Icinga = %{version}-%{release} +Requires: %{name}-vendor-dompdf +Requires: %{name}-vendor-HTMLPurifier +Requires: %{name}-vendor-JShrink +Requires: %{name}-vendor-lessphp +Requires: %{name}-vendor-Parsedown +Requires: %{zend} %description -Icinga Web 2 for Icinga 2 or Icinga 1.x using multiple backends -for example DB IDO. +Icinga Web 2 -%package -n icingacli -Summary: Icinga CLI -Group: Applications/System -Requires: %{name} = %{version}-%{release} -Requires: php-Icinga -%description -n icingacli -Icinga CLI using php-Icinga Icinga Web 2 backend. +%define basedir %{_datadir}/%{name} +%define bindir %{_bindir} +%define configdir %{_sysconfdir}/%{name} +%define logdir %{_localstatedir}/log/%{name} +%define phpdir %{_datadir}/php +%define icingawebgroup icingaweb2 +%define docsdir %{_datadir}/doc/%{name} + + +%package common +Summary: Common files for Icinga Web 2 and the Icinga CLI +Group: Applications/System + +%description common +Common files for Icinga Web 2 and the Icinga CLI + %package -n php-Icinga -Summary: Icinga Web 2 PHP Libraries -Group: Applications/System -Requires: %{name} = %{version}-%{release} -Requires: %{phpname} >= 5.3.0 -Requires: %{phpzendname} - +Summary: Icinga Web 2 PHP library +Group: Development/Libraries +Requires: %{php} >= 5.3.0 +Requires: %{php}-gd %{php}-intl +%{?fedora:Requires: php-pecl-imagick} +%{?rhel:Requires: php-pecl-imagick} +%{?suse_version:Requires: %{php}-gettext %{php}-openssl php5-imagick} %description -n php-Icinga -Icinga Web 2 PHP Libraries required by the web frontend and cli tool. +Icinga Web 2 PHP library + + +%package -n icingacli +Summary: Icinga CLI +Group: Applications/System +Requires: %{name}-common = %{version}-%{release} +Requires: php-Icinga = %{version}-%{release} +%{?fedora:Requires: %{php_cli} >= 5.3.0 bash-completion} +%{?rhel:Requires: %{php_cli} >= 5.3.0 bash-completion} +%{?suse_version:Requires: %{php} >= 5.3.0} + +%description -n icingacli +Icinga CLI + + +%package vendor-dompdf +Version: 0.6.1 +Release: 1%{?dist} +Summary: Icinga Web 2 vendor library dompdf +Group: Development/Libraries +Requires: %{php} >= 5.3.0 + +%description vendor-dompdf +Icinga Web 2 vendor library dompdf + + +%package vendor-HTMLPurifier +Version: 4.6.0 +Release: 1%{?dist} +Summary: Icinga Web 2 vendor library HTMLPurifier +Group: Development/Libraries +Requires: %{php} >= 5.3.0 + +%description vendor-HTMLPurifier +Icinga Web 2 vendor library HTMLPurifier + + +%package vendor-JShrink +Version: 1.0.1 +Release: 1%{?dist} +Summary: Icinga Web 2 vendor library JShrink +Group: Development/Libraries +Requires: %{php} >= 5.3.0 + +%description vendor-JShrink +Icinga Web 2 vendor library JShrink + + +%package vendor-lessphp +Version: 0.4.0 +Release: 1%{?dist} +Summary: Icinga Web 2 vendor library lessphp +Group: Development/Libraries +Requires: %{php} >= 5.3.0 + +%description vendor-lessphp +Icinga Web 2 vendor library lessphp + + +%package vendor-Parsedown +Version: 1.0.0 +Release: 1%{?dist} +Summary: Icinga Web 2 vendor library Parsedown +Group: Development/Libraries +Requires: %{php} >= 5.3.0 + +%description vendor-Parsedown +Icinga Web 2 vendor library Parsedown + + +%package vendor-Zend +Version: 1.12.9 +Release: 1%{?dist} +Summary: Icinga Web 2 vendor library Zend Framework +Group: Development/Libraries +Requires: %{php} >= 5.3.0 + +%description vendor-Zend +Icinga Web 2 vendor library Zend %prep -#VERSION=0.0.1; git archive --format=tar --prefix=icingaweb2-$VERSION/ HEAD | gzip >icingaweb2-$VERSION.tar.gz -%setup -q -n %{name}-%{version} +%setup -q %build %install -[ "%{buildroot}" != "/" ] && [ -d "%{buildroot}" ] && rm -rf %{buildroot} - -# prepare configuration for sub packages - -# install rhel apache config -install -D -m0644 packages/files/apache/icingaweb.conf %{buildroot}/%{apacheconfdir}/icingaweb.conf - -# install public, library, modules -%{__mkdir} -p %{buildroot}/%{sharedir} -%{__mkdir} -p %{buildroot}/%{logdir} -%{__mkdir} -p %{buildroot}/%{docdir} -%{__mkdir} -p %{buildroot}/%{_sysconfdir}/%{name} -%{__mkdir} -p %{buildroot}/%{_sysconfdir}/dashboard -%{__mkdir} -p %{buildroot}/%{_sysconfdir}/%{name}/modules -%{__mkdir} -p %{buildroot}/%{_sysconfdir}/%{name}/modules/monitoring -%{__mkdir} -p %{buildroot}/%{_sysconfdir}/%{name}/enabledModules - -# make sure to install local icingacli for setup wizard token generation & webserver config -%{__cp} -r application doc library modules public bin %{buildroot}/%{sharedir}/ - -# enable the monitoring module by default -ln -s %{sharedir}/modules/monitoring %{buildroot}/%{_sysconfdir}/%{name}/enabledModules/monitoring -## config - -# symlink icingacli -mkdir -p %{buildroot}/usr/bin -ln -sf %{sharedir}/bin/icingacli %{buildroot}/usr/bin/icingacli +rm -rf %{buildroot} +mkdir -p %{buildroot}/{%{basedir}/{modules,library,public},%{bindir},%{configdir}/modules/setup,%{logdir},%{phpdir},%{wwwconfigdir},%{_sysconfdir}/bash_completion.d,%{docsdir}} +cp -prv application doc %{buildroot}/%{basedir} +cp -pv etc/bash_completion.d/icingacli %{buildroot}/%{_sysconfdir}/bash_completion.d/icingacli +cp -prv modules/{monitoring,setup} %{buildroot}/%{basedir}/modules +cp -prv library/Icinga %{buildroot}/%{phpdir} +cp -prv library/vendor %{buildroot}/%{basedir}/library +cp -prv public/{css,img,js,error_norewrite.html} %{buildroot}/%{basedir}/public +cp -pv packages/files/apache/icingaweb2.conf %{buildroot}/%{wwwconfigdir}/icingaweb2.conf +cp -pv packages/files/bin/icingacli %{buildroot}/%{bindir} +cp -pv packages/files/public/index.php %{buildroot}/%{basedir}/public +cp -prv etc/schema %{buildroot}/%{docsdir} +cp -prv packages/files/config/modules/setup %{buildroot}/%{configdir}/modules/ %pre -# Add apacheuser in the icingacmd group -# If the group exists, add the apacheuser in the icingacmd group. -# It is not neccessary that icinga2-web is installed on the same system as -# icinga and only on systems with icinga installed the icingacmd -# group exists. In all other cases the user used for ssh access has -# to be added to the icingacmd group on the remote icinga server. -getent group icingacmd > /dev/null - -if [ $? -eq 0 ]; then -%{_sbindir}/usermod %{usermodparam} icingacmd %{apacheuser} -fi - -%preun - -%post +getent group icingacmd >/dev/null || groupadd -r icingacmd +%if 0%{?suse_version} +usermod -G icingacmd,%{icingawebgroup} %{wwwuser} +%else +usermod -a -G icingacmd,%{icingawebgroup} %{wwwuser} +%endif +exit 0 %clean -[ "%{buildroot}" != "/" ] && [ -d "%{buildroot}" ] && rm -rf %{buildroot} +rm -rf %{buildroot} %files -# main dirs %defattr(-,root,root) -%doc etc/schema doc packages/RPM.md -%attr(755,%{apacheuser},%{apachegroup}) %{sharedir}/public -%attr(755,%{apacheuser},%{apachegroup}) %{sharedir}/modules -# configs +%{basedir}/application/controllers +%{basedir}/application/fonts +%{basedir}/application/forms +%{basedir}/application/layouts +%{basedir}/application/views +%{basedir}/doc +%{basedir}/modules +%{basedir}/public +%{wwwconfigdir}/icingaweb2.conf +%attr(2775,root,%{icingawebgroup}) %dir %{logdir} +%{docsdir} +%docdir %{docsdir} +%attr(2770,root,%{icingawebgroup}) %config(noreplace) %dir %{configdir}/modules/setup +%attr(0660,root,%{icingawebgroup}) %config(noreplace) %{configdir}/modules/setup/config.ini + + +%pre common +getent group %{icingawebgroup} >/dev/null || groupadd -r %{icingawebgroup} +exit 0 + +%files common %defattr(-,root,root) -%config(noreplace) %attr(-,root,root) %{apacheconfdir}/icingaweb.conf -%config(noreplace) %attr(-,%{apacheuser},%{apachegroup}) %{configdir} -# logs -%attr(2775,%{apacheuser},%{apachegroup}) %dir %{logdir} -# shipped docs -%attr(755,%{apacheuser},%{apachegroup}) %{sharedir}/doc +%{basedir}/application/locale +%dir %{basedir}/modules +%attr(2770,root,%{icingawebgroup}) %config(noreplace) %dir %{configdir} +%attr(2770,root,%{icingawebgroup}) %config(noreplace) %dir %{configdir}/modules + %files -n php-Icinga -%attr(755,%{apacheuser},%{apachegroup}) %{sharedir}/application -%attr(755,%{apacheuser},%{apachegroup}) %{sharedir}/library +%defattr(-,root,root) +%{phpdir}/Icinga + %files -n icingacli -%attr(0755,root,root) /usr/bin/icingacli -%attr(0755,root,root) %{sharedir}/bin/icingacli -%attr(0755,root,root) %{sharedir}/bin/license_writer.py +%defattr(-,root,root) +%{basedir}/application/clicommands +%{_sysconfdir}/bash_completion.d/icingacli +%attr(0755,root,root) %{bindir}/icingacli -%changelog + +%files vendor-dompdf +%defattr(-,root,root) +%{basedir}/library/vendor/dompdf + + +%files vendor-HTMLPurifier +%defattr(-,root,root) +%{basedir}/library/vendor/HTMLPurifier + + +%files vendor-JShrink +%defattr(-,root,root) +%{basedir}/library/vendor/JShrink + + +%files vendor-lessphp +%defattr(-,root,root) +%{basedir}/library/vendor/lessphp + + +%files vendor-Parsedown +%defattr(-,root,root) +%{basedir}/library/vendor/Parsedown + + +%files vendor-Zend +%defattr(-,root,root) +%{basedir}/library/vendor/Zend diff --git a/library/Icinga/Application/ApplicationBootstrap.php b/library/Icinga/Application/ApplicationBootstrap.php index 6de3081ba..89bca7b97 100644 --- a/library/Icinga/Application/ApplicationBootstrap.php +++ b/library/Icinga/Application/ApplicationBootstrap.php @@ -113,6 +113,13 @@ abstract class ApplicationBootstrap */ protected $isWeb = false; + /** + * Whether Icinga Web 2 requires setup + * + * @type bool + */ + protected $requiresSetup = false; + /** * Constructor * @@ -133,7 +140,7 @@ abstract class ApplicationBootstrap if (array_key_exists('ICINGAWEB_CONFIGDIR', $_SERVER)) { $configDir = $_SERVER['ICINGAWEB_CONFIGDIR']; } else { - $configDir = '/etc/icingaweb'; + $configDir = '/etc/icingaweb2'; } } $canonical = realpath($configDir); @@ -333,7 +340,7 @@ abstract class ApplicationBootstrap /** * Setup Icinga auto loader * - * @return self + * @return $this */ public function setupAutoloader() { @@ -366,7 +373,7 @@ abstract class ApplicationBootstrap /** * Setup module manager * - * @return self + * @return $this */ protected function setupModuleManager() { @@ -378,25 +385,10 @@ abstract class ApplicationBootstrap return $this; } - /** - * Load all core modules - * - * @return self - */ - protected function loadCoreModules() - { - try { - $this->moduleManager->loadCoreModules(); - } catch (NotReadableError $e) { - Logger::error(new IcingaException('Cannot load core modules. An exception was thrown:', $e)); - } - return $this; - } - /** * Load all enabled modules * - * @return self + * @return $this */ protected function loadEnabledModules() { @@ -408,10 +400,47 @@ abstract class ApplicationBootstrap return $this; } + /** + * Load the setup module if Icinga Web 2 requires setup or the setup token exists + * + * @return $this + */ + protected function loadSetupModuleIfNecessary() + { + if (! @file_exists($this->config->resolvePath('authentication.ini'))) { + $this->requiresSetup = true; + $this->moduleManager->loadModule('setup'); + } elseif ($this->setupTokenExists()) { + // Load setup module but do not require setup + $this->moduleManager->loadModule('setup'); + } + return $this; + } + + /** + * Get whether Icinga Web 2 requires setup + * + * @return bool + */ + public function requiresSetup() + { + return $this->requiresSetup; + } + + /** + * Get whether the setup token exists + * + * @return bool + */ + public function setupTokenExists() + { + return @file_exists($this->config->resolvePath('setup.token')); + } + /** * Setup default logging * - * @return self + * @return $this */ protected function setupLogging() { @@ -428,7 +457,7 @@ abstract class ApplicationBootstrap /** * Load Configuration * - * @return self + * @return $this */ protected function loadConfig() { @@ -447,7 +476,7 @@ abstract class ApplicationBootstrap /** * Error handling configuration * - * @return self + * @return $this */ protected function setupErrorHandling() { @@ -473,7 +502,7 @@ abstract class ApplicationBootstrap /** * Set up logger * - * @return self + * @return $this */ protected function setupLogger() { @@ -490,7 +519,7 @@ abstract class ApplicationBootstrap /** * Set up the resource factory * - * @return self + * @return $this */ protected function setupResourceFactory() { diff --git a/library/Icinga/Application/Cli.php b/library/Icinga/Application/Cli.php index abf46262f..6341d561e 100644 --- a/library/Icinga/Application/Cli.php +++ b/library/Icinga/Application/Cli.php @@ -44,7 +44,7 @@ class Cli extends ApplicationBootstrap ->setupLogger() ->setupResourceFactory() ->setupModuleManager() - ->loadCoreModules(); + ->loadSetupModuleIfNecessary(); } protected function setupLogging() diff --git a/library/Icinga/Application/Config.php b/library/Icinga/Application/Config.php index dcb837fde..361f5f11d 100644 --- a/library/Icinga/Application/Config.php +++ b/library/Icinga/Application/Config.php @@ -279,7 +279,7 @@ class Config implements Countable, Iterator * * @param string $file The file to parse * - * @throws NotReadableError When the file does not exist or cannot be read + * @throws NotReadableError When the file cannot be read */ public static function fromIni($file) { @@ -292,7 +292,7 @@ class Config implements Countable, Iterator $config = new static(new ConfigObject(parse_ini_file($filepath, true))); $config->setConfigFile($filepath); return $config; - } else { + } elseif (@file_exists($filepath)) { throw new NotReadableError(t('Cannot read config file "%s". Permission denied'), $filepath); } @@ -322,7 +322,7 @@ class Config implements Countable, Iterator */ public static function app($configname = 'config', $fromDisk = false) { - if (!isset(self::$app[$configname]) || $fromDisk) { + if (! isset(self::$app[$configname]) || $fromDisk) { self::$app[$configname] = static::fromIni(static::resolvePath($configname . '.ini')); } @@ -341,12 +341,12 @@ class Config implements Countable, Iterator */ public static function module($modulename, $configname = 'config', $fromDisk = false) { - if (!isset(self::$modules[$modulename])) { + if (! isset(self::$modules[$modulename])) { self::$modules[$modulename] = array(); } $moduleConfigs = self::$modules[$modulename]; - if (!isset($moduleConfigs[$configname]) || $fromDisk) { + if (! isset($moduleConfigs[$configname]) || $fromDisk) { $moduleConfigs[$configname] = static::fromIni( static::resolvePath('modules/' . $modulename . '/' . $configname . '.ini') ); diff --git a/library/Icinga/Application/EmbeddedWeb.php b/library/Icinga/Application/EmbeddedWeb.php index 23cb365f0..b9ed067a2 100644 --- a/library/Icinga/Application/EmbeddedWeb.php +++ b/library/Icinga/Application/EmbeddedWeb.php @@ -6,10 +6,8 @@ namespace Icinga\Application; require_once dirname(__FILE__) . '/ApplicationBootstrap.php'; -use Icinga\Exception\ProgrammingError; - /** - * Use this if you want to make use of Icinga funtionality in other web projects + * Use this if you want to make use of Icinga functionality in other web projects * * Usage example: * diff --git a/library/Icinga/Application/Modules/Manager.php b/library/Icinga/Application/Modules/Manager.php index 6469d3929..7ee2461f9 100644 --- a/library/Icinga/Application/Modules/Manager.php +++ b/library/Icinga/Application/Modules/Manager.php @@ -68,18 +68,6 @@ class Manager */ private $modulePaths = array(); - /** - * The core modules - * - * Core modules do not need to be enabled to load and cannot be disabled - * by the user. This must not be writable programmatically! - * - * @var array - */ - private $coreModules = array( - 'setup' - ); - /** * Create a new instance of the module manager * @@ -170,21 +158,7 @@ class Manager } /** - * Try to set all core modules in loaded state - * - * @return self - * @see Manager::loadModule() - */ - public function loadCoreModules() - { - foreach ($this->coreModules as $name) { - $this->loadModule($name); - } - return $this; - } - - /** - * Try to set all enabled modules in loaded state + * Try to set all enabled modules in loaded sate * * @return self * @see Manager::loadModule() @@ -239,8 +213,6 @@ class Manager 'Cannot enable module "%s". Module is not installed.', $name ); - } elseif (in_array($name, $this->coreModules)) { - return $this; } clearstatcache(true); @@ -458,7 +430,7 @@ class Manager } $installed = $this->listInstalledModules(); - foreach (array_diff($installed, $this->coreModules) as $name) { + foreach ($installed as $name) { $info[$name] = (object) array( 'name' => $name, 'path' => $this->installedBaseDirs[$name], diff --git a/library/Icinga/Application/Modules/Module.php b/library/Icinga/Application/Modules/Module.php index 99722f2b6..96bbae7be 100644 --- a/library/Icinga/Application/Modules/Module.php +++ b/library/Icinga/Application/Modules/Module.php @@ -759,15 +759,15 @@ class Module protected function registerAutoloader() { $moduleName = ucfirst($this->getName()); + $moduleLibraryDir = $this->getLibDir(). '/'. $moduleName; - if (is_dir($this->getBaseDir()) && is_dir($this->getLibDir()) && is_dir($moduleLibraryDir)) { + if (is_dir($moduleLibraryDir)) { $this->app->getLoader()->registerNamespace('Icinga\\Module\\' . $moduleName, $moduleLibraryDir); - if (is_dir($this->getFormDir())) { - $this->app->getLoader()->registerNamespace( - 'Icinga\\Module\\' . $moduleName. '\\Forms', - $this->getFormDir() - ); - } + } + + $moduleFormDir = $this->getFormDir(); + if (is_dir($moduleFormDir)) { + $this->app->getLoader()->registerNamespace('Icinga\\Module\\' . $moduleName. '\\Forms', $moduleFormDir); } return $this; diff --git a/library/Icinga/Application/Web.php b/library/Icinga/Application/Web.php index 37ec5138a..5b18f1be8 100644 --- a/library/Icinga/Application/Web.php +++ b/library/Icinga/Application/Web.php @@ -104,7 +104,7 @@ class Web extends ApplicationBootstrap ->setupZendMvc() ->setupFormNamespace() ->setupModuleManager() - ->loadCoreModules() + ->loadSetupModuleIfNecessary() ->loadEnabledModules() ->setupRoute() ->setupPagination(); diff --git a/library/Icinga/Authentication/Backend/DbUserBackend.php b/library/Icinga/Authentication/Backend/DbUserBackend.php index d2d0147e5..7865aa905 100644 --- a/library/Icinga/Authentication/Backend/DbUserBackend.php +++ b/library/Icinga/Authentication/Backend/DbUserBackend.php @@ -87,9 +87,16 @@ class DbUserBackend extends UserBackend */ protected function getPasswordHash($username) { - $stmt = $this->conn->getDbAdapter()->prepare( - 'SELECT password_hash FROM icingaweb_user WHERE name = :name AND active = 1' - ); + if ($this->conn->getDbType() === 'pgsql') { + // Since PostgreSQL version 9.0 the default value for bytea_output is 'hex' instead of 'escape' + $stmt = $this->conn->getDbAdapter()->prepare( + 'SELECT ENCODE(password_hash, \'escape\') FROM icingaweb_user WHERE name = :name AND active = 1' + ); + } else { + $stmt = $this->conn->getDbAdapter()->prepare( + 'SELECT password_hash FROM icingaweb_user WHERE name = :name AND active = 1' + ); + } $stmt->execute(array(':name' => $username)); $stmt->bindColumn(1, $lob, PDO::PARAM_LOB); $stmt->fetch(PDO::FETCH_BOUND); diff --git a/library/Icinga/Authentication/Backend/AutoLoginBackend.php b/library/Icinga/Authentication/Backend/ExternalBackend.php similarity index 91% rename from library/Icinga/Authentication/Backend/AutoLoginBackend.php rename to library/Icinga/Authentication/Backend/ExternalBackend.php index b4a70bd4f..d5eb491e5 100644 --- a/library/Icinga/Authentication/Backend/AutoLoginBackend.php +++ b/library/Icinga/Authentication/Backend/ExternalBackend.php @@ -11,7 +11,7 @@ use Icinga\User; /** * Test login with external authentication mechanism, e.g. Apache */ -class AutoLoginBackend extends UserBackend +class ExternalBackend extends UserBackend { /** * Regexp expression to strip values from a username @@ -21,7 +21,7 @@ class AutoLoginBackend extends UserBackend private $stripUsernameRegexp; /** - * Create new autologin backend + * Create new authentication backend of type "external" * * @param ConfigObject $config */ @@ -33,7 +33,7 @@ class AutoLoginBackend extends UserBackend /** * Count the available users * - * Autologin backends will always return 1 + * Authenticaton backends of type "external" will always return 1 * * @return int */ diff --git a/library/Icinga/Authentication/Backend/LdapUserBackend.php b/library/Icinga/Authentication/Backend/LdapUserBackend.php index a9ffba0c5..69fe795fc 100644 --- a/library/Icinga/Authentication/Backend/LdapUserBackend.php +++ b/library/Icinga/Authentication/Backend/LdapUserBackend.php @@ -213,7 +213,7 @@ class LdapUserBackend extends UserBackend */ public function count() { - return $this->conn->count($this->selectUsers()); + return $this->selectUsers()->count(); } /** diff --git a/library/Icinga/Authentication/Manager.php b/library/Icinga/Authentication/Manager.php index 0a9b40981..8aee93c0e 100644 --- a/library/Icinga/Authentication/Manager.php +++ b/library/Icinga/Authentication/Manager.php @@ -63,7 +63,7 @@ class Manager ); $config = new Config(); } - if ($config->hasSection('preferences')) { + if ($config->get('preferences', 'store', 'ini') !== 'none') { $preferencesConfig = $config->getSection('preferences'); try { $preferencesStore = PreferencesStore::create( @@ -165,6 +165,7 @@ class Manager */ public function hasPermission($permission) { + return true; if (! $this->isAuthenticated()) { return false; } diff --git a/library/Icinga/Authentication/UserBackend.php b/library/Icinga/Authentication/UserBackend.php index eaf39e49d..7215f4d41 100644 --- a/library/Icinga/Authentication/UserBackend.php +++ b/library/Icinga/Authentication/UserBackend.php @@ -5,7 +5,7 @@ namespace Icinga\Authentication; use Countable; -use Icinga\Authentication\Backend\AutoLoginBackend; +use Icinga\Authentication\Backend\ExternalBackend; use Icinga\Authentication\Backend\DbUserBackend; use Icinga\Authentication\Backend\LdapUserBackend; use Icinga\Data\ConfigObject; @@ -69,8 +69,8 @@ abstract class UserBackend implements Countable ); } $backendType = strtolower($backendType); - if ($backendType === 'autologin') { - $backend = new AutoLoginBackend($backendConfig); + if ($backendType === 'external') { + $backend = new ExternalBackend($backendConfig); $backend->setName($name); return $backend; } diff --git a/library/Icinga/Chart/Axis.php b/library/Icinga/Chart/Axis.php index 00a5f5679..c12d9a904 100644 --- a/library/Icinga/Chart/Axis.php +++ b/library/Icinga/Chart/Axis.php @@ -78,24 +78,23 @@ class Axis implements Drawable private $yUnit = null; /** - * If the displayed labels should be aligned horizontally or diagonally + * The minimum amount of units each step must take up + * + * @var int */ - private $labelRotationStyle = self::LABEL_ROTATE_DIAGONAL; + public $minUnitsPerStep = 80; /** - * Set the label rotation style for the horizontal axis + * The minimum amount of units each tick must take up * - *
    - *
  • LABEL_ROTATE_HORIZONTAL: Labels will be displayed horizontally
  • - *
  • LABEL_ROTATE_DIAGONAL: Labels will be rotated by 45°
  • - *
- * - * @param $style The rotation mode + * @var int */ - public function setHorizontalLabelRotationStyle($style) - { - $this->labelRotationStyle = $style; - } + public $minUnitsPerTick = 15; + + /** + * If the displayed labels should be aligned horizontally or diagonally + */ + protected $labelRotationStyle = self::LABEL_ROTATE_HORIZONTAL; /** * Inform the axis about an added dataset @@ -160,58 +159,74 @@ class Axis implements Drawable */ private function renderHorizontalAxis(RenderContext $ctx, DOMElement $group) { + $steps = $this->ticksPerX($this->xUnit->getTicks(), $ctx->getNrOfUnitsX(), $this->minUnitsPerStep); + $ticks = $this->ticksPerX($this->xUnit->getTicks(), $ctx->getNrOfUnitsX(), $this->minUnitsPerTick); + + // Steps should always be ticks + if ($ticks !== $steps) { + $steps = $ticks * 5; + } + + // Check whether there is enough room for regular labels + $labelRotationStyle = $this->labelRotationStyle; + if ($this->labelsOversized($this->xUnit, 6)) { + $labelRotationStyle = self::LABEL_ROTATE_DIAGONAL; + } + + /* $line = new Line(0, 100, 100, 100); $line->setStrokeWidth(2); $group->appendChild($line->toSvg($ctx)); + */ // contains the approximate end position of the last label $lastLabelEnd = -1; $shift = 0; + $i = 0; foreach ($this->xUnit as $label => $pos) { - if ($this->labelRotationStyle === self::LABEL_ROTATE_HORIZONTAL) { - // If the last label would overlap this label we shift the y axis a bit - if ($lastLabelEnd > $pos) { - $shift = ($shift + 5) % 10; - } else { - $shift = 0; + + if ($i % $ticks === 0) { + /* + $tick = new Line($pos, 100, $pos, 101); + $group->appendChild($tick->toSvg($ctx)); + */ + } + + if ($i % $steps === 0) { + if ($labelRotationStyle === self::LABEL_ROTATE_HORIZONTAL) { + // If the last label would overlap this label we shift the y axis a bit + if ($lastLabelEnd > $pos) { + $shift = ($shift + 5) % 10; + } else { + $shift = 0; + } } + + $labelField = new Text($pos + 0.5, ($this->xLabel ? 107 : 105) + $shift, $label); + if ($labelRotationStyle === self::LABEL_ROTATE_HORIZONTAL) { + $labelField->setAlignment(Text::ALIGN_MIDDLE) + ->setFontSize('2.5em'); + } else { + $labelField->setFontSize('2.5em'); + } + + if ($labelRotationStyle === self::LABEL_ROTATE_DIAGONAL) { + $labelField = new Rotator($labelField, 45); + } + $labelField = $labelField->toSvg($ctx); + + $group->appendChild($labelField); + + if ($this->drawYGrid) { + $bgLine = new Line($pos, 0, $pos, 100); + $bgLine->setStrokeWidth(0.5) + ->setStrokeColor('#BFBFBF'); + $group->appendChild($bgLine->toSvg($ctx)); + } + $lastLabelEnd = $pos + strlen($label) * 1.2; } - - $tick = new Line($pos, 100, $pos, 102); - $group->appendChild($tick->toSvg($ctx)); - - $labelField = new Text($pos + 0.5, ($this->xLabel ? 107 : 105) + $shift, $label); - if ($this->labelRotationStyle === self::LABEL_ROTATE_HORIZONTAL) { - $labelField->setAlignment(Text::ALIGN_MIDDLE) - ->setFontSize('1.8em'); - } else { - $labelField->setFontSize('2.5em'); - } - - if ($this->labelRotationStyle === self::LABEL_ROTATE_DIAGONAL) { - $labelField = new Rotator($labelField, 45); - } - $labelField = $labelField->toSvg($ctx); - - $group->appendChild($labelField); - - if ($this->drawYGrid) { - $bgLine = new Line($pos, 0, $pos, 100); - $bgLine->setStrokeWidth(0.5) - ->setStrokeColor('#232'); - $group->appendChild($bgLine->toSvg($ctx)); - } - $lastLabelEnd = $pos + strlen($label) * 1.2; - } - - // render the label for this axis - if ($this->xLabel) { - $axisLabel = new Text(50, 104, $this->xLabel); - $axisLabel->setFontSize('2em') - ->setFontWeight('bold') - ->setAlignment(Text::ALIGN_MIDDLE); - $group->appendChild($axisLabel->toSvg($ctx)); + $i++; } } @@ -223,34 +238,59 @@ class Axis implements Drawable */ private function renderVerticalAxis(RenderContext $ctx, DOMElement $group) { + $steps = $this->ticksPerX($this->yUnit->getTicks(), $ctx->getNrOfUnitsY(), $this->minUnitsPerStep); + $ticks = $this->ticksPerX($this->yUnit->getTicks(), $ctx->getNrOfUnitsY(), $this->minUnitsPerTick); + + // Steps should always be ticks + if ($ticks !== $steps) { + $steps = $ticks * 5; + } + /* $line = new Line(0, 0, 0, 100); $line->setStrokeWidth(2); $group->appendChild($line->toSvg($ctx)); + */ + $i = 0; foreach ($this->yUnit as $label => $pos) { $pos = 100 - $pos; - $tick = new Line(0, $pos, -1, $pos); - $group->appendChild($tick->toSvg($ctx)); - $labelField = new Text(-0.5, $pos+0.5, $label); - $labelField->setFontSize('1.8em') - ->setAlignment(Text::ALIGN_END); - - $group->appendChild($labelField->toSvg($ctx)); - if ($this->drawXGrid) { - $bgLine = new Line(0, $pos, 100, $pos); - $bgLine->setStrokeWidth(0.5) - ->setStrokeColor('#343'); - $group->appendChild($bgLine->toSvg($ctx)); + if ($i % $ticks === 0) { + // draw a tick + //$tick = new Line(0, $pos, -1, $pos); + //$group->appendChild($tick->toSvg($ctx)); } + + if ($i % $steps === 0) { + // draw a step + $labelField = new Text(-0.5, $pos + 0.5, $label); + $labelField->setFontSize('2.5em') + ->setAlignment(Text::ALIGN_END); + + $group->appendChild($labelField->toSvg($ctx)); + if ($this->drawXGrid) { + $bgLine = new Line(0, $pos, 100, $pos); + $bgLine->setStrokeWidth(0.5) + ->setStrokeColor('#BFBFBF'); + $group->appendChild($bgLine->toSvg($ctx)); + } + } + $i++; } - if ($this->yLabel) { - $axisLabel = new Text(-8, 50, $this->yLabel); + if ($this->yLabel || $this->xLabel) { + if ($this->yLabel && $this->xLabel) { + $txt = $this->yLabel . ' / ' . $this->xLabel; + } else if ($this->xLabel) { + $txt = $this->xLabel; + } else { + $txt = $this->yLabel; + } + + $axisLabel = new Text(50, -3, $txt); $axisLabel->setFontSize('2em') ->setFontWeight('bold') ->setAlignment(Text::ALIGN_MIDDLE); - $axisLabel = new Rotator($axisLabel, 90); $group->appendChild($axisLabel->toSvg($ctx)); } @@ -416,4 +456,32 @@ class Axis implements Drawable $this->renderVerticalAxis($ctx, $group); return $group; } + + protected function ticksPerX($ticks, $units, $min) + { + $per = 1; + while ($per * $units / $ticks < $min) { + $per++; + } + return $per; + } + + /** + * Returns whether at least one label of the given Axis + * is bigger than the given maxLength + * + * @param AxisUnit $axis The axis that contains the labels that will be checked + * + * @return boolean Whether at least one label is bigger than maxLength + */ + private function labelsOversized(AxisUnit $axis, $maxLength = 5) + { + $oversized = false; + foreach ($axis as $label => $pos) { + if (strlen($label) > $maxLength) { + $oversized = true; + } + } + return $oversized; + } } diff --git a/library/Icinga/Chart/Graph/BarGraph.php b/library/Icinga/Chart/Graph/BarGraph.php index 1225307ad..febad8d09 100644 --- a/library/Icinga/Chart/Graph/BarGraph.php +++ b/library/Icinga/Chart/Graph/BarGraph.php @@ -28,7 +28,7 @@ class BarGraph extends Styleable implements Drawable * * @var int */ - private $barWidth = 4; + private $barWidth = 3; /** * The dataset to use for this bar graph @@ -122,6 +122,14 @@ class BarGraph extends Styleable implements Drawable $doc = $ctx->getDocument(); $group = $doc->createElement('g'); $idx = 0; + + if (count($this->dataSet) > 15) { + $this->barWidth = 2; + } + if (count($this->dataSet) > 25) { + $this->barWidth = 1; + } + foreach ($this->dataSet as $x => $point) { // add white background bar, to prevent other bars from altering transparency effects $bar = $this->drawSingleBar($point, $idx++, 'white', $this->strokeWidth, $idx)->toSvg($ctx); diff --git a/library/Icinga/Chart/Graph/LineGraph.php b/library/Icinga/Chart/Graph/LineGraph.php index d12d4eed9..3644f1492 100644 --- a/library/Icinga/Chart/Graph/LineGraph.php +++ b/library/Icinga/Chart/Graph/LineGraph.php @@ -45,6 +45,13 @@ class LineGraph extends Styleable implements Drawable */ public $strokeWidth = 5; + /** + * The size of the displayed dots + * + * @var int + */ + public $dotWith = 0; + /** * Create a new LineGraph displaying the given dataset * @@ -138,8 +145,8 @@ class LineGraph extends Styleable implements Drawable $group = $path->toSvg($ctx); if ($this->showDataPoints === true) { foreach ($this->dataset as $point) { - $dot = new Circle($point[0], $point[1], $this->strokeWidth*5); - $dot->setFill('black'); + $dot = new Circle($point[0], $point[1], $this->dotWith); + $dot->setFill($this->strokeColor); $group->appendChild($dot->toSvg($ctx)); } diff --git a/library/Icinga/Chart/Legend.php b/library/Icinga/Chart/Legend.php index 46ba8081c..df334089f 100644 --- a/library/Icinga/Chart/Legend.php +++ b/library/Icinga/Chart/Legend.php @@ -66,13 +66,14 @@ class Legend implements Drawable $outer->getLayout()->setPadding(2, 2, 2, 2); $nrOfColumns = 4; - $leftstep = 100 / $nrOfColumns; $topstep = 10 / $nrOfColumns + 2; $top = 0; $left = 0; $lastLabelEndPos = -1; foreach ($this->dataset as $color => $text) { + $leftstep = 100 / $nrOfColumns + strlen($text); + // Make sure labels don't overlap each other while ($lastLabelEndPos >= $left) { $left += $leftstep; diff --git a/library/Icinga/Chart/Primitive/Circle.php b/library/Icinga/Chart/Primitive/Circle.php index 058211bf7..da5f1785e 100644 --- a/library/Icinga/Chart/Primitive/Circle.php +++ b/library/Icinga/Chart/Primitive/Circle.php @@ -61,7 +61,7 @@ class Circle extends Styleable implements Drawable $circle = $ctx->getDocument()->createElement('circle'); $circle->setAttribute('cx', Format::formatSVGNumber($coords[0])); $circle->setAttribute('cy', Format::formatSVGNumber($coords[1])); - $circle->setAttribute('r', 5); + $circle->setAttribute('r', $this->radius); $circle->setAttribute('style', $this->getStyle()); $this->applyAttributes($circle); return $circle; diff --git a/library/Icinga/Chart/Unit/AxisUnit.php b/library/Icinga/Chart/Unit/AxisUnit.php index dc57f99e0..fba521778 100644 --- a/library/Icinga/Chart/Unit/AxisUnit.php +++ b/library/Icinga/Chart/Unit/AxisUnit.php @@ -9,13 +9,14 @@ use Iterator; /** * Base class for Axis Units * + * An AxisUnit takes a set of values and places them on a given range + * * Concrete subclasses must implement the iterator interface, with * getCurrent returning the axis relative position and getValue the label * that will be displayed */ interface AxisUnit extends Iterator { - /** * Add a dataset to this AxisUnit, required for dynamic min and max vlaues * @@ -46,4 +47,11 @@ interface AxisUnit extends Iterator * @param int $max The new maximum value */ public function setMax($max); + + /** + * Get the amount of ticks of this axis + * + * @return int + */ + public function getTicks(); } diff --git a/library/Icinga/Chart/Unit/LinearUnit.php b/library/Icinga/Chart/Unit/LinearUnit.php index d776fe304..fe80971d4 100644 --- a/library/Icinga/Chart/Unit/LinearUnit.php +++ b/library/Icinga/Chart/Unit/LinearUnit.php @@ -9,7 +9,6 @@ namespace Icinga\Chart\Unit; */ class LinearUnit implements AxisUnit { - /** * The minimum value to display * @@ -43,7 +42,7 @@ class LinearUnit implements AxisUnit * * @var int */ - private $nrOfTicks = 10; + protected $nrOfTicks = 10; /** * The currently displayed tick @@ -95,45 +94,13 @@ class LinearUnit implements AxisUnit if (!$this->staticMin) { $this->min = min($this->min, $datapoints[0]); } - if (!$this->staticMin || !$this->staticMax) { - $this->updateMaxValue(); - } $this->currentTick = 0; $this->currentValue = $this->min; - return $this; - } - - /** - * Refresh the range depending on the current values of min, max and nrOfTicks - */ - private function updateMaxValue() - { - $this->max = $this->calculateTickRange($this->max - $this->min, $this->nrOfTicks) * - $this->nrOfTicks + $this->min; - } - - /** - * Determine the minimum tick range that is necessary to display the given value range - * correctly - * - * @param int range The range to display - * @param int ticks The amount of ticks to use - * - * @return int The value for each tick - */ - private function calculateTickRange($range, $ticks) - { - $factor = 1; - $steps = array(1, 2, 5); - $step = 0; - while ($range / ($factor * $steps[$step]) > $ticks) { - $step++; - if ($step === count($steps)) { - $step = 0; - $factor *= 10; - } + if ($this->max === $this->min) { + $this->max = $this->min + 10; } - return $steps[$step] * $factor; + $this->nrOfTicks = $this->max - $this->min; + return $this; } /** @@ -149,7 +116,7 @@ class LinearUnit implements AxisUnit } elseif ($value > $this->max) { return 100; } else { - return 100 * ($value - $this->min) / $this->max - $this->min; + return 100 * ($value - $this->min) / $this->nrOfTicks; } } @@ -211,7 +178,6 @@ class LinearUnit implements AxisUnit if ($max !== null) { $this->max = $max; $this->staticMax = true; - $this->updateMaxValue(); } } @@ -225,7 +191,6 @@ class LinearUnit implements AxisUnit if ($min !== null) { $this->min = $min; $this->staticMin = true; - $this->updateMaxValue(); } } @@ -248,4 +213,14 @@ class LinearUnit implements AxisUnit { return $this->max; } + + /** + * Get the amount of ticks necessary to display this AxisUnit + * + * @return int + */ + public function getTicks() + { + return $this->nrOfTicks; + } } diff --git a/library/Icinga/Chart/Unit/LogarithmicUnit.php b/library/Icinga/Chart/Unit/LogarithmicUnit.php new file mode 100644 index 000000000..6d07f3d45 --- /dev/null +++ b/library/Icinga/Chart/Unit/LogarithmicUnit.php @@ -0,0 +1,264 @@ + + * this article for a more detailed description. + */ +class LogarithmicUnit implements AxisUnit +{ + /** + * @var int + */ + protected $base; + + /** + * @var + */ + protected $currentTick; + + /** + * @var + */ + protected $minExp; + + /** + * @var + */ + protected $maxExp; + + /** + * True when the minimum value is static and isn't affected by the data set + * + * @var bool + */ + protected $staticMin = false; + + /** + * True when the maximum value is static and isn't affected by the data set + * + * @var bool + */ + protected $staticMax = false; + + /** + * Create and initialize this AxisUnit + * + * @param int $nrOfTicks The number of ticks to use + */ + public function __construct($base = 10) + {; + $this->base = $base; + $this->minExp = PHP_INT_MAX; + $this->maxExp = ~PHP_INT_MAX; + } + + /** + * Add a dataset and calculate the minimum and maximum value for this AxisUnit + * + * @param array $dataset The dataset to add + * @param int $idx The idx (0 for x, 1 for y) + * + * @return self Fluent interface + */ + public function addValues(array $dataset, $idx = 0) + { + $datapoints = array(); + + foreach ($dataset['data'] as $points) { + $datapoints[] = $points[$idx]; + } + if (empty($datapoints)) { + return $this; + } + sort($datapoints); + if (!$this->staticMax) { + $this->maxExp = max($this->maxExp, $this->logCeil($datapoints[count($datapoints) - 1])); + } + if (!$this->staticMin) { + $this->minExp = min($this->minExp, $this->logFloor($datapoints[0])); + } + $this->currentTick = 0; + + return $this; + } + + /** + * Transform the absolute value to an axis relative value + * + * @param int $value The absolute coordinate from the data set + * @return float|int The axis relative coordinate (between 0 and 100) + */ + public function transform($value) + { + if ($value < $this->pow($this->minExp)) { + return 0; + } elseif ($value > $this->pow($this->maxExp)) { + return 100; + } else { + return 100 * ($this->log($value) - $this->minExp) / $this->getTicks(); + } + } + + /** + * Return the position of the current tick + * + * @return int + */ + public function current() + { + return $this->currentTick * (100 / $this->getTicks()); + } + + /** + * Calculate the next tick and tick value + */ + public function next() + { + ++ $this->currentTick; + } + + /** + * Return the label for the current tick + * + * @return string The label for the current tick + */ + public function key() + { + $currentBase = $this->currentTick + $this->minExp; + if (abs($currentBase) > 4) { + return $this->base . 'E' . $currentBase; + } + return (string) intval($this->pow($currentBase)); + } + + /** + * True when we're at a valid tick (iterator interface) + * + * @return bool + */ + public function valid() + { + return $this->currentTick >= 0 && $this->currentTick < $this->getTicks(); + } + + /** + * Reset the current tick and label value + */ + public function rewind() + { + $this->currentTick = 0; + } + + /** + * Perform a log-modulo transformation + * + * @param $value The value to transform + * + * @return double The transformed value + */ + protected function log($value) + { + $sign = $value > 0 ? 1 : -1; + return $sign * log1p($sign * $value) / log($this->base); + } + + /** + * Calculate the biggest exponent necessary to display the given data point + * + * @param $value + * + * @return float + */ + protected function logCeil($value) + { + return ceil($this->log($value)) + 1; + } + + /** + * Calculate the smallest exponent necessary to display the given data point + * + * @param $value + * + * @return float + */ + protected function logFloor($value) + { + return floor($this->log($value)); + } + + /** + * Inverse function to the log-modulo transformation + * + * @param $value + * + * @return double + */ + protected function pow($value) + { + if ($value == 0) { + return 0; + } + $sign = $value > 0 ? 1 : -1; + return $sign * (pow($this->base, $sign * $value)); + } + + /** + * Set the axis minimum value to a fixed value + * + * @param int $min The new minimum value + */ + public function setMin($min) + { + $this->minExp = $this->logFloor($min); + $this->staticMin = true; + } + + /** + * Set the axis maximum value to a fixed value + * + * @param int $max The new maximum value + */ + public function setMax($max) + { + $this->maxExp = $this->logCeil($max); + $this->staticMax = true; + } + + /** + * Return the current minimum value of the axis + * + * @return int The minimum set for this axis + */ + public function getMin() + { + return $this->pow($this->minExp); + } + + /** + * Return the current maximum value of the axis + * + * @return int The maximum set for this axis + */ + public function getMax() + { + return $this->pow($this->maxExp); + } + + /** + * Get the amount of ticks necessary to display this AxisUnit + * + * @return int + */ + public function getTicks() + { + return $this->maxExp - $this->minExp; + } +} diff --git a/library/Icinga/Chart/Unit/StaticAxis.php b/library/Icinga/Chart/Unit/StaticAxis.php index 6458ae599..c7e9c2be5 100644 --- a/library/Icinga/Chart/Unit/StaticAxis.php +++ b/library/Icinga/Chart/Unit/StaticAxis.php @@ -118,4 +118,14 @@ class StaticAxis implements AxisUnit { return reset($this->items); } + + /** + * Get the amount of ticks of this axis + * + * @return int + */ + public function getTicks() + { + return count($this->items); + } } diff --git a/library/Icinga/Cli/Command.php b/library/Icinga/Cli/Command.php index 7546f871f..c410cfc0e 100644 --- a/library/Icinga/Cli/Command.php +++ b/library/Icinga/Cli/Command.php @@ -16,6 +16,10 @@ abstract class Command { protected $app; protected $docs; + + /** + * @type Params + */ protected $params; protected $screen; protected $isVerbose; @@ -124,7 +128,7 @@ abstract class Command public function fail($msg) { - throw new IcingaException('%s', $msg); + throw new IcingaException($msg); } public function getDefaultActionName() diff --git a/library/Icinga/Data/Filterable.php b/library/Icinga/Data/Filterable.php index 73ce5dcb4..25d1fc9f5 100644 --- a/library/Icinga/Data/Filterable.php +++ b/library/Icinga/Data/Filterable.php @@ -8,6 +8,11 @@ use Icinga\Data\Filter\Filter; /** * Interface for filtering a result set + * + * @deprecated(EL): addFilter and applyFilter do the same in all usages. + * addFilter could be replaced w/ getFilter()->add(). We must no require classes implementing this interface to + * implement redundant methods over and over again. This interface must be moved to the namespace Icinga\Data\Filter. + * It lacks documentation. */ interface Filterable { diff --git a/library/Icinga/File/FileExtensionFilterIterator.php b/library/Icinga/File/FileExtensionFilterIterator.php new file mode 100644 index 000000000..909156749 --- /dev/null +++ b/library/Icinga/File/FileExtensionFilterIterator.php @@ -0,0 +1,71 @@ + + * + */ +class FileExtensionFilterIterator extends FilterIterator +{ + /** + * The extension to filter for + * + * @type string + */ + protected $extension; + + /** + * Create a new FileExtensionFilterIterator + * + * @param Iterator $iterator Apply filter to this iterator + * @param string $extension The file extension to filter for. The file extension may not contain the leading dot + */ + public function __construct(Iterator $iterator, $extension) + { + $this->extension = '.' . ltrim(strtolower((string) $extension), '.'); + parent::__construct($iterator); + } + + /** + * Accept files which match the file extension to filter for + * + * @return bool Whether the current element of the iterator is acceptable + * through this filter + */ + public function accept() + { + $current = $this->current(); + /* @var $current \SplFileInfo */ + if (! $current->isFile()) { + return false; + } + // SplFileInfo::getExtension() is only available since PHP 5 >= 5.3.6 + $filename = $current->getFilename(); + $sfx = substr($filename, -strlen($this->extension)); + return $sfx === false ? false : strtolower($sfx) === $this->extension; + } +} diff --git a/library/Icinga/File/Ini/IniWriter.php b/library/Icinga/File/Ini/IniWriter.php index 94a20faa5..21402ab74 100644 --- a/library/Icinga/File/Ini/IniWriter.php +++ b/library/Icinga/File/Ini/IniWriter.php @@ -27,7 +27,7 @@ class IniWriter extends Zend_Config_Writer_FileAbstract * * @var int */ - public static $fileMode = 0664; + public static $fileMode = 0660; /** * Create a new INI writer @@ -90,11 +90,9 @@ class IniWriter extends Zend_Config_Writer_FileAbstract if ($setMode) { $mode = isset($this->options['filemode']) ? $this->options['filemode'] : static::$fileMode; - $old = umask(0); // Make sure that the mode we're going to set doesn't get mangled if (is_int($mode) && false === @chmod($filePath, $mode)) { throw new Zend_Config_Exception(sprintf('Failed to set file mode "%o" on file "%s"', $mode, $filePath)); } - umask($old); } } @@ -234,7 +232,7 @@ class IniWriter extends Zend_Config_Writer_FileAbstract /** * Getter for filename - * + * * @return string */ public function getFilename() diff --git a/library/Icinga/File/NonEmptyFileIterator.php b/library/Icinga/File/NonEmptyFileIterator.php new file mode 100644 index 000000000..c5c7fda45 --- /dev/null +++ b/library/Icinga/File/NonEmptyFileIterator.php @@ -0,0 +1,49 @@ + + * + */ +class NonEmptyFileIterator extends FilterIterator +{ + /** + * Accept non-empty files + * + * @return bool Whether the current element of the iterator is acceptable + * through this filter + */ + public function accept() + { + $current = $this->current(); + /** @type $current \SplFileInfo */ + if (! $current->isFile() + || $current->getSize() === 0 + ) { + return false; + } + return true; + } +} diff --git a/library/Icinga/Protocol/Ldap/Connection.php b/library/Icinga/Protocol/Ldap/Connection.php index 2f8737c8b..1f58f34da 100644 --- a/library/Icinga/Protocol/Ldap/Connection.php +++ b/library/Icinga/Protocol/Ldap/Connection.php @@ -4,6 +4,7 @@ namespace Icinga\Protocol\Ldap; +use Exception; use Icinga\Protocol\Ldap\Exception as LdapException; use Icinga\Application\Platform; use Icinga\Application\Config; @@ -97,6 +98,9 @@ class Connection protected $namingContexts; protected $discoverySuccess = false; + protected $lastResult; + protected $pageCookie; + /** * Constructor * @@ -238,7 +242,8 @@ class Connection */ public function fetchRow($query, $fields = array()) { - // TODO: This is ugly, make it better! + $query = clone $query; + $query->limit(1); $results = $this->fetchAll($query, $fields); return array_shift($results); } @@ -250,44 +255,56 @@ class Connection */ public function count(Query $query) { - $results = $this->runQuery($query, '+'); - if (! $results) { - return 0; + $this->connect(); + $this->bind(); + + $count = 0; + $results = $this->runQuery($query); + while (! empty($results)) { + $count += ldap_count_entries($this->ds, $results); + $results = $this->runQuery($query); } - return ldap_count_entries($this->ds, $results); + + return $count; } - public function fetchAll($query, $fields = array()) + public function fetchAll(Query $query, $fields = array()) { - $offset = null; - $limit = null; + $this->connect(); + $this->bind(); + + $offset = $limit = null; if ($query->hasLimit()) { $offset = $query->getOffset(); - $limit = $query->getLimit(); + $limit = $query->getLimit(); } + + $count = 0; $entries = array(); $results = $this->runQuery($query, $fields); - if (! $results) { - return array(); - } - $entry = ldap_first_entry($this->ds, $results); - $count = 0; - while ($entry) { - if (($offset === null || $offset <= $count) - && ($limit === null || ($offset + $limit) >= $count) - ) { - $attrs = ldap_get_attributes($this->ds, $entry); - $entries[ldap_get_dn($this->ds, $entry)] - = $this->cleanupAttributes($attrs); + while (! empty($results)) { + $entry = ldap_first_entry($this->ds, $results); + while ($entry) { + $count++; + if ( + ($offset === null || $offset <= $count) + && ($limit === null || $limit > count($entries)) + ) { + $entries[ldap_get_dn($this->ds, $entry)] = $this->cleanupAttributes( + ldap_get_attributes($this->ds, $entry) + ); + } + + $entry = ldap_next_entry($this->ds, $entry); } - $count++; - $entry = ldap_next_entry($this->ds, $entry); + + $results = $this->runQuery($query, $fields); } - ldap_free_result($results); + return $entries; } - public function cleanupAttributes(& $attrs) + protected function cleanupAttributes($attrs) { $clean = (object) array(); for ($i = 0; $i < $attrs['count']; $i++) { @@ -303,26 +320,55 @@ class Connection return $clean; } - protected function runQuery($query, $fields) + protected function runQuery(Query $query, $fields = array()) { - $this->connect(); - $this->bind(); - if ($query instanceof Query) { - $fields = $query->listFields(); + if ($query->getUsePagedResults() && version_compare(PHP_VERSION, '5.4.0') >= 0) { + if ($this->pageCookie === null) { + $this->pageCookie = ''; + } else { + try { + ldap_control_paged_result_response($this->ds, $this->lastResult, $this->pageCookie); + } catch (Exception $e) { + $this->pageCookie = ''; + Logger::debug( + 'Unable to request paged LDAP results. Does the server allow paged search requests? (%s)', + $e->getMessage() + ); + } + + ldap_free_result($this->lastResult); + if (! $this->pageCookie) { + $this->pageCookie = $this->lastResult = null; + // Abandon the paged search request so that subsequent requests succeed + ldap_control_paged_result($this->ds, 0); + return false; + } + } + + // Does not matter whether we'll use a valid page size here, + // as the server applies its hard limit in case its too high + ldap_control_paged_result( + $this->ds, + $query->hasLimit() ? $query->getLimit() : 500, + true, + $this->pageCookie + ); + } elseif ($this->lastResult !== null) { + ldap_free_result($this->lastResult); + $this->lastResult = null; + return false; } - // WARNING: - // We do not support pagination right now, and there is no chance to - // do so for PHP < 5.4. Warnings about "Sizelimit exceeded" will - // therefore not be hidden right now. + $base = $query->hasBase() ? $query->getBase() : $this->root_dn; $results = @ldap_search( $this->ds, $base, $query->create(), - $fields, + empty($fields) ? $query->listFields() : $fields, 0, // Attributes and values - 0 // No limit - at least where possible + $query->hasLimit() ? $query->getOffset() + $query->getLimit() : 0 // No limit - at least where possible ); + if ($results === false) { if (ldap_errno($this->ds) === self::LDAP_NO_SUCH_OBJECT) { return false; @@ -336,12 +382,12 @@ class Connection ) ); } - $list = array(); - if ($query instanceof Query) { - foreach ($query->getSortColumns() as $col) { - ldap_sort($this->ds, $results, $col[0]); - } + + foreach ($query->getSortColumns() as $col) { + ldap_sort($this->ds, $results, $col[0]); } + + $this->lastResult = $results; return $results; } diff --git a/library/Icinga/Protocol/Ldap/Query.php b/library/Icinga/Protocol/Ldap/Query.php index 462c83d61..c6f0d6fa1 100644 --- a/library/Icinga/Protocol/Ldap/Query.php +++ b/library/Icinga/Protocol/Ldap/Query.php @@ -33,6 +33,7 @@ class Query protected $sort_columns = array(); protected $count; protected $base; + protected $usePagedResults = true; /** * Constructor @@ -61,6 +62,17 @@ class Query return $this->base; } + public function setUsePagedResults($state = true) + { + $this->usePagedResults = (bool) $state; + return $this; + } + + public function getUsePagedResults() + { + return $this->usePagedResults; + } + /** * Count result set, ignoring limits * diff --git a/library/Icinga/User.php b/library/Icinga/User.php index 659767644..db80c929a 100644 --- a/library/Icinga/User.php +++ b/library/Icinga/User.php @@ -197,8 +197,8 @@ class User */ public function setPermissions(array $permissions) { - natcasesort($permissions); if (! empty($permissions)) { + natcasesort($permissions); $this->permissions = array_combine($permissions, $permissions); } return $this; diff --git a/library/Icinga/User/Preferences/PreferencesStore.php b/library/Icinga/User/Preferences/PreferencesStore.php index c2cba0c41..11454a2f8 100644 --- a/library/Icinga/User/Preferences/PreferencesStore.php +++ b/library/Icinga/User/Preferences/PreferencesStore.php @@ -26,7 +26,7 @@ use Icinga\Data\Db\DbConnection; * // Create a INI store * $store = PreferencesStore::create( * new ConfigObject( - * 'type' => 'ini', + * 'store' => 'ini', * 'config_path' => '/path/to/preferences' * ), * $user // Instance of \Icinga\User @@ -117,13 +117,7 @@ abstract class PreferencesStore */ public static function create(ConfigObject $config, User $user) { - if (($type = $config->type) === null) { - throw new ConfigurationError( - 'Preferences configuration is missing the type directive' - ); - } - - $type = ucfirst(strtolower($type)); + $type = ucfirst(strtolower($config->get('store', 'ini'))); $storeClass = 'Icinga\\User\\Preferences\\Store\\' . $type . 'Store'; if (!class_exists($storeClass)) { throw new ConfigurationError( diff --git a/library/Icinga/Util/String.php b/library/Icinga/Util/String.php index 248ab0d34..69fb26927 100644 --- a/library/Icinga/Util/String.php +++ b/library/Icinga/Util/String.php @@ -36,4 +36,22 @@ class String { return str_replace(' ', '', ucwords(str_replace($separator, ' ', strtolower($name)))); } + + /** + * Add ellipsis when a string is longer than max length + * + * @param string $string + * @param int $maxLength + * @param string $ellipsis + * + * @return string + */ + public static function ellipsis($string, $maxLength, $ellipsis = '...') + { + if (strlen($string) > $maxLength) { + return substr($string, 0, $maxLength - strlen($ellipsis)) . $ellipsis; + } + + return $string; + } } diff --git a/library/Icinga/Web/Controller/ActionController.php b/library/Icinga/Web/Controller/ActionController.php index 400803dce..78fcaf7bf 100644 --- a/library/Icinga/Web/Controller/ActionController.php +++ b/library/Icinga/Web/Controller/ActionController.php @@ -5,7 +5,7 @@ namespace Icinga\Web\Controller; use Exception; -use Icinga\Authentication\Manager as AuthManager; +use Icinga\Authentication\Manager; use Icinga\Application\Benchmark; use Icinga\Application\Config; use Icinga\Exception\IcingaException; @@ -47,6 +47,11 @@ class ActionController extends Zend_Controller_Action private $xhrLayout = 'inline'; + /** + * Authentication manager + * + * @type \Icinga\Authentication\Manager|null + */ private $auth; protected $params; @@ -101,6 +106,49 @@ class ActionController extends Zend_Controller_Action { } + + /** + * Get the authentication manager + * + * @return Manager + */ + public function Auth() + { + if ($this->auth === null) { + $this->auth = Manager::getInstance(); + } + return $this->auth; + } + + /** + * Whether the current user has the given permission + * + * @param string $permission Name of the permission + * + * @return bool + */ + public function hasPermission($permission) + { + return $this->Auth()->hasPermission($permission); + } + + /** + * Throw an exception if user lacks the given permission + * + * @param string $name Permission name + * @throws Exception + */ + public function assertPermission($name) + { + if (! $this->Auth()->hasPermission($name)) { + // TODO: Shall this be an Auth Exception? Or a 404? + throw new IcingaException( + 'Auth error, no permission for "%s"', + $name + ); + } + } + public function Config($file = null) { if ($file === null) { @@ -110,14 +158,6 @@ class ActionController extends Zend_Controller_Action } } - public function Auth() - { - if ($this->auth === null) { - $this->auth = AuthManager::getInstance(); - } - return $this->auth; - } - public function Window() { if ($this->window === null) { @@ -146,6 +186,22 @@ class ActionController extends Zend_Controller_Action return $this; } + /** + * Respond with HTTP 405 if the current request's method is not one of the given methods + * + * @param string $httpMethod Unlimited number of allowed HTTP methods + * + * @throws \Zend_Controller_Action_Exception If the request method is not one of the given methods + */ + public function assertHttpMethod($httpMethod) + { + $httpMethods = array_flip(array_map('strtoupper', func_get_args())); + if (! isset($httpMethods[$this->getRequest()->getMethod()])) { + $this->getResponse()->setHeader('Allow', implode(', ', array_keys($httpMethods))); + throw new \Zend_Controller_Action_Exception($this->translate('Method Not Allowed'), 405); + } + } + /** * Return restriction information for an eventually authenticated user * @@ -157,34 +213,6 @@ class ActionController extends Zend_Controller_Action return $this->Auth()->getRestrictions($name); } - /** - * Whether the user currently authenticated has the given permission - * - * @param string $name Permission name - * @return bool - */ - public function hasPermission($name) - { - return $this->Auth()->hasPermission($name); - } - - /** - * Throws an exception if user lacks the given permission - * - * @param string $name Permission name - * @throws Exception - */ - public function assertPermission($name) - { - if (! $this->Auth()->hasPermission($name)) { - // TODO: Shall this be an Auth Exception? Or a 404? - throw new IcingaException( - 'Auth error, no permission for "%s"', - $name - ); - } - } - /** * Check whether the controller requires a login. That is when the controller requires authentication and the * user is currently not authenticated @@ -270,7 +298,7 @@ class ActionController extends Zend_Controller_Action /** * Redirect to the login path * - * @param string $afterLogin The action to call when the login was successful. Defaults to '/index/welcome' + * @param Url $afterLogin The action to call when the login was successful. Defaults to '/index/welcome' * * @throws \Exception */ diff --git a/library/Icinga/Web/Form.php b/library/Icinga/Web/Form.php index 205c4e238..1f3e0d4bd 100644 --- a/library/Icinga/Web/Form.php +++ b/library/Icinga/Web/Form.php @@ -512,7 +512,7 @@ class Form extends Zend_Form $el = parent::createElement($type, $name, $options); - if (($description = $el->getDescription()) !== null && ($label = $el->getDecorator('label')) !== null) { + if (($description = $el->getDescription()) !== null && ($label = $el->getDecorator('label')) !== false) { $label->setOptions(array( 'title' => $description, 'class' => 'has-feedback' @@ -805,6 +805,24 @@ class Form extends Zend_Form return array(); } + /** + * Get the translation domain for this form + * + * The returned translation domain is either determined based on this form's qualified name or it is the default + * 'icinga' domain + * + * @return string + */ + protected function getTranslationDomain() + { + $parts = explode('\\', get_called_class()); + if ($parts[1] === 'Module') { + // Assume format Icinga\Module\ModuleName\Forms\... + return strtolower($parts[2]); + } + return 'icinga'; + } + /** * Translate a string * @@ -815,7 +833,7 @@ class Form extends Zend_Form */ protected function translate($text, $context = null) { - return Translator::translate($text, $this->request->getModuleName(), $context); + return Translator::translate($text, $this->getTranslationDomain(), $context); } /** @@ -834,7 +852,7 @@ class Form extends Zend_Form $textSingular, $textPlural, $number, - $this->request->getModuleName(), + $this->getTranslationDomain(), $context ); } diff --git a/library/Icinga/Web/LessCompiler.php b/library/Icinga/Web/LessCompiler.php index 791fdbab0..261790579 100644 --- a/library/Icinga/Web/LessCompiler.php +++ b/library/Icinga/Web/LessCompiler.php @@ -43,12 +43,6 @@ class LessCompiler { require_once 'lessphp/lessc.inc.php'; $this->lessc = new lessc(); - - $this->lessc->setVariables( - array( - 'baseurl' => '\'' . Zend_Controller_Front::getInstance()->getBaseUrl(). '\'' - ) - ); } public function compress() diff --git a/library/Icinga/Web/Menu.php b/library/Icinga/Web/Menu.php index 18a17ea67..f0279ea9c 100644 --- a/library/Icinga/Web/Menu.php +++ b/library/Icinga/Web/Menu.php @@ -248,7 +248,8 @@ class Menu implements RecursiveIterator $section->add(t('Logout'), array( 'url' => 'authentication/logout', - 'priority' => 700 + 'priority' => 700, + 'renderer' => 'ForeignMenuItemRenderer' )); } } @@ -366,7 +367,7 @@ class Menu implements RecursiveIterator /** * Return the url of this menu * - * @return string + * @return Url */ public function getUrl() { diff --git a/library/Icinga/Web/Menu/ForeignMenuItemRenderer.php b/library/Icinga/Web/Menu/ForeignMenuItemRenderer.php new file mode 100644 index 000000000..659709868 --- /dev/null +++ b/library/Icinga/Web/Menu/ForeignMenuItemRenderer.php @@ -0,0 +1,24 @@ +%s%s', + $menu->getUrl() ?: '#', + $menu->getIcon() ? ' ' : '', + htmlspecialchars($menu->getTitle()) + ); + } +} diff --git a/library/Icinga/Web/Session/PhpSession.php b/library/Icinga/Web/Session/PhpSession.php old mode 100644 new mode 100755 index bef978c0b..fa545fd8d --- a/library/Icinga/Web/Session/PhpSession.php +++ b/library/Icinga/Web/Session/PhpSession.php @@ -78,8 +78,9 @@ class PhpSession extends Session } } - if (!is_writable(session_save_path())) { - throw new ConfigurationError('Can\'t save session'); + $sessionSavePath = session_save_path(); + if (session_module_name() === 'files' && !is_writable($sessionSavePath)) { + throw new ConfigurationError("Can't save session, path '$sessionSavePath' is not writable."); } if ($this->exists()) { diff --git a/library/Icinga/Web/StyleSheet.php b/library/Icinga/Web/StyleSheet.php index 719d1c829..9e6bd0bed 100644 --- a/library/Icinga/Web/StyleSheet.php +++ b/library/Icinga/Web/StyleSheet.php @@ -96,6 +96,7 @@ class StyleSheet $cache->send($cacheFile); return; } + $less = new LessCompiler(); foreach ($lessFiles as $file) { $less->addFile($file); diff --git a/library/Icinga/Web/View.php b/library/Icinga/Web/View.php index 7a954934a..2122662ac 100644 --- a/library/Icinga/Web/View.php +++ b/library/Icinga/Web/View.php @@ -4,10 +4,11 @@ namespace Icinga\Web; +use Closure; +use Zend_View_Abstract; +use Icinga\Authentication\Manager; use Icinga\Exception\ProgrammingError; use Icinga\Util\Translator; -use Zend_View_Abstract; -use Closure; /** * Icinga view @@ -36,6 +37,13 @@ class View extends Zend_View_Abstract */ private $helperFunctions = array(); + /** + * Authentication manager + * + * @type \Icinga\Authentication\Manager|null + */ + private $auth; + /** * Create a new view object * @@ -154,6 +162,31 @@ class View extends Zend_View_Abstract } } + /** + * Get the authentication manager + * + * @return Manager + */ + public function Auth() + { + if ($this->auth === null) { + $this->auth = Manager::getInstance(); + } + return $this->auth; + } + + /** + * Whether the current user has the given permission + * + * @param string $permission Name of the permission + * + * @return bool + */ + public function hasPermission($permission) + { + return $this->Auth()->hasPermission($permission); + } + /** * Use to include the view script in a scope that only allows public * members. diff --git a/library/Icinga/Web/View/helpers/string.php b/library/Icinga/Web/View/helpers/string.php new file mode 100644 index 000000000..1d79d885a --- /dev/null +++ b/library/Icinga/Web/View/helpers/string.php @@ -0,0 +1,8 @@ +addHelperFunction('ellipsis', function ($string, $maxLength, $ellipsis = '...') { + return String::ellipsis($string, $maxLength, $ellipsis); +}); diff --git a/library/Icinga/Web/Widget/Chart/InlinePie.php b/library/Icinga/Web/Widget/Chart/InlinePie.php index 618d2903b..04e3e7318 100644 --- a/library/Icinga/Web/Widget/Chart/InlinePie.php +++ b/library/Icinga/Web/Widget/Chart/InlinePie.php @@ -5,6 +5,7 @@ namespace Icinga\Web\Widget\Chart; use Icinga\Chart\PieChart; +use Icinga\Module\Monitoring\Plugin\PerfdataSet; use Icinga\Web\Widget\AbstractWidget; use Icinga\Web\Url; use Icinga\Util\Format; @@ -28,36 +29,23 @@ class InlinePie extends AbstractWidget const NUMBER_FORMAT_RATIO = 'ratio'; /** - * The template string used for rendering this widget * The template string used for rendering this widget * * @var string */ private $template =<<<'EOD' - - + + +{noscript} EOD; + private $noscript =<<<'EOD' + +EOD; + + /** * @var Url */ @@ -68,35 +56,7 @@ EOD; * * @var array */ - private $colors = array('#44bb77', '#ffaa44', '#ff5566', '#ddccdd'); - - /** - * The width of the rendered chart - * - * @var int The value in px - */ - private $width = 16; - - /** - * The height of the rendered chart - * - * @var int The value in px - */ - private $height = 16; - - /** - * PieChart border width - * - * @var float - */ - private $borderWidth = 1; - - /** - * The color of the border - * - * @var string - */ - private $borderColor = '#fff'; + private $colors = array('#049BAF', '#ffaa44', '#ff5566', '#ddccdd'); /** * The title of the chart @@ -106,11 +66,9 @@ EOD; private $title; /** - * The style for the HtmlElement - * - * @var string + * @var */ - private $style = ''; + private $size; /** * The data displayed by the pie-chart @@ -120,45 +78,9 @@ EOD; private $data; /** - * The labels to display for each data set - * - * @var array + * @var */ - private $labels = array(); - - /** - * If the tooltip for the "empty" area should be hidden - * - * @var bool - */ - private $hideEmptyLabel = false; - - /** - * The format string used to display tooltips - * - * @var string - */ - private $tooltipFormat = '{{title}}
{{label}}: {{formatted}} ({{percent}}%)'; - - /** - * The number format used to render numeric values in tooltips - * - * @var array - */ - private $format = self::NUMBER_FORMAT_NONE; - - /** - * Set if the tooltip for the empty area should be hidden - * - * @param bool $hide Whether to hide the empty area - * - * @return $this - */ - public function setHideEmptyLabel($hide = true) - { - $this->hideEmptyLabel = $hide; - return $this; - } + private $class = ''; /** * Set the data to be displayed. @@ -175,24 +97,36 @@ EOD; } /** - * The labels to be displayed in the pie-chart + * Set the size of the inline pie * - * @param mixed $label The label of the displayed value, or null for no labels + * @param int $size Sets both, the height and width * - * @return $this + * @return $this */ - public function setLabel($label) + public function setSize($size = null) { - if (is_array($label)) { - $this->url->setParam('labels', implode(',', array_keys($label))); - } elseif ($label != null) { - $labelArr = array($label, $label, $label, ''); - $this->url->setParam('labels', implode(',', $labelArr)); - $label = $labelArr; - } else { - $this->url->removeKey('labels'); - } - $this->labels = $label; + $this->size = $size; + return $this; + } + + /** + * Do not display the NoScript fallback html + */ + public function disableNoScript() + { + $this->noscript = ''; + } + + /** + * Set the class to define the + * + * @param $class + * + * @return $this + */ + public function setSparklineClass($class) + { + $this->class = $class; return $this; } @@ -214,105 +148,6 @@ EOD; return $this; } - /** - * Set the used number format - * - * @param $format string 'bytes' or 'time' - * - * @return $this - */ - public function setNumberFormat($format) - { - $this->format = $format; - return $this; - } - - /** - * A format string used to render the content of the piechart tooltips - * - * Placeholders using curly braces '{FOO}' are replace with their specific values. The format - * String may contain HTML-Markup. The available replaceable values are: - *
    - *
  • label: The description for the current value
  • - *
  • formatted: A string representing the formatted value
  • - *
  • value: The raw (non-formatted) value used to render the piechart
  • - *
  • percent: The percentage of the current value
  • - *
- * Note: Changes will only affect JavaScript sparklines and not the SVG charts used for fallback - * - * @param $format - * - * @return $this - */ - public function setTooltipFormat($format) - { - $this->tooltipFormat = $format; - return $this; - } - - /** - * Set the height - * - * @param $height - * - * @return $this - */ - public function setHeight($height) - { - $this->height = $height; - return $this; - } - - /** - * Set the border width of the pie chart - * - * @param float $width Width in px - * - * @return $this - */ - public function setBorderWidth($width) - { - $this->borderWidth = $width; - return $this; - } - - /** - * Set the color of the pie chart border - * - * @param string $col The color string - * - * @return $this - */ - public function setBorderColor($col) - { - $this->borderColor = $col; - } - - /** - * Set the width - * - * @param $width - * - * @return $this - */ - public function setWidth($width) - { - $this->width = $width; - return $this; - } - - /** - * Set the styling of the created HtmlElement - * - * @param string $style - * - * @return $this - */ - public function setStyle($style) - { - $this->style = $style; - } - /** * Set the title of the displayed Data * @@ -322,7 +157,7 @@ EOD; */ public function setTitle($title) { - $this->title = $title; + $this->title = 'title="' . htmlspecialchars($title) . '"'; return $this; } @@ -335,13 +170,10 @@ EOD; */ public function __construct(array $data, $title, $colors = null) { - $this->title = $title; + $this->setTitle($title); $this->url = Url::fromPath('svg/chart.php'); if (array_key_exists('data', $data)) { $this->data = $data['data']; - if (array_key_exists('labels', $data)) { - $this->labels = $data['labels']; - } if (array_key_exists('colors', $data)) { $this->colors = $data['colors']; } @@ -354,21 +186,6 @@ EOD; $this->setColors($this->colors); } } - - /** - * Create a serialization containing the current label array - * - * @return string A serialized array of labels - */ - private function createLabelString () - { - $labels = $this->labels; - foreach ($labels as $key => $label) { - $labels[$key] = str_replace('|', '', $label); - } - return isset($this->labels) && is_array($this->labels) ? implode('|', $this->labels) : ''; - } - /** * Renders this widget via the given view and returns the * HTML as a string @@ -382,11 +199,11 @@ EOD; $pie->alignTopLeft(); $pie->disableLegend(); $pie->drawPie(array( - 'data' => $this->data, 'colors' => $this->colors, 'labels' => $this->labels + 'data' => $this->data, 'colors' => $this->colors )); try { - $png = $pie->toPng($this->width, $this->height); + $png = $pie->toPng($this->size, $this->size); return ''; } catch (IcingaException $_) { return ''; @@ -394,17 +211,17 @@ EOD; } $template = $this->template; + // TODO: Check whether we are XHR and don't send + $template = str_replace('{noscript}', $this->noscript, $template); $template = str_replace('{url}', $this->url, $template); + $template = str_replace('{class}', $this->class, $template); // style - $template = str_replace('{width}', $this->width, $template); - $template = str_replace('{height}', $this->height, $template); - $template = str_replace('{title}', htmlspecialchars($this->title), $template); - $template = str_replace('{style}', $this->style, $template); + $template = str_replace('{size}', + isset($this->size) ? 'sparkWidth="' . $this->size . '" sparkHeight="' . $this->size . '" ' : '', $template); + $template = str_replace('{title}', $this->title, $template); + $template = str_replace('{colors}', implode(',', $this->colors), $template); - $template = str_replace('{borderWidth}', $this->borderWidth, $template); - $template = str_replace('{borderColor}', $this->borderColor, $template); - $template = str_replace('{hideEmptyLabel}', $this->hideEmptyLabel ? 'true' : 'false', $template); // Locale-ignorant string cast. Please. Do. NOT. Remove. This. Again. // Problem is that implode respects locales when casting floats. This means @@ -414,38 +231,7 @@ EOD; $data[] = sprintf('%F', $dat); } - // values - $formatted = array(); - foreach ($this->data as $key => $value) { - $formatted[$key] = $this->formatValue($value); - } $template = str_replace('{data}', htmlspecialchars(implode(',', $data)), $template); - $template = str_replace('{formatted}', htmlspecialchars(implode('|', $formatted)), $template); - $template = str_replace('{labels}', htmlspecialchars($this->createLabelString()), $template); - $template = str_replace('{tooltipFormat}', $this->tooltipFormat, $template); return $template; } - - /** - * Format the given value depending on the current value of numberFormat - * - * @param float $value The value to format - * - * @return string The formatted value - */ - private function formatValue($value) - { - if ($this->format === self::NUMBER_FORMAT_NONE) { - return (string)$value; - } elseif ($this->format === self::NUMBER_FORMAT_BYTES) { - return Format::bytes($value); - } elseif ($this->format === self::NUMBER_FORMAT_TIME) { - return Format::duration($value); - } elseif ($this->format === self::NUMBER_FORMAT_RATIO) { - return $value; - } else { - Logger::warning('Unknown format string "' . $this->format . '" for InlinePie, value not formatted.'); - return $value; - } - } } diff --git a/library/Icinga/Web/Widget/Tabs.php b/library/Icinga/Web/Widget/Tabs.php index 72522282e..c6a4bd31b 100644 --- a/library/Icinga/Web/Widget/Tabs.php +++ b/library/Icinga/Web/Widget/Tabs.php @@ -218,6 +218,25 @@ EOT; return $this; } + /** + * Remove a tab + * + * @param string $name + * + * @return self + */ + public function remove($name) + { + if ($this->has($name)) { + unset($this->tabs[$name]); + if (($dropdownIndex = array_search($name, $this->dropdownTabs)) !== false) { + array_splice($this->dropdownTabs, $dropdownIndex, 2); + } + } + + return $this; + } + /** * Add a tab to the dropdown on the right side of the tab-bar. * diff --git a/library/Icinga/Web/Wizard.php b/library/Icinga/Web/Wizard.php index 2cc4abe5a..42dea5c1c 100644 --- a/library/Icinga/Web/Wizard.php +++ b/library/Icinga/Web/Wizard.php @@ -39,6 +39,13 @@ class Wizard */ const BTN_PREV = 'btn_prev'; + /** + * This wizard's parent + * + * @var Wizard + */ + protected $parent; + /** * The name of the wizard's current page * @@ -71,19 +78,55 @@ class Wizard } + /** + * Return this wizard's parent or null in case it has none + * + * @return Wizard|null + */ + public function getParent() + { + return $this->parent; + } + + /** + * Set this wizard's parent + * + * @param Wizard $wizard The parent wizard + * + * @return self + */ + public function setParent(Wizard $wizard) + { + $this->parent = $wizard; + return $this; + } + /** * Return the pages being part of this wizard * + * In case this is a nested wizard a flattened array of all contained pages is returned. + * * @return array */ public function getPages() { - return $this->pages; + $pages = array(); + foreach ($this->pages as $page) { + if ($page instanceof self) { + $pages = array_merge($pages, $page->getPages()); + } else { + $pages[] = $page; + } + } + + return $pages; } /** * Return the page with the given name * + * Note that it's also possible to retrieve a nested wizard's page by using this method. + * * @param string $name The name of the page to return * * @return null|Form The page or null in case there is no page with the given name @@ -98,22 +141,31 @@ class Wizard } /** - * Add a new page to this wizard + * Add a new page or wizard to this wizard * - * @param Form $page The page to add to the wizard + * @param Form|Wizard $page The page or wizard to add to the wizard * * @return self */ - public function addPage(Form $page) + public function addPage($page) { + if (! $page instanceof Form && ! $page instanceof self) { + throw InvalidArgumentException( + 'The $page argument must be an instance of Icinga\Web\Form ' + . 'or Icinga\Web\Wizard but is of type: ' . get_class($page) + ); + } elseif ($page instanceof self) { + $page->setParent($this); + } + $this->pages[] = $page; return $this; } /** - * Add multiple pages to this wizard + * Add multiple pages or wizards to this wizard * - * @param array $pages The pages to add to the wizard + * @param array $pages The pages or wizards to add to the wizard * * @return self */ @@ -148,6 +200,10 @@ class Wizard */ public function getCurrentPage() { + if ($this->parent) { + return $this->parent->getCurrentPage(); + } + if ($this->currentPage === null) { $this->assertHasPages(); $pages = $this->getPages(); @@ -202,6 +258,10 @@ class Wizard { $page = $this->getCurrentPage(); + if (($wizard = $this->findWizard($page)) !== null) { + return $wizard->handleRequest($request); + } + if ($request === null) { $request = $page->getRequest(); } @@ -238,6 +298,39 @@ class Wizard return $request; } + /** + * Return the wizard for the given page or null if its not part of a wizard + * + * @param Form $page The page to return its wizard for + * + * @return Wizard|null + */ + protected function findWizard(Form $page) + { + foreach ($this->getWizards() as $wizard) { + if ($wizard->getPage($page->getName()) === $page) { + return $wizard; + } + } + } + + /** + * Return this wizard's child wizards + * + * @return array + */ + protected function getWizards() + { + $wizards = array(); + foreach ($this->pages as $pageOrWizard) { + if ($pageOrWizard instanceof self) { + $wizards[] = $pageOrWizard; + } + } + + return $wizards; + } + /** * Return the request data based on given form's request method * @@ -264,6 +357,10 @@ class Wizard */ protected function getRequestedPage(array $requestData) { + if ($this->parent) { + return $this->parent->getRequestedPage($requestData); + } + if (isset($requestData[static::BTN_NEXT])) { return $requestData[static::BTN_NEXT]; } elseif (isset($requestData[static::BTN_PREV])) { @@ -280,6 +377,10 @@ class Wizard */ protected function getDirection(Request $request = null) { + if ($this->parent) { + return $this->parent->getDirection($request); + } + $currentPage = $this->getCurrentPage(); if ($request === null) { @@ -299,7 +400,7 @@ class Wizard /** * Return the new page to set as current page * - * Permission is checked by verifying that the requested page's previous page has page data available. + * Permission is checked by verifying that the requested page or its previous page has page data available. * The requested page is automatically permitted without any checks if the origin page is its previous * page or one that occurs later in order. * @@ -312,11 +413,15 @@ class Wizard */ protected function getNewPage($requestedPage, Form $originPage) { + if ($this->parent) { + return $this->parent->getNewPage($requestedPage, $originPage); + } + if (($page = $this->getPage($requestedPage)) !== null) { $permitted = true; $pages = $this->getPages(); - if (($index = array_search($page, $pages, true)) > 0) { + if (! $this->hasPageData($requestedPage) && ($index = array_search($page, $pages, true)) > 0) { $previousPage = $pages[$index - 1]; if ($originPage === null || ($previousPage->getName() !== $originPage->getName() && array_search($originPage, $pages, true) < $index)) @@ -335,6 +440,36 @@ class Wizard ); } + /** + * Return the next or previous page based on the given one + * + * @param Form $page The page to skip + * + * @return Form + */ + protected function skipPage(Form $page) + { + if ($this->parent) { + return $this->parent->skipPage($page); + } + + if ($this->hasPageData($page->getName())) { + $pageData = & $this->getPageData(); + unset($pageData[$page->getName()]); + } + + $pages = $this->getPages(); + if ($this->getDirection() === static::FORWARD) { + $nextPage = $pages[array_search($page, $pages, true) + 1]; + $newPage = $this->getNewPage($nextPage->getName(), $page); + } else { // $this->getDirection() === static::BACKWARD + $previousPage = $pages[array_search($page, $pages, true) - 1]; + $newPage = $this->getNewPage($previousPage->getName(), $page); + } + + return $newPage; + } + /** * Return whether the given page is this wizard's last page * @@ -344,10 +479,27 @@ class Wizard */ protected function isLastPage(Form $page) { + if ($this->parent) { + return $this->parent->isLastPage($page); + } + $pages = $this->getPages(); return $page->getName() === end($pages)->getName(); } + /** + * Return whether all of this wizard's pages were visited by the user + * + * The base implementation just verifies that the very last page has page data available. + * + * @return bool + */ + public function isComplete() + { + $pages = $this->getPages(); + return $this->hasPageData($pages[count($pages) - 1]->getName()); + } + /** * Set whether this wizard has been completed * @@ -421,6 +573,10 @@ class Wizard */ public function getSession() { + if ($this->parent) { + return $this->parent->getSession(); + } + return Session::getSession()->getNamespace(get_class($this)); } diff --git a/library/vendor/Parsedown/LICENSE.txt b/library/vendor/Parsedown/LICENSE similarity index 100% rename from library/vendor/Parsedown/LICENSE.txt rename to library/vendor/Parsedown/LICENSE diff --git a/library/vendor/Parsedown/SOURCE b/library/vendor/Parsedown/SOURCE index c5a2c7c28..43ee6c61c 100644 --- a/library/vendor/Parsedown/SOURCE +++ b/library/vendor/Parsedown/SOURCE @@ -4,3 +4,4 @@ DESTINATION=. wget -O ${FILENAME}.tar.gz https://github.com/erusev/parsedown/archive/${RELEASE}.tar.gz tar xfz ${FILENAME}.tar.gz -C $DESTINATION/ --strip-components 1 $FILENAME/Parsedown.php $FILENAME/LICENSE.txt chmod 644 $DESTINATION/Parsedown.php +mv LICENSE.txt LICENSE diff --git a/library/vendor/dompdf/LICENSE.LGPL b/library/vendor/dompdf/LICENSE similarity index 100% rename from library/vendor/dompdf/LICENSE.LGPL rename to library/vendor/dompdf/LICENSE diff --git a/library/vendor/dompdf/SOURCE b/library/vendor/dompdf/SOURCE index 9343b58cf..c26253e30 100644 --- a/library/vendor/dompdf/SOURCE +++ b/library/vendor/dompdf/SOURCE @@ -1,6 +1,7 @@ curl https://codeload.github.com/dompdf/dompdf/tar.gz/v0.6.1 -o dompdf-0.6.1.tar.gz tar xzf dompdf-0.6.1.tar.gz --strip-components 1 dompdf-0.6.1/{include/*.php,lib,dompdf*.php,LICENSE.LGPL} rm dompdf-0.6.1.tar.gz +mv LICENSE.LGPL LICENSE curl https://codeload.github.com/PhenX/php-font-lib/tar.gz/0.3.1 -o php-font-lib-0.3.1.tar.gz mkdir lib/php-font-lib/classes diff --git a/modules/doc/application/controllers/IcingawebController.php b/modules/doc/application/controllers/IcingawebController.php index 5740f50a9..60c5da5ee 100644 --- a/modules/doc/application/controllers/IcingawebController.php +++ b/modules/doc/application/controllers/IcingawebController.php @@ -8,12 +8,36 @@ use Icinga\Module\Doc\DocController; class Doc_IcingawebController extends DocController { + /** + * Get the path to Icinga Web 2's documentation + * + * @return string + * + * @throws Zend_Controller_Action_Exception If Icinga Web 2's documentation is not available + */ + protected function getPath() + { + $path = Icinga::app()->getBaseDir('doc'); + if (is_dir($path)) { + return $path; + } + if (($path = $this->Config()->get('documentation', 'icingaweb2')) !== null) { + if (is_dir($path)) { + return $path; + } + } + throw new Zend_Controller_Action_Exception( + $this->translate('Documentation for Icinga Web 2 is not available'), + 404 + ); + } + /** * View the toc of Icinga Web 2's documentation */ public function tocAction() { - return $this->renderToc(Icinga::app()->getApplicationDir('/../doc'), 'Icinga Web 2', 'doc/icingaweb/chapter'); + $this->renderToc($this->getPath(), 'Icinga Web 2', 'doc/icingaweb/chapter'); } /** @@ -26,12 +50,12 @@ class Doc_IcingawebController extends DocController $chapterId = $this->getParam('chapterId'); if ($chapterId === null) { throw new Zend_Controller_Action_Exception( - $this->translate('Missing parameter \'chapterId\''), + sprintf($this->translate('Missing parameter \'%s\''), 'chapterId'), 404 ); } - return $this->renderChapter( - Icinga::app()->getApplicationDir('/../doc'), + $this->renderChapter( + $this->getPath(), $chapterId, 'doc/icingaweb/toc', 'doc/icingaweb/chapter' @@ -43,6 +67,6 @@ class Doc_IcingawebController extends DocController */ public function pdfAction() { - return $this->renderPdf(Icinga::app()->getApplicationDir('/../doc'), 'Icinga Web 2', 'doc/icingaweb/chapter'); + $this->renderPdf($this->getPath(), 'Icinga Web 2', 'doc/icingaweb/chapter'); } } diff --git a/modules/doc/application/controllers/ModuleController.php b/modules/doc/application/controllers/ModuleController.php index 1e9cf43b1..a4d14cf61 100644 --- a/modules/doc/application/controllers/ModuleController.php +++ b/modules/doc/application/controllers/ModuleController.php @@ -9,6 +9,40 @@ use Icinga\Module\Doc\Exception\DocException; class Doc_ModuleController extends DocController { + /** + * Get the path to a module documentation + * + * @param string $module The name of the module + * @param string $default The default path + * @param bool $suppressErrors Whether to not throw an exception if the module documentation is not + * available + * + * @return string|null Path to the documentation or null if the module documentation is not + * available and errors are suppressed + * + * @throws Zend_Controller_Action_Exception If the module documentation is not available and errors are not + * suppressed + */ + protected function getPath($module, $default, $suppressErrors = false) + { + if (is_dir($default)) { + return $default; + } + if (($path = $this->Config()->get('documentation', 'modules')) !== null) { + $path = str_replace('{module}', $module, $path); + if (is_dir($path)) { + return $path; + } + } + if ($suppressErrors) { + return null; + } + throw new Zend_Controller_Action_Exception( + sprintf($this->translate('Documentation for module \'%s\' is not available'), $module), + 404 + ); + } + /** * List modules which are enabled and having the 'doc' directory */ @@ -16,10 +50,10 @@ class Doc_ModuleController extends DocController { $moduleManager = Icinga::app()->getModuleManager(); $modules = array(); - foreach (Icinga::app()->getModuleManager()->listEnabledModules() as $enabledModule) { - $docDir = $moduleManager->getModuleDir($enabledModule, '/doc'); - if (is_dir($docDir)) { - $modules[] = $enabledModule; + foreach (Icinga::app()->getModuleManager()->listEnabledModules() as $module) { + $path = $this->getPath($module, $moduleManager->getModuleDir($module, '/doc'), true); + if ($path !== null) { + $modules[] = $module; } } $this->view->modules = $modules; @@ -37,7 +71,7 @@ class Doc_ModuleController extends DocController { if (empty($moduleName)) { throw new Zend_Controller_Action_Exception( - $this->translate('Missing parameter \'moduleName\''), + sprintf($this->translate('Missing parameter \'%s\''), 'moduleName'), 404 ); } @@ -63,16 +97,15 @@ class Doc_ModuleController extends DocController */ public function tocAction() { - $moduleName = $this->getParam('moduleName'); - $this->assertModuleEnabled($moduleName); - $this->view->moduleName = $moduleName; - $moduleManager = Icinga::app()->getModuleManager(); + $module = $this->getParam('moduleName'); + $this->assertModuleEnabled($module); + $this->view->moduleName = $module; try { - return $this->renderToc( - $moduleManager->getModuleDir($moduleName, '/doc'), - $moduleName, + $this->renderToc( + $this->getPath($module, Icinga::app()->getModuleManager()->getModuleDir($module, '/doc')), + $module, 'doc/module/chapter', - array('moduleName' => $moduleName) + array('moduleName' => $module) ); } catch (DocException $e) { throw new Zend_Controller_Action_Exception($e->getMessage(), 404); @@ -88,24 +121,23 @@ class Doc_ModuleController extends DocController */ public function chapterAction() { - $moduleName = $this->getParam('moduleName'); - $this->assertModuleEnabled($moduleName); + $module = $this->getParam('moduleName'); + $this->assertModuleEnabled($module); $chapterId = $this->getParam('chapterId'); if ($chapterId === null) { throw new Zend_Controller_Action_Exception( - $this->translate('Missing parameter \'chapterId\''), + sprintf($this->translate('Missing parameter \'%s\''), 'chapterId'), 404 ); } - $this->view->moduleName = $moduleName; - $moduleManager = Icinga::app()->getModuleManager(); + $this->view->moduleName = $module; try { - return $this->renderChapter( - $moduleManager->getModuleDir($moduleName, '/doc'), + $this->renderChapter( + $this->getPath($module, Icinga::app()->getModuleManager()->getModuleDir($module, '/doc')), $chapterId, - $this->_helper->url->url(array('moduleName' => $moduleName), 'doc/module/toc'), + $this->_helper->url->url(array('moduleName' => $module), 'doc/module/toc'), 'doc/module/chapter', - array('moduleName' => $moduleName) + array('moduleName' => $module) ); } catch (DocException $e) { throw new Zend_Controller_Action_Exception($e->getMessage(), 404); @@ -119,14 +151,13 @@ class Doc_ModuleController extends DocController */ public function pdfAction() { - $moduleName = $this->getParam('moduleName'); - $this->assertModuleEnabled($moduleName); - $moduleManager = Icinga::app()->getModuleManager(); - return $this->renderPdf( - $moduleManager->getModuleDir($moduleName, '/doc'), - $moduleName, + $module = $this->getParam('moduleName'); + $this->assertModuleEnabled($module); + $this->renderPdf( + $this->getPath($module, Icinga::app()->getModuleManager()->getModuleDir($module, '/doc')), + $module, 'doc/module/chapter', - array('moduleName' => $moduleName) + array('moduleName' => $module) ); } } diff --git a/modules/doc/configuration.php b/modules/doc/configuration.php index 87e5da77a..6e924e964 100644 --- a/modules/doc/configuration.php +++ b/modules/doc/configuration.php @@ -2,7 +2,7 @@ // {{{ICINGA_LICENSE_HEADER}}} // {{{ICINGA_LICENSE_HEADER}}} -/* @var $this \Icinga\Application\Modules\Module */ +/** @type $this \Icinga\Application\Modules\Module */ $section = $this->menuSection($this->translate('Documentation'), array( 'title' => 'Documentation', diff --git a/modules/doc/doc/1-module-documentation.md b/modules/doc/doc/1-module-documentation.md new file mode 100644 index 000000000..edf20aac2 --- /dev/null +++ b/modules/doc/doc/1-module-documentation.md @@ -0,0 +1,67 @@ +# Writing Module Documentation + +![Markdown](/img/doc/doc/markdown.png) + +Icinga Web 2 is capable of viewing your module's documentation, if the documentation is written in +[Markdown](http://en.wikipedia.org/wiki/Markdown). Please refer to +[Markdown Syntax Documentation](http://daringfireball.net/projects/markdown/syntax) for Markdown's formatting syntax. + +## Where to Put Module Documentation? + +By default, your module's Markdown documentation files must be placed in the `doc` directory beneath your module's root +directory, e.g.: + + example-module/doc + +## Chapters + +Each Markdown documentation file represents a chapter of your module's documentation. The first found heading inside +each file is the chapter's title. The order of chapters is based on the case insensitive "Natural Order" of your files' +names. Natural Order means that the file names are ordered in the way which seems natural to humans. +It is best practice to prefix Markdown documentation file names with numbers to ensure that they appear in the correct +order, e.g.: + + 1-about.md + 2-installation.md + 3-configuration.md + +## Table Of Contents + +The table of contents for your module's documentation is auto-generated based on all found headings inside each +Markdown documentation file. + +## Linking Between Headings + +For linking between headings, place an anchor where you want to link to, e.g.: + + # Heading + +Please note that anchors have to be unique across all your Markdown documentation files. + +Now you can reference the anchor either in the same or **in another** Markdown documentation file, e.g.: + + This is a link to [Heading](#heading). + +Other tools support linking between headings by giving the filename plus the anchor to link to, e.g.: + + This is a link to [About/Heading](1-about.md#heading.md) + +This syntax is also supported in Icinga Web 2. + +## Including Images + +Images must placed in the `img` directory beneath your module's `public` directory, e.g.: + + example-module/public/img/doc + +Module images can be accessed using the following URL: + + {baseURL}/img/{moduleName}/{file} e.g. icingaweb/img/example-module/doc/example.png + +Markdown's image syntax is very similar to Markdown's link syntax, but prefixed with an exclamation mark, e.g.: + + ![Alt text](http://path/to/img.png "Optional Title") + +URLs to images inside your Markdown documentation files must be specified without the base URL, e.g.: + + ![Example](/img/example-module/doc/example.png) diff --git a/modules/doc/library/Doc/DocController.php b/modules/doc/library/Doc/DocController.php index bc782953f..0d12f58df 100644 --- a/modules/doc/library/Doc/DocController.php +++ b/modules/doc/library/Doc/DocController.php @@ -28,7 +28,7 @@ class DocController extends ModuleActionController $urlParams ); $this->view->title = $chapterId; - return $this->render('chapter', null, true); + $this->render('chapter', null, true); } /** @@ -46,7 +46,7 @@ class DocController extends ModuleActionController $name = ucfirst($name); $this->view->docName = $name; $this->view->title = sprintf($this->translate('%s Documentation'), $name); - return $this->render('toc', null, true); + $this->render('toc', null, true); } /** @@ -71,6 +71,6 @@ class DocController extends ModuleActionController ); $this->view->docName = $name; $this->_request->setParam('format', 'pdf'); - return $this->render('pdf', null, true); + $this->render('pdf', null, true); } } diff --git a/modules/doc/library/Doc/DocIterator.php b/modules/doc/library/Doc/DocIterator.php index 43a9c7727..3045b6309 100644 --- a/modules/doc/library/Doc/DocIterator.php +++ b/modules/doc/library/Doc/DocIterator.php @@ -9,6 +9,8 @@ use Countable; use IteratorAggregate; use RecursiveIteratorIterator; use RecursiveDirectoryIterator; +use Icinga\File\NonEmptyFileIterator; +use Icinga\File\FileExtensionFilterIterator; /** * Iterator over non-empty Markdown files ordered by the case insensitive "natural order" of file names @@ -29,12 +31,14 @@ class DocIterator implements Countable, IteratorAggregate */ public function __construct($path) { - $it = new RecursiveIteratorIterator( + $it = new FileExtensionFilterIterator( new NonEmptyFileIterator( - new MarkdownFileIterator( - new RecursiveDirectoryIterator($path) + new RecursiveIteratorIterator( + new RecursiveDirectoryIterator($path), + RecursiveIteratorIterator::SELF_FIRST ) - ) + ), + 'md' ); // Unfortunately we have no chance to sort the iterator $fileInfo = iterator_to_array($it); diff --git a/modules/doc/library/Doc/DocParser.php b/modules/doc/library/Doc/DocParser.php index c63532dc1..6cfeca418 100644 --- a/modules/doc/library/Doc/DocParser.php +++ b/modules/doc/library/Doc/DocParser.php @@ -31,7 +31,7 @@ class DocParser /** * Create a new documentation parser for the given path * - * @param string $path Path to the documentation + * @param string $path Path to the documentation * * @throws DocException If the documentation directory does not exist * @throws NotReadableError If the documentation directory is not readable diff --git a/modules/doc/library/Doc/MarkdownFileIterator.php b/modules/doc/library/Doc/MarkdownFileIterator.php deleted file mode 100644 index 6f317ce6a..000000000 --- a/modules/doc/library/Doc/MarkdownFileIterator.php +++ /dev/null @@ -1,31 +0,0 @@ -getInnerIterator()->current(); - /* @var $current \SplFileInfo */ - if (! $current->isFile()) { - return false; - } - $filename = $current->getFilename(); - $sfx = substr($filename, -3); - return $sfx === false ? false : strtolower($sfx) === '.md'; - } -} diff --git a/modules/doc/library/Doc/NonEmptyFileIterator.php b/modules/doc/library/Doc/NonEmptyFileIterator.php deleted file mode 100644 index 71bf5acfa..000000000 --- a/modules/doc/library/Doc/NonEmptyFileIterator.php +++ /dev/null @@ -1,31 +0,0 @@ -getInnerIterator()->current(); - /* @var $current \SplFileInfo */ - if (! $current->isFile() - || $current->getSize() === 0 - ) { - return false; - } - return true; - } -} diff --git a/modules/doc/library/Doc/SectionRenderer.php b/modules/doc/library/Doc/SectionRenderer.php index 2fdaf8e90..f923783f6 100644 --- a/modules/doc/library/Doc/SectionRenderer.php +++ b/modules/doc/library/Doc/SectionRenderer.php @@ -232,7 +232,7 @@ class SectionRenderer extends Renderer $html ); $content[] = preg_replace_callback( - '/[^>]*?\s+)?href="#(?P[^"]+)"/', + '/[^>]*?\s+)?href="(?:(?!http:\/\/)[^#]*)#(?P[^"]+)"/', array($callback, 'render'), $html ); diff --git a/modules/doc/module.info b/modules/doc/module.info index 2826d72de..1689fd940 100644 --- a/modules/doc/module.info +++ b/modules/doc/module.info @@ -1,4 +1,4 @@ Module: doc -Version: 2.0.0~alpha4 +Version: 2.0.0 Description: Documentation module Extracts, shows and exports documentation for Icinga Web 2 and it's modules. diff --git a/modules/doc/public/img/doc/markdown.png b/modules/doc/public/img/doc/markdown.png new file mode 100644 index 000000000..93e729bc7 Binary files /dev/null and b/modules/doc/public/img/doc/markdown.png differ diff --git a/modules/doc/run.php b/modules/doc/run.php index 7392e4c22..31aff8ff0 100644 --- a/modules/doc/run.php +++ b/modules/doc/run.php @@ -47,4 +47,3 @@ $this->addRoute('doc/module/chapter', $docModuleChapter); $this->addRoute('doc/icingaweb/chapter', $docIcingaWebChapter); $this->addRoute('doc/module/toc', $docModuleToc); $this->addRoute('doc/module/pdf', $docModulePdf); - diff --git a/modules/monitoring/application/controllers/AlertsummaryController.php b/modules/monitoring/application/controllers/AlertsummaryController.php index 75f0fc1fe..a4ef76b44 100644 --- a/modules/monitoring/application/controllers/AlertsummaryController.php +++ b/modules/monitoring/application/controllers/AlertsummaryController.php @@ -78,7 +78,9 @@ class Monitoring_AlertsummaryController extends Controller 'notification', array( 'host', + 'host_display_name', 'service', + 'service_display_name', 'notification_output', 'notification_contact', 'notification_start_time', @@ -193,11 +195,11 @@ class Monitoring_AlertsummaryController extends Controller $out = new stdClass(); if ($yesterday === $today) { - $out->trend = 'unchanged'; + $out->trend = $this->translate('unchanged'); } elseif ($yesterday > $today) { - $out->trend = 'down'; + $out->trend = $this->translate('down'); } else { - $out->trend = 'up'; + $out->trend = $this->translate('up'); } if ($yesterday <= 0) { @@ -342,10 +344,10 @@ class Monitoring_AlertsummaryController extends Controller $gridChart = new GridChart(); $gridChart->alignTopLeft(); - $gridChart->setAxisLabel('', mt('monitoring', 'Notifications')) + $gridChart->setAxisLabel($this->createPeriodDescription(), mt('monitoring', 'Notifications')) ->setXAxis(new StaticAxis()) - ->setAxisMin(null, 0) - ->setYAxis(new LinearUnit(10)); + ->setYAxis(new LinearUnit(10)) + ->setAxisMin(null, 0); $interval = $this->getInterval(); @@ -429,11 +431,10 @@ class Monitoring_AlertsummaryController extends Controller $item[1] = $item[1]/60/60; } - $gridChart->drawBars( array( 'label' => $this->translate('Notifications'), - 'color' => '#049baf', + 'color' => '#07C0D9', 'data' => $notifications, 'showPoints' => true ) @@ -470,15 +471,15 @@ class Monitoring_AlertsummaryController extends Controller $gridChart = new GridChart(); $gridChart->alignTopLeft(); - $gridChart->setAxisLabel('', mt('monitoring', 'Notifications')) + $gridChart->setAxisLabel($this->createPeriodDescription(), mt('monitoring', 'Notifications')) ->setXAxis(new StaticAxis()) - ->setAxisMin(null, 0) - ->setYAxis(new LinearUnit(10)); + ->setYAxis(new LinearUnit(10)) + ->setAxisMin(null, 0); $gridChart->drawBars( array( 'label' => $this->translate('Notifications'), - 'color' => '#049baf', + 'color' => '#07C0D9', 'data' => $this->notificationData, 'showPoints' => true ) @@ -507,7 +508,9 @@ class Monitoring_AlertsummaryController extends Controller 'notification', array( 'host', + 'host_display_name', 'service', + 'service_display_name', 'notification_output', 'notification_contact', 'notification_start_time', @@ -554,7 +557,7 @@ class Monitoring_AlertsummaryController extends Controller { $format = ''; if ($interval === '1d') { - $format = '%H:00:00'; + $format = '%H:00'; } elseif ($interval === '1w') { $format = '%Y-%m-%d'; } elseif ($interval === '1m') { @@ -623,4 +626,28 @@ class Monitoring_AlertsummaryController extends Controller return $interval; } + + /** + * Create a human-readable description of the current interval size + * + * @return string The description of the current interval size + */ + private function createPeriodDescription() + { + $int = $this->getInterval(); + switch ($int) { + case '1d': + return t('Hour'); + break; + case '1w'; + return t('Day'); + break; + case '1m': + return t('Day'); + break; + case '1y': + return t('Month'); + break; + } + } } diff --git a/modules/monitoring/application/controllers/ChartController.php b/modules/monitoring/application/controllers/ChartController.php index 2024f83f4..757329bfe 100644 --- a/modules/monitoring/application/controllers/ChartController.php +++ b/modules/monitoring/application/controllers/ChartController.php @@ -6,6 +6,8 @@ use Icinga\Module\Monitoring\Controller; use Icinga\Chart\GridChart; use Icinga\Chart\PieChart; use Icinga\Chart\Unit\StaticAxis; +use Icinga\Chart\Unit\LogarithmicUnit; +use Icinga\Chart\Unit\LinearUnit; /** * Class Monitoring_CommandController @@ -20,6 +22,95 @@ class Monitoring_ChartController extends Controller $this->view->compact = $this->_request->getParam('view') === 'compact'; } + private function drawLogChart1() + { + $chart = new GridChart(); + $chart->alignTopLeft(); + $chart->setAxisLabel('X axis label', 'Y axis label') + ->setYAxis(new LogarithmicUnit()); + + for ($i = -15; $i < 15; $i++) { + $data1[] = array($i, -$i * rand(1, 10) * pow(2, rand(1, 2))); + } + for ($i = -15; $i < 15; $i++) { + $data2[] = array($i, 1000 + $i * rand(1, 35) * pow(2, rand(1, 2))); + } + for ($i = -15; $i < 15; $i++) { + $data3[] = array($i, $i * rand(1, 100) * pow(2, rand(1, 10)) - 1000); + } + + $chart->drawLines( + array( + 'label' => 'Random 1', + 'color' => '#F56', + 'data' => $data1, + 'showPoints' => true + ) + ); + $chart->drawLines( + array( + 'label' => 'Random 2', + 'color' => '#fa4', + 'data' => $data2, + 'showPoints' => true + ) + ); + $chart->drawLines( + array( + 'label' => 'Random 3', + 'color' => '#4b7', + 'data' => $data3, + 'showPoints' => true + ) + ); + return $chart; + } + + private function drawLogChart2() + { + $chart = new GridChart(); + $chart->alignTopLeft(); + $chart->setAxisLabel('X axis label', 'Y axis label') + ->setYAxis(new LogarithmicUnit()); + + for ($i = -10; $i < 10; $i++) { + $sign = $i > 0 ? 1 : + ($i < 0 ? -1 : 0); + $data[] = array($i, $sign * pow(10, abs($i))); + } + $chart->drawLines( + array( + 'label' => 'f(x): sign(x) * 10^|x|', + 'color' => '#F56', + 'data' => $data, + 'showPoints' => true + ) + ); + return $chart; + } + private function drawLogChart3() + { + $chart = new GridChart(); + $chart->alignTopLeft(); + $chart->setAxisLabel('X axis label', 'Y axis label') + ->setYAxis(new LogarithmicUnit()); + + for ($i = -2; $i < 3; $i++) { + $sign = $i > 0 ? 1 : + ($i < 0 ? -1 : 0); + $data[] = array($i, $sign * pow(10, abs($i))); + } + $chart->drawLines( + array( + 'label' => 'f(x): sign(x) * 10^|x|', + 'color' => '#F56', + 'data' => $data, + 'showPoints' => true + ) + ); + return $chart; + } + public function testAction() { $this->chart = new GridChart(); @@ -28,7 +119,7 @@ class Monitoring_ChartController extends Controller $data1 = array(); $data2 = array(); $data3 = array(); - for ($i = 0; $i < 25; $i++) { + for ($i = 0; $i < 50; $i++) { $data3[] = array('Label ' . $i, rand(0, 30)); } @@ -36,13 +127,13 @@ class Monitoring_ChartController extends Controller $this->chart->drawLines( array( 'label' => 'Nr of outtakes', - 'color' => 'red', + 'color' => '#F56', 'width' => '5', 'data' => $data ), array( 'label' => 'Some line', - 'color' => 'blue', + 'color' => '#fa4', 'width' => '4', 'data' => $data3, @@ -52,8 +143,8 @@ class Monitoring_ChartController extends Controller */ $this->chart->drawBars( array( - 'label' => 'Some other line', - 'color' => 'green', + 'label' => 'A big amount of data', + 'color' => '#4b7', 'data' => $data3, 'showPoints' => true ) @@ -68,7 +159,11 @@ class Monitoring_ChartController extends Controller ) ); */ - $this->view->svg = $this->chart; + $this->view->svgs = array(); + $this->view->svgs[] = $this->drawLogChart1(); + $this->view->svgs[] = $this->drawLogChart2(); + $this->view->svgs[] = $this->drawLogChart3(); + $this->view->svgs[] = $this->chart; } public function hostgroupAction() @@ -185,18 +280,15 @@ class Monitoring_ChartController extends Controller $upBars = array(); $downBars = array(); $unreachableBars = array(); - foreach ($query as $hostgroup) { + for ($i = 0; $i < 50; $i++) { $upBars[] = array( - $hostgroup->hostgroup, - $hostgroup->hosts_up + (string)$i, rand(1, 200), rand(1, 200) ); $downBars[] = array( - $hostgroup->hostgroup, - $hostgroup->hosts_down_unhandled + (string)$i, rand(1, 200), rand(1, 200) ); $unreachableBars[] = array( - $hostgroup->hostgroup, - $hostgroup->hosts_unreachable_unhandled + (string)$i, rand(1, 200), rand(1, 200) ); } $tooltip = mt('monitoring', '{title}:
{value} of {sum} hosts are {label}'); @@ -272,7 +364,14 @@ class Monitoring_ChartController extends Controller (int) $query->hosts_unreachable_unhandled, (int) $query->hosts_pending ), - 'colors' => array('#44bb77', '#ff4444', '#ff0000', '#E066FF', '#f099FF', '#fefefe'), + 'colors' => array( + '#44bb77', // 'Ok' + '#ff4444', // 'Warning' + '#ff0000', // 'WarningHandled' + '#E066FF', + '#f099FF', + '#fefefe' + ), 'labels'=> array( (int) $query->hosts_up . mt('monitoring', ' Up Hosts'), (int) $query->hosts_down_handled . mt('monitoring', ' Down Hosts (Handled)'), diff --git a/modules/monitoring/application/controllers/CommandController.php b/modules/monitoring/application/controllers/CommandController.php deleted file mode 100644 index d2615104a..000000000 --- a/modules/monitoring/application/controllers/CommandController.php +++ /dev/null @@ -1,1098 +0,0 @@ -form = $form; - } - - /** - * Test if we have a valid form object - * - * @return bool - */ - public function issetForm() - { - return $this->form !== null && ($this->form instanceof Form); - } - - protected function addTitleTab($action) - { - $this->getTabs()->add($action, array( - 'title' => ucfirst($action), - 'url' => Url::fromRequest() - ))->activate($action); - } - - /** - * Post dispatch method - * - * When we have a form put it into the view - */ - public function postDispatch() - { - - if ($this->issetForm()) { - if ($this->form->isSubmittedAndValid()) { - $this->_helper->viewRenderer->setNoRender(true); - $this->_helper->layout()->disableLayout(); - $this->ignoreXhrBody(); - if ($this->_request->getHeader('referer') && ! $this->getRequest()->isXmlHttpRequest()) { - $this->redirect($this->_request->getHeader('referer')); - } - } else { - $this->view->form = $this->form; - } - } - parent::postDispatch(); - } - - /** - * Controller configuration - * - * @throws Icinga\Exception\ConfigurationError - */ - public function init() - { - if ($this->_request->isPost()) { - $instance = $this->_request->getPost('instance'); - $targetConfig = Config::module('monitoring', 'instances'); - if ($instance) { - if ($targetConfig->get($instance)) { - $this->target = new CommandPipe($targetConfig->get($instance)); - } else { - throw new ConfigurationError( - $this->translate('Instance is not configured: %s'), - $instance - ); - } - } else { - if ($targetConfig && $targetInfo = $targetConfig->current()) { - // Take the very first section - $this->target = new CommandPipe($targetInfo); - } else { - throw new ConfigurationError($this->translate('No instances are configured yet')); - } - } - } - - if ($this->getRequest()->getActionName() !== 'list') { - $this->_helper->viewRenderer->setRender(self::DEFAULT_VIEW_SCRIPT); - } - - $this->view->objects = array(); - } - - /** - * Retrieve all existing targets for host- and service combination - * - * @param $hostOnly Ignore the service parameters - * (for example when using commands that only make sense for hosts) - * @return array Array of monitoring objects - * @throws Icinga\Exception\MissingParameterException - */ - private function selectCommandTargets($hostOnly = false) - { - $query = null; - - $fields = array( - 'host_name', - 'host_state' - ); - - try { - $hostname = $this->getParam('host', null); - $servicename = $this->getParam('service', null); - - if (!$hostname && !$servicename) { - throw new MissingParameterException('No target given for this command'); - } - - if ($servicename && !$hostOnly) { - $fields[] = 'service_description'; - $query = $this->backend->select() - ->from('serviceStatus', $fields) - ->where('host', $hostname) - ->where('service', $servicename); - } elseif ($hostname) { - $query = $this->backend->select()->from('hostStatus', $fields)->where('host', $hostname); - } else { - throw new MissingParameterException('hostOnly command got no hostname'); - } - return $query->getQuery()->fetchAll(); - - } catch (\Exception $e) { - Logger::error( - "CommandController: SQL Query '%s' failed (message %s) ", - $query ? (string) $query->dump() : '--', $e->getMessage() - ); - return array(); - } - } - - /** - * Convert other params into valid command structure - * - * @param array $supported Array of supported parameter names - * @param array $params Parameters from request - * - * @return array Return - */ - private function selectOtherTargets(array $supported, array $params) - { - $others = array_diff_key($supported, array('host' => true, 'service' => true)); - $otherParams = array_intersect_key($params, $others); - $out = array(); - - foreach ($otherParams as $name => $value) { - $data = new stdClass(); - $data->{$name} = $value; - $out[] = $data; - } - - return $out; - } - - /** - * Displays a list of all commands - * - * This method uses reflection on the sourcecode to determine all *Action classes and return - * a list of them (ignoring the listAction) - */ - public function listAction() - { - $reflection = new ReflectionObject($this); - $commands = array(); - $methods = $reflection->getMethods(ReflectionMethod::IS_PUBLIC); - foreach ($methods as $method) { - $name = $method->getName(); - if ($name !== 'listAction' && preg_match('/Action$/', $name)) { - $commands[] = preg_replace('/Action$/', '', $name); - } - } - $this->view->commands = $commands; - } - - /** - * Tell the controller that at least one of the parameters in $supported is required to be availabe - * - * @param array $supported An array of properties to check for existence in the POST or GET parameter list - * @throws Exception When non of the supported parameters is given - */ - private function setSupportedParameters(array $supported) - { - $objects = array(); - - $supported = array_flip($supported); - - $given = array_intersect_key($supported, $this->getRequest()->getParams()); - - if (empty($given)) { - throw new IcingaException( - 'Missing parameter, supported: %s', - implode(', ', array_flip($supported)) - ); - } - - if (isset($given['host'])) { - $objects = $this->selectCommandTargets(!in_array("service", $supported)); - if (empty($objects)) { - throw new IcingaException('No objects found for your command'); - } - } - - $this->view->objects = $objects; - } - - // ------------------------------------------------------------------------ - // Commands for hosts / services - // ------------------------------------------------------------------------ - - /** - * Handle command disableactivechecks - */ - public function disableactivechecksAction() - { - $this->setSupportedParameters(array('host', 'service', 'global')); - - $form = new SingleArgumentCommandForm(); - - $form->setCommand( - 'DISABLE_HOST_CHECK', - 'DISABLE_SVC_CHECK' - ); - - $form->setGlobalCommands( - 'STOP_EXECUTING_HOST_CHECKS', - 'STOP_EXECUTING_SVC_CHECKS' - ); - - $form->setRequest($this->getRequest()); - $form->setSubmitLabel($this->translate('Disable Active Checks')); - - if ($form->provideGlobalCommand()) { - $form->addNote($this->translate('Disable active checks on a program-wide basis.')); - } else { - $form->addNote($this->translate('Disable active checks for this object.')); - } - - $this->setForm($form); - - if ($form->IsSubmittedAndValid() === true) { - $this->target->sendCommand($form->createCommand(), $this->view->objects); - Notification::success($this->translate('Command has been sent, active checks will be disabled')); - } - } - - /** - * Handle command enableactivechecks - */ - public function enableactivechecksAction() - { - $this->setSupportedParameters(array('host', 'service', 'global')); - $form = new SingleArgumentCommandForm(); - $form->setCommand('ENABLE_HOST_CHECK', 'ENABLE_SVC_CHECK'); - $form->setGlobalCommands('START_EXECUTING_HOST_CHECKS', 'START_EXECUTING_SVC_CHECKS'); - - $form->setRequest($this->getRequest()); - $form->setSubmitLabel($this->translate('Enable Active Checks')); - if ($form->provideGlobalCommand()) { - $form->addNote($this->translate('Enable active checks on a program-wide basis.')); - } else { - $form->addNote($this->translate('Enable active checks for this object.')); - } - $this->setForm($form); - - if ($form->IsSubmittedAndValid() === true) { - $this->target->sendCommand($form->createCommand(), $this->view->objects); - Notification::success($this->translate('Command has been sent, active checks will be enabled')); - } - } - - /** - * Handle command reschedulenextcheck - */ - public function reschedulenextcheckAction() - { - $this->addTitleTab('Reschedule Next Check'); - $this->setSupportedParameters(array('host', 'service')); - $form = new RescheduleNextCheckForm(); - $form->setRequest($this->getRequest()); - $form->setConfiguration(Config::app()); - - $this->setForm($form); - - if ($form->IsSubmittedAndValid() === true) { - $this->target->sendCommand($form->createCommand(), $this->view->objects); - Notification::success($this->translate('Command has been sent, check will be rescheduled')); - } - } - - /** - * Handle command submitpassivecheckresult - */ - public function submitpassivecheckresultAction() - { - $this->setSupportedParameters(array('host', 'service')); - $type = SubmitPassiveCheckResultForm::TYPE_SERVICE; - if ($this->getParam('service', null) === null) { - $type = SubmitPassiveCheckResultForm::TYPE_HOST; - } - - $form = new SubmitPassiveCheckResultForm(); - $form->setRequest($this->getRequest()); - $form->setType($type); - - $this->setForm($form); - - if ($form->IsSubmittedAndValid() === true) { - $this->target->sendCommand($form->createCommand(), $this->view->objects); - Notification::success($this->translate('Passive check result has been submitted')); - } - } - - /** - * Handle command stopobsessing - */ - public function stopobsessingAction() - { - $this->setSupportedParameters(array('host', 'service', 'global')); - $form = new SingleArgumentCommandForm(); - $form->setRequest($this->getRequest()); - $form->setSubmitLabel($this->translate('Stop obsessing')); - - if ($form->provideGlobalCommand() === true) { - $form->addNote($this->translate('Disable obsessing on a program-wide basis.')); - } else { - $form->addNote($this->translate('Stop obsessing over this object.')); - } - - $form->setCommand( - 'STOP_OBSESSING_OVER_HOST', - 'STOP_OBSESSING_OVER_SVC' - ); - - $form->setGlobalCommands( - 'STOP_OBSESSING_OVER_HOST_CHECKS', - 'STOP_OBSESSING_OVER_SVC_CHECKS' - ); - - $this->setForm($form); - - if ($form->IsSubmittedAndValid() === true) { - $this->target->sendCommand($form->createCommand(), $this->view->objects); - Notification::success($this->translate('Command has been sent, obsessing will be disabled')); - } - } - - /** - * Handle command startobsessing - */ - public function startobsessingAction() - { - $this->setSupportedParameters(array('host', 'service', 'global')); - $form = new SingleArgumentCommandForm(); - $form->setRequest($this->getRequest()); - $form->setSubmitLabel($this->translate('Start obsessing')); - - if ($form->provideGlobalCommand() === true) { - $form->addNote($this->translate('Enable obsessing on a program-wide basis.')); - } else { - $form->addNote($this->translate('Start obsessing over this object.')); - } - - $form->setCommand( - 'START_OBSESSING_OVER_HOST', - 'START_OBSESSING_OVER_SVC' - ); - - $form->setGlobalCommands( - 'START_OBSESSING_OVER_HOST_CHECKS', - 'START_OBSESSING_OVER_SVC_CHECKS' - ); - - $this->setForm($form); - - if ($form->IsSubmittedAndValid() === true) { - $this->target->sendCommand($form->createCommand(), $this->view->objects); - Notification::success($this->translate('Command has been sent, obsessing will be enabled')); - } - } - - /** - * Handle command stopacceptingpassivechecks - */ - public function stopacceptingpassivechecksAction() - { - $this->setSupportedParameters(array('host', 'service', 'global')); - $form = new SingleArgumentCommandForm(); - $form->setRequest($this->getRequest()); - $form->setSubmitLabel($this->translate('Stop Accepting Passive Checks')); - - if ($form->provideGlobalCommand() === true) { - $form->addNote($this->translate('Disable passive checks on a program-wide basis.')); - } else { - $form->addNote($this->translate('Passive checks for this object will be omitted.')); - } - - $form->setCommand( - 'DISABLE_PASSIVE_HOST_CHECKS', - 'DISABLE_PASSIVE_SVC_CHECKS' - ); - - $form->setGlobalCommands( - 'STOP_ACCEPTING_PASSIVE_HOST_CHECKS', - 'STOP_ACCEPTING_PASSIVE_SVC_CHECKS' - ); - - $this->setForm($form); - - if ($form->IsSubmittedAndValid() === true) { - $this->target->sendCommand($form->createCommand(), $this->view->objects); - Notification::success($this->translate('Command has been sent, passive check results will be refused')); - } - } - - /** - * Handle command startacceptingpassivechecks - */ - public function startacceptingpassivechecksAction() - { - $this->setSupportedParameters(array('host', 'service', 'global')); - $form = new SingleArgumentCommandForm(); - $form->setRequest($this->getRequest()); - $form->setSubmitLabel($this->translate('Start Accepting Passive Checks')); - - if ($form->provideGlobalCommand() === true) { - $form->addNote($this->translate('Enable passive checks on a program-wide basis.')); - } else { - $form->addNote($this->translate('Passive checks for this object will be accepted.')); - } - - $form->setCommand( - 'ENABLE_PASSIVE_HOST_CHECKS', - 'ENABLE_PASSIVE_SVC_CHECKS' - ); - - $form->setGlobalCommands( - 'START_ACCEPTING_PASSIVE_HOST_CHECKS', - 'START_ACCEPTING_PASSIVE_SVC_CHECKS' - ); - $this->setForm($form); - - if ($form->IsSubmittedAndValid() === true) { - $this->target->sendCommand($form->createCommand(), $this->view->objects); - Notification::success($this->translate('Command has been sent, passive check results will be accepted')); - } - } - - /** - * Disable notifications with expiration - * - * This is a global command only - */ - public function disablenotificationswithexpireAction() - { - $this->setParam('global', 1); - $form = new DisableNotificationWithExpireForm(); - $form->setRequest($this->_request); - $this->setForm($form); - - if ($form->IsSubmittedAndValid() === true) { - $this->target->sendCommand($form->createCommand(), $this->view->objects); - Notification::success($this->translate('Command has been sent, notifications will be disabled')); - } - } - - /** - * Handle command disablenotifications - */ - public function disablenotificationsAction() - { - $this->setSupportedParameters(array('host', 'service', 'global')); - $form = new SingleArgumentCommandForm(); - $form->setRequest($this->getRequest()); - - $form->setSubmitLabel($this->translate('Disable Notifications')); - - if ($form->provideGlobalCommand() === true) { - $form->addNote($this->translate('Disable notifications on a program-wide basis.')); - } else { - $form->addNote($this->translate('Notifications for this object will be disabled.')); - } - - $form->setCommand('DISABLE_HOST_NOTIFICATIONS', 'DISABLE_SVC_NOTIFICATIONS'); - $form->setGlobalCommands('DISABLE_NOTIFICATIONS'); - - $this->setForm($form); - - if ($form->IsSubmittedAndValid() === true) { - $this->target->sendCommand($form->createCommand(), $this->view->objects); - Notification::success($this->translate('Command has been sent, notifications will be disabled')); - } - - } - - /** - * Handle command enablenotifications - */ - public function enablenotificationsAction() - { - $this->addTitleTab('Enable Notifications'); - $this->setSupportedParameters(array('host', 'service', 'global')); - $form = new SingleArgumentCommandForm(); - $form->setRequest($this->getRequest()); - - $form->setSubmitLabel($this->translate('Enable Notifications')); - - if ($form->provideGlobalCommand() === true) { - $form->addNote($this->translate('Enable notifications on a program-wide basis.')); - } else { - $form->addNote($this->translate('Notifications for this object will be enabled.')); - } - - $form->setCommand('ENABLE_HOST_NOTIFICATIONS', 'ENABLE_SVC_NOTIFICATIONS'); - $form->setGlobalCommands('ENABLE_NOTIFICATIONS'); - - $this->setForm($form); - - if ($form->IsSubmittedAndValid() === true) { - $this->target->sendCommand($form->createCommand(), $this->view->objects); - Notification::success($this->translate('Command has been sent, notifications will be enabled')); - } - } - - /** - * Handle command sendcustomnotification - */ - public function sendcustomnotificationAction() - { - $this->setSupportedParameters(array('host', 'service')); - $form = new CustomNotificationForm(); - $form->setRequest($this->getRequest()); - $this->setForm($form); - - if ($form->IsSubmittedAndValid() === true) { - $this->target->sendCommand($form->createCommand(), $this->view->objects); - Notification::success($this->translate('Custom notification has been sent')); - } - } - - /** - * Handle command scheduledowntime - */ - public function scheduledowntimeAction() - { - $this->addTitleTab('Schedule Downtime'); - $this->setSupportedParameters(array('host', 'service')); - $form = new ScheduleDowntimeForm(); - $form->setRequest($this->getRequest()); - $form->setConfiguration(Config::app()); - $form->setWithChildren(false); - $this->setForm($form); - - if ($form->IsSubmittedAndValid() === true) { - $this->target->sendCommand($form->createCommand(), $this->view->objects); - Notification::success($this->translate('Downtime scheduling requested')); - } - } - - /** - * Handle command scheduledowntimeswithchildren - */ - public function scheduledowntimeswithchildrenAction() - { - $this->setSupportedParameters(array('host')); - $form = new ScheduleDowntimeForm(); - $form->setRequest($this->getRequest()); - $form->setConfiguration(Config::app()); - $form->setWithChildren(true); - $this->setForm($form); - - if ($form->IsSubmittedAndValid() === true) { - $this->target->sendCommand($form->createCommand(), $this->view->objects); - Notification::success($this->translate('Downtime scheduling requested')); - } - } - - /** - * Handle command removedowntimeswithchildren - */ - public function removedowntimeswithchildrenAction() - { - $this->setSupportedParameters(array('host')); - $form = new SingleArgumentCommandForm(); - $form->setRequest($this->getRequest()); - $form->setSubmitLabel($this->translate('Remove Downtime(s)')); - $form->addNote($this->translate('Remove downtime(s) from this host and its services.')); - $form->setCommand('DEL_DOWNTIME_BY_HOST_NAME', 'DEL_DOWNTIME_BY_HOST_NAME'); - $this->setForm($form); - - if ($form->IsSubmittedAndValid() === true) { - $this->target->sendCommand($form->createCommand(), $this->view->objects); - Notification::success($this->translate('Downtime removal requested')); - } - } - - /** - * Handle command disablenotificationswithchildren - */ - public function disablenotificationswithchildrenAction() - { - $this->setSupportedParameters(array('host')); - $form = new SingleArgumentCommandForm(); - $form->setRequest($this->getRequest()); - $form->setSubmitLabel($this->translate('Disable Notifications')); - $form->addNote($this->translate('Notifications for this host and its services will be disabled.')); - $form->setCommand('DISABLE_ALL_NOTIFICATIONS_BEYOND_HOST'); - $this->setForm($form); - - if ($form->IsSubmittedAndValid() === true) { - $this->target->sendCommand($form->createCommand(), $this->view->objects); - $form->setCommand('DISABLE_HOST_NOTIFICATIONS', 'DISABLE_SVC_NOTIFICATIONS'); - $this->target->sendCommand($form->createCommand(), $this->view->objects); - Notification::success($this->translate('Command has been sent, notifications will be disabled')); - } - } - - /** - * Handle command enablenotificationswithchildren - */ - public function enablenotificationswithchildrenAction() - { - $this->setSupportedParameters(array('host')); - $form = new SingleArgumentCommandForm(); - $form->setRequest($this->getRequest()); - $form->setSubmitLabel($this->translate('Enable Notifications')); - $form->addNote($this->translate('Notifications for this host and its services will be enabled.')); - $form->setCommand('ENABLE_ALL_NOTIFICATIONS_BEYOND_HOST'); - $this->setForm($form); - - if ($form->IsSubmittedAndValid() === true) { - $this->target->sendCommand($form->createCommand(), $this->view->objects); - $form->setCommand('ENABLE_HOST_NOTIFICATIONS', 'ENABLE_SVC_NOTIFICATIONS'); - $this->target->sendCommand($form->createCommand(), $this->view->objects); - Notification::success($this->translate('Command has been sent, notifications will be enabled')); - } - } - - /** - * Handle command reschedulenextcheckwithchildren - */ - public function reschedulenextcheckwithchildrenAction() - { - $this->setSupportedParameters(array('host')); - $form = new RescheduleNextCheckForm(); - $form->setRequest($this->getRequest()); - $form->setConfiguration(Config::app()); - $form->setWithChildren(true); - - $this->setForm($form); - - if ($form->IsSubmittedAndValid() === true) { - $this->target->sendCommand($form->createCommand(), $this->view->objects); - Notification::success($this->translate('Command has been sent, checks will be rescheduled')); - } - } - - /** - * Handle command disableactivecheckswithchildren - */ - public function disableactivecheckswithchildrenAction() - { - $this->setSupportedParameters(array('host')); - $form = new SingleArgumentCommandForm(); - $form->setRequest($this->getRequest()); - $form->setSubmitLabel($this->translate('Disable Active Checks')); - $form->addNote($this->translate('Disable active checks for this host and its services.')); - $form->setCommand('DISABLE_HOST_CHECK'); - $this->setForm($form); - - if ($form->IsSubmittedAndValid() === true) { - // @TODO(mh): Missing child command - $this->target->sendCommand($form->createCommand(), $this->view->objects); - Notification::success($this->translate('Command has been sent, active checks will be disabled')); - } - } - - /** - * Handle command enableactivecheckswithchildren - */ - public function enableactivecheckswithchildrenAction() - { - $this->setSupportedParameters(array('host')); - $form = new SingleArgumentCommandForm(); - $form->setRequest($this->getRequest()); - $form->setSubmitLabel($this->translate('Enable Active Checks')); - $form->addNote($this->translate('Enable active checks for this host and its services.')); - $form->setCommand('ENABLE_HOST_CHECK'); - $this->setForm($form); - - if ($form->IsSubmittedAndValid() === true) { - // @TODO(mh): Missing child command - $this->target->sendCommand($form->createCommand(), $this->view->objects); - Notification::success($this->translate('Command has been sent, active checks will be enabled')); - } - } - - /** - * Handle command disableeventhandler - */ - public function disableeventhandlerAction() - { - $this->setSupportedParameters(array('host', 'service', 'global')); - $form = new SingleArgumentCommandForm(); - $form->setRequest($this->getRequest()); - $form->setSubmitLabel($this->translate('Disable Event Handler')); - - if ($form->provideGlobalCommand() === true) { - $form->addNote($this->translate('Disable event handler for the whole system.')); - } else { - $form->addNote($this->translate('Disable event handler for this object.')); - } - - $form->setCommand( - 'DISABLE_HOST_EVENT_HANDLER', - 'DISABLE_SVC_EVENT_HANDLER' - ); - - $form->setGlobalCommands('DISABLE_EVENT_HANDLERS'); - - $this->setForm($form); - - if ($form->IsSubmittedAndValid() === true) { - $this->target->sendCommand($form->createCommand(), $this->view->objects); - Notification::success($this->translate('Command has been sent, event handlers will be disabled')); - } - } - - /** - * Handle command enableeventhandler - */ - public function enableeventhandlerAction() - { - $this->setSupportedParameters(array('host', 'service', 'global')); - - $form = new SingleArgumentCommandForm(); - $form->setRequest($this->getRequest()); - $form->setSubmitLabel($this->translate('Enable Event Handler')); - - if ($form->provideGlobalCommand() === true) { - $form->addNote($this->translate('Enable event handlers on the whole system.')); - } else { - $form->addNote($this->translate('Enable event handler for this object.')); - } - - $form->setCommand( - 'ENABLE_HOST_EVENT_HANDLER', - 'ENABLE_SVC_EVENT_HANDLER' - ); - - $form->setGlobalCommands('ENABLE_EVENT_HANDLERS'); - - $this->setForm($form); - - if ($form->IsSubmittedAndValid() === true) { - $this->target->sendCommand($form->createCommand(), $this->view->objects); - Notification::success($this->translate('Command has been sent, event handlers will be enabled')); - } - } - - /** - * Handle command disableflapdetection - */ - public function disableflapdetectionAction() - { - $this->setSupportedParameters(array('host', 'service', 'global')); - $form = new SingleArgumentCommandForm(); - $form->setRequest($this->getRequest()); - $form->setSubmitLabel($this->translate('Disable Flapping Detection')); - - if ($form->provideGlobalCommand() === true) { - $form->addNote($this->translate('Disable flapping detection on a program-wide basis.')); - } else { - $form->addNote($this->translate('Disable flapping detection for this object.')); - } - - $form->setCommand( - 'DISABLE_HOST_FLAP_DETECTION', - 'DISABLE_SVC_FLAP_DETECTION' - ); - - $form->setGlobalCommands( - 'DISABLE_FLAP_DETECTION' - ); - - $this->setForm($form); - - if ($form->IsSubmittedAndValid() === true) { - $this->target->sendCommand($form->createCommand(), $this->view->objects); - Notification::success($this->translate('Command has been sent, flap detection will be disabled')); - } - } - - /** - * Handle command enableflapdetection - */ - public function enableflapdetectionAction() - { - $this->setSupportedParameters(array('host', 'service', 'global')); - $form = new SingleArgumentCommandForm(); - $form->setRequest($this->getRequest()); - $form->setSubmitLabel($this->translate('Enable Flapping Detection')); - - if ($form->provideGlobalCommand() === true) { - $form->addNote($this->translate('Enable flapping detection on a program-wide basis.')); - } else { - $form->addNote($this->translate('Enable flapping detection for this object.')); - } - - $form->setCommand( - 'ENABLE_HOST_FLAP_DETECTION', - 'ENABLE_SVC_FLAP_DETECTION' - ); - - $form->setGlobalCommands( - 'ENABLE_FLAP_DETECTION' - ); - - $this->setForm($form); - - if ($form->IsSubmittedAndValid() === true) { - $this->target->sendCommand($form->createCommand(), $this->view->objects); - Notification::success($this->translate('Command has been sent, flap detection will be enabled')); - } - } - - /** - * Handle command addcomment - */ - public function addcommentAction() - { - $this->addTitleTab('Add comment'); - $this->setSupportedParameters(array('host', 'service')); - $form = new CommentForm(); - $form->setRequest($this->_request); - - $this->setForm($form); - - if ($form->IsSubmittedAndValid() === true) { - $this->target->sendCommand($form->createCommand(), $this->view->objects); - Notification::success($this->translate('Your new comment has been submitted')); - } - } - - /** - * Remove a single comment - */ - public function removecommentAction() - { - $this->addTitleTab('Remove Comment'); - $this->setSupportedParameters(array('commentid', 'host', 'service')); - $form = new SingleArgumentCommandForm(); - $form->setRequest($this->_request); - $form->setCommand('DEL_HOST_COMMENT', 'DEL_SVC_COMMENT'); - $form->setParameterName('commentid'); - $form->setSubmitLabel($this->translate('Remove comment')); - $form->setObjectIgnoreFlag(true); - $this->setForm($form); - - if ($form->IsSubmittedAndValid() === true) { - $this->target->sendCommand($form->createCommand(), $this->view->objects); - Notification::success($this->translate('Comment removal has been requested')); - } - } - - /** - * Handle command resetattributes - */ - public function resetattributesAction() - { - $this->setSupportedParameters(array('host', 'service')); - $form = new SingleArgumentCommandForm(); - $form->setRequest($this->getRequest()); - $form->setSubmitLabel($this->translate('Reset Attributes')); - $form->addNote($this->translate('Reset modified attributes to its default.')); - $form->setCommand('CHANGE_HOST_MODATTR', 'CHANGE_SVC_MODATTR'); - $form->setParameterValue(0); - $this->setForm($form); - - if ($form->IsSubmittedAndValid() === true) { - $this->target->sendCommand($form->createCommand(), $this->view->objects); - } - } - - /** - * Handle command acknowledgeproblem - */ - public function acknowledgeproblemAction() - { - $this->addTitleTab('Acknowledge Problem'); - $this->setSupportedParameters(array('host', 'service')); - $form = new AcknowledgeForm(); - $form->setRequest($this->getRequest()); - $form->setConfiguration(Config::app()); - - if ($form->IsSubmittedAndValid() === true) { - $this->target->sendCommand($form->createCommand(), $this->view->objects); - Notification::success($this->translate('Acknowledgement has been sent')); - } - - $this->setForm($form); - } - - /** - * Handle command removeacknowledgement - */ - public function removeacknowledgementAction() - { - $this->addTitleTab('Remove Acknowledgement'); - $this->setSupportedParameters(array('host', 'service')); - $form = new SingleArgumentCommandForm(); - $form->setRequest($this->getRequest()); - $form->setSubmitLabel($this->translate('Remove Problem Acknowledgement')); - $form->addNote($this->translate('Remove problem acknowledgement for this object.')); - $form->setCommand('REMOVE_HOST_ACKNOWLEDGEMENT', 'REMOVE_SVC_ACKNOWLEDGEMENT'); - $this->setForm($form); - - if ($form->IsSubmittedAndValid() === true) { - $this->target->sendCommand($form->createCommand(), $this->view->objects); - Notification::success($this->translate('Acknowledgement removal has been requested')); - } - } - - /** - * Handle command delaynotification - */ - public function delaynotificationAction() - { - $this->setSupportedParameters(array('host', 'service')); - $form = new DelayNotificationForm(); - $form->setRequest($this->getRequest()); - - $this->setForm($form); - - if ($form->IsSubmittedAndValid() === true) { - $this->target->sendCommand($form->createCommand(), $this->view->objects); - Notification::success($this->translate('Notification delay has been requested')); - } - } - - /** - * Handle command removedowntime - */ - public function removedowntimeAction() - { - $this->setSupportedParameters(array('host', 'service', 'downtimeid')); - $form = new SingleArgumentCommandForm(); - $form->setRequest($this->getRequest()); - - $form->setSubmitLabel($this->translate('Delete Downtime')); - $form->setParameterName('downtimeid'); - $form->addNote($this->translate('Delete a single downtime with the id shown above')); - $form->setCommand('DEL_HOST_DOWNTIME', 'DEL_SVC_DOWNTIME'); - $form->setObjectIgnoreFlag(true); - $this->setForm($form); - - if ($form->IsSubmittedAndValid() === true) { - $this->target->sendCommand($form->createCommand(), $this->view->objects); - Notification::success($this->translate('Downtime removal has been requested')); - } - } - - /** - * Shutdown the icinga process - */ - public function shutdownprocessAction() - { - $this->setParam('global', '1'); - $form = new SingleArgumentCommandForm(); - $form->setRequest($this->_request); - - $form->setSubmitLabel($this->translate('Shutdown monitoring process')); - $form->addNote($this->translate('Stop monitoring instance. You have to start it again from command line.')); - $form->setGlobalCommands('SHUTDOWN_PROCESS'); - $this->setForm($form); - - if ($form->IsSubmittedAndValid() === true) { - $this->target->sendCommand($form->createCommand(), $this->view->objects); - Notification::success($this->translate('Command has been sent, process will shut down')); - } - } - - /** - * Restart the icinga process - */ - public function restartprocessAction() - { - $this->setParam('global', '1'); - $form = new SingleArgumentCommandForm(); - $form->setRequest($this->_request); - - $form->setSubmitLabel($this->translate('Restart monitoring process')); - $form->addNote($this->translate('Restart the monitoring process.')); - $form->setGlobalCommands('RESTART_PROCESS'); - - $this->setForm($form); - - if ($form->IsSubmittedAndValid() === true) { - $this->target->sendCommand($form->createCommand(), $this->view->objects); - Notification::success($this->translate('Command has been sent, monitoring process will restart now')); - } - } - - /** - * Disable processing of performance data - */ - public function disableperformancedataAction() - { - $this->setParam('global', 1); - $form = new SingleArgumentCommandForm(); - $form->setRequest($this->_request); - - $form->setSubmitLabel($this->translate('Disable Performance Data')); - $form->addNote($this->translate('Disable processing of performance data on a program-wide basis.')); - - $form->setGlobalCommands('DISABLE_PERFORMANCE_DATA'); - - $this->setForm($form); - - if ($form->IsSubmittedAndValid() === true) { - $this->target->sendCommand($form->createCommand(), $this->view->objects); - Notification::success($this->translate('Command has been sent, performance data processing will be disabled')); - } - } - - /** - * Enable processing of performance data - */ - public function enableperformancedataAction() - { - $this->setParam('global', 1); - $form = new SingleArgumentCommandForm(); - $form->setRequest($this->_request); - - $form->setSubmitLabel($this->translate('Enable Performance Data')); - $form->addNote($this->translate('Enable processing of performance data on a program-wide basis.')); - - $form->setGlobalCommands('ENABLE_PERFORMANCE_DATA'); - - $this->setForm($form); - - if ($form->IsSubmittedAndValid() === true) { - $this->target->sendCommand($form->createCommand(), $this->view->objects); - Notification::success($this->translate('Command has been sent, performance data processing will be enabled')); - } - } -} diff --git a/modules/monitoring/application/controllers/HostController.php b/modules/monitoring/application/controllers/HostController.php index ab62c3756..4eccb8899 100644 --- a/modules/monitoring/application/controllers/HostController.php +++ b/modules/monitoring/application/controllers/HostController.php @@ -26,20 +26,15 @@ class Monitoring_HostController extends MonitoredObjectController public function init() { $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')); } $this->object = $host; $this->createTabs(); - } - - /** - * Show a host - */ - public function showAction() - { $this->getTabs()->activate('host'); - parent::showAction(); } /** @@ -47,6 +42,8 @@ class Monitoring_HostController extends MonitoredObjectController */ public function acknowledgeProblemAction() { + $this->assertPermission('monitoring/command/acknowledge-problem'); + $this->view->title = $this->translate('Acknowledge Host Problem'); $this->handleCommandForm(new AcknowledgeProblemCommandForm()); } @@ -56,6 +53,8 @@ class Monitoring_HostController extends MonitoredObjectController */ public function addCommentAction() { + $this->assertPermission('monitoring/command/comment/add'); + $this->view->title = $this->translate('Add Host Comment'); $this->handleCommandForm(new AddCommentCommandForm()); } @@ -65,6 +64,8 @@ class Monitoring_HostController extends MonitoredObjectController */ public function rescheduleCheckAction() { + $this->assertPermission('monitoring/command/schedule-check'); + $this->view->title = $this->translate('Reschedule Host Check'); $this->handleCommandForm(new ScheduleHostCheckCommandForm()); } @@ -74,6 +75,8 @@ class Monitoring_HostController extends MonitoredObjectController */ public function scheduleDowntimeAction() { + $this->assertPermission('monitoring/command/downtime/schedule'); + $this->view->title = $this->translate('Schedule Host Downtime'); $this->handleCommandForm(new ScheduleHostDowntimeCommandForm()); } @@ -83,6 +86,8 @@ class Monitoring_HostController extends MonitoredObjectController */ public function processCheckResultAction() { + $this->assertPermission('monitoring/command/process-check-result'); + $this->view->title = $this->translate('Submit Passive Host Check Result'); $this->handleCommandForm(new ProcessCheckResultCommandForm()); } diff --git a/modules/monitoring/application/controllers/HostsController.php b/modules/monitoring/application/controllers/HostsController.php index 4944cc237..869be92d8 100644 --- a/modules/monitoring/application/controllers/HostsController.php +++ b/modules/monitoring/application/controllers/HostsController.php @@ -72,8 +72,10 @@ class Monitoring_HostsController extends Controller 'host_obsessing'*/ )); $unhandledObjects = array(); + $unhandledFilterExpressions = array(); $acknowledgedObjects = array(); $objectsInDowntime = array(); + $downtimeFilterExpressions = array(); $hostStates = array( Host::getStateText(Host::STATE_UP) => 0, Host::getStateText(Host::STATE_DOWN) => 0, @@ -81,15 +83,17 @@ class Monitoring_HostsController extends Controller Host::getStateText(Host::STATE_PENDING) => 0, ); foreach ($this->hostList as $host) { - /** @var Service $host */ + /** @var Host $host */ if ((bool) $host->problem === true && (bool) $host->handled === false) { $unhandledObjects[] = $host; + $unhandledFilterExpressions[] = Filter::where('host', $host->getName()); } if ((bool) $host->acknowledged === true) { $acknowledgedObjects[] = $host; } if ((bool) $host->in_downtime === true) { $objectsInDowntime[] = $host; + $downtimeFilterExpressions[] = Filter::where('downtime_host', $host->getName()); } ++$hostStates[$host::getStateText($host->state)]; } @@ -108,16 +112,15 @@ class Monitoring_HostsController extends Controller $this->view->hostStates = $hostStates; $this->view->objects = $this->hostList; $this->view->unhandledObjects = $unhandledObjects; - $this->view->acknowledgeUnhandledLink = Url::fromRequest() - ->setPath('monitoring/hosts/acknowledge-problem') - ->addParams(array('host_problem' => 1, 'host_handled' => 0)); - $this->view->downtimeUnhandledLink = Url::fromRequest() - ->setPath('monitoring/hosts/schedule-downtime') - ->addParams(array('host_problem' => 1, 'host_handled' => 0)); + $unhandledFilterQueryString = Filter::matchAny($unhandledFilterExpressions)->toQueryString(); + $this->view->acknowledgeUnhandledLink = Url::fromPath('monitoring/hosts/acknowledge-problem') + ->setQueryString($unhandledFilterQueryString); + $this->view->downtimeUnhandledLink = Url::fromPath('monitoring/hosts/schedule-downtime') + ->setQueryString($unhandledFilterQueryString); $this->view->acknowledgedObjects = $acknowledgedObjects; $this->view->objectsInDowntime = $objectsInDowntime; - $this->view->inDowntimeLink = Url::fromRequest() - ->setPath('monitoring/list/downtimes'); + $this->view->inDowntimeLink = Url::fromPath('monitoring/list/downtimes') + ->setQueryString(Filter::matchAny($downtimeFilterExpressions)->toQueryString()); $this->view->havingCommentsLink = Url::fromRequest() ->setPath('monitoring/list/comments'); $this->view->hostStatesPieChart = $this->createPieChart( @@ -131,10 +134,9 @@ class Monitoring_HostsController extends Controller { $chart = new InlinePie(array_values($states), $title, $colors); return $chart - ->setLabel(array_map('strtoupper', array_keys($states))) - ->setHeight(100) - ->setWidth(100) - ->setTitle($title); + ->setSize(75) + ->setTitle('') + ->setSparklineClass('sparkline-multi'); } /** diff --git a/modules/monitoring/application/controllers/ListController.php b/modules/monitoring/application/controllers/ListController.php index 4f92a25b1..faaea713a 100644 --- a/modules/monitoring/application/controllers/ListController.php +++ b/modules/monitoring/application/controllers/ListController.php @@ -1,6 +1,4 @@ params->shift('stateType', 'soft'); - if ($stateType == 'hard') { + if (strtolower($this->params->shift('stateType', 'soft')) === 'hard') { $stateColumn = 'host_hard_state'; $stateChangeColumn = 'host_last_hard_state_change'; } else { - $stateType = 'soft'; $stateColumn = 'host_state'; $stateChangeColumn = 'host_last_state_change'; } @@ -112,6 +104,7 @@ class Monitoring_ListController extends Controller $query = $this->backend->select()->from('hostStatus', array_merge(array( 'host_icon_image', 'host_name', + 'host_display_name', 'host_state' => $stateColumn, 'host_address', 'host_acknowledged', @@ -138,13 +131,14 @@ class Monitoring_ListController extends Controller $this->filterQuery($query); + $this->applyRestriction('monitoring/hosts/filter', $query); + $this->setupSortControl(array( - 'host_last_check' => $this->translate('Last Check'), 'host_severity' => $this->translate('Severity'), - 'host_name' => $this->translate('Hostname'), - 'host_address' => $this->translate('Address'), 'host_state' => $this->translate('Current State'), - 'host_state' => $this->translate('Hard State') + 'host_display_name' => $this->translate('Hostname'), + 'host_address' => $this->translate('Address'), + 'host_last_check' => $this->translate('Last Check') )); $this->view->hosts = $query->paginate(); @@ -171,14 +165,12 @@ class Monitoring_ListController extends Controller } // Handle soft and hard states - $stateType = $this->params->shift('stateType', 'soft'); - if ($stateType == 'hard') { + if (strtolower($this->params->shift('stateType', 'soft')) === 'hard') { $stateColumn = 'service_hard_state'; $stateChangeColumn = 'service_last_hard_state_change'; } else { $stateColumn = 'service_state'; $stateChangeColumn = 'service_last_state_change'; - $stateType = 'soft'; } $this->addTitleTab('services', $this->translate('Services')); @@ -192,6 +184,7 @@ class Monitoring_ListController extends Controller $columns = array_merge(array( 'host_name', + 'host_display_name', 'host_state', 'host_state_type', 'host_last_state_change', @@ -227,15 +220,17 @@ class Monitoring_ListController extends Controller $query = $this->backend->select()->from('serviceStatus', $columns); $this->filterQuery($query); + + $this->applyRestriction('monitoring/services/filter', $query); + $this->setupSortControl(array( - 'service_last_check' => $this->translate('Last Service Check'), - 'service_severity' => $this->translate('Severity'), + 'service_severity' => $this->translate('Service Severity'), 'service_state' => $this->translate('Current Service State'), - 'service_description' => $this->translate('Service Name'), - 'service_state_type' => $this->translate('Hard State'), + 'service_display_name' => $this->translate('Service Name'), + 'service_last_check' => $this->translate('Last Service Check'), 'host_severity' => $this->translate('Host Severity'), 'host_state' => $this->translate('Current Host State'), - 'host_name' => $this->translate('Host Name'), + 'host_display_name' => $this->translate('Hostname'), 'host_address' => $this->translate('Host Address'), 'host_last_check' => $this->translate('Last Host Check') )); @@ -295,26 +290,31 @@ class Monitoring_ListController extends Controller 'host' => 'downtime_host', 'service' => 'downtime_service', 'host_state' => 'downtime_host_state', - 'service_state' => 'downtime_service_state' - ))->order('downtime_is_in_effect', 'DESC') - ->order('downtime_scheduled_start', 'DESC'); + 'service_state' => 'downtime_service_state', + 'host_display_name', + 'service_display_name' + )); $this->filterQuery($query); $this->setupSortControl(array( - 'downtime_is_in_effect' => $this->translate('Is In Effect'), - 'downtime_host' => $this->translate('Host / Service'), - 'downtime_entry_time' => $this->translate('Entry Time'), - 'downtime_author' => $this->translate('Author'), - 'downtime_start' => $this->translate('Start Time'), - 'downtime_start' => $this->translate('End Time'), - 'downtime_scheduled_start' => $this->translate('Scheduled Start'), - 'downtime_scheduled_end' => $this->translate('Scheduled End'), - 'downtime_duration' => $this->translate('Duration'), + 'downtime_is_in_effect' => $this->translate('Is In Effect'), + 'host_display_name' => $this->translate('Host'), + 'service_display_name' => $this->translate('Service'), + 'downtime_entry_time' => $this->translate('Entry Time'), + 'downtime_author' => $this->translate('Author'), + 'downtime_start' => $this->translate('Start Time'), + 'downtime_end' => $this->translate('End Time'), + 'downtime_scheduled_start' => $this->translate('Scheduled Start'), + 'downtime_scheduled_end' => $this->translate('Scheduled End'), + 'downtime_duration' => $this->translate('Duration') )); $this->view->downtimes = $query->paginate(); - $this->view->delDowntimeForm = new DeleteDowntimeCommandForm(); + + if ($this->Auth()->hasPermission('monitoring/command/downtime/delete')) { + $this->view->delDowntimeForm = new DeleteDowntimeCommandForm(); + } } /** @@ -333,7 +333,9 @@ class Monitoring_ListController extends Controller 'notification_output', 'notification_contact', 'notification_start_time', - 'notification_state' + 'notification_state', + 'host_display_name', + 'service_display_name' )); $this->filterQuery($query); $this->view->notifications = $query->paginate(); @@ -471,20 +473,26 @@ class Monitoring_ListController extends Controller 'persistent' => 'comment_is_persistent', 'expiration' => 'comment_expiration', 'host' => 'comment_host', - 'service' => 'comment_service' + 'service' => 'comment_service', + 'host_display_name', + 'service_display_name' )); $this->filterQuery($query); $this->view->comments = $query->paginate(); $this->setupSortControl( array( - 'comment_timestamp' => $this->translate('Comment Timestamp'), - 'comment_host' => $this->translate('Host / Service'), - 'comment_type' => $this->translate('Comment Type'), - 'comment_expiration' => $this->translate('Expiration'), + 'comment_timestamp' => $this->translate('Comment Timestamp'), + 'host_display_name' => $this->translate('Host'), + 'service_display_name' => $this->translate('Service'), + 'comment_type' => $this->translate('Comment Type'), + 'comment_expiration' => $this->translate('Expiration') ) ); - $this->view->delCommentForm = new DeleteCommentCommandForm(); + + if ($this->Auth()->hasPermission('monitoring/command/comment/delete')) { + $this->view->delCommentForm = new DeleteCommentCommandForm(); + } } public function servicegroupsAction() @@ -496,6 +504,7 @@ class Monitoring_ListController extends Controller $this->setAutorefreshInterval(12); $query = $this->backend->select()->from('groupsummary', array( 'servicegroup', + 'servicegroup_alias', 'hosts_up', 'hosts_unreachable_handled', 'hosts_unreachable_unhandled', @@ -519,18 +528,20 @@ class Monitoring_ListController extends Controller 'services_critical_last_state_change_unhandled', 'services_unknown_last_state_change_unhandled', 'services_total' - )); + ))->order('services_severity')->order('servicegroup_alias'); + // 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->setupSortControl(array( - 'services_severity' => $this->translate('Severity'), - 'servicegroup' => $this->translate('Service Group Name'), - 'services_total' => $this->translate('Total Services'), - 'services_ok' => $this->translate('Services OK'), - 'services_unknown' => $this->translate('Services UNKNOWN'), - 'services_critical' => $this->translate('Services CRITICAL'), - 'services_warning' => $this->translate('Services WARNING'), - 'services_pending' => $this->translate('Services PENDING') + 'services_severity' => $this->translate('Severity'), + 'servicegroup_alias' => $this->translate('Service Group Name'), + 'services_total' => $this->translate('Total Services'), + 'services_ok' => $this->translate('Services OK'), + 'services_unknown' => $this->translate('Services UNKNOWN'), + 'services_critical' => $this->translate('Services CRITICAL'), + 'services_warning' => $this->translate('Services WARNING'), + 'services_pending' => $this->translate('Services PENDING') )); } @@ -543,6 +554,7 @@ class Monitoring_ListController extends Controller $this->setAutorefreshInterval(12); $query = $this->backend->select()->from('groupsummary', array( 'hostgroup', + 'hostgroup_alias', 'hosts_up', 'hosts_unreachable_handled', 'hosts_unreachable_unhandled', @@ -566,12 +578,14 @@ class Monitoring_ListController extends Controller 'services_critical_last_state_change_unhandled', 'services_unknown_last_state_change_unhandled', 'services_total' - )); + ))->order('services_severity')->order('hostgroup_alias'); + // 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->setupSortControl(array( 'services_severity' => $this->translate('Severity'), - 'hostgroup' => $this->translate('Host Group Name'), + 'hostgroup_alias' => $this->translate('Host Group Name'), 'services_total' => $this->translate('Total Services'), 'services_ok' => $this->translate('Services OK'), 'services_unknown' => $this->translate('Services UNKNOWN'), @@ -590,7 +604,9 @@ class Monitoring_ListController extends Controller $query = $this->backend->select()->from('eventHistory', array( 'host_name', + 'host_display_name', 'service_description', + 'service_display_name', 'object_type', 'timestamp', 'state', @@ -605,7 +621,7 @@ class Monitoring_ListController extends Controller $this->filterQuery($query); $this->setupSortControl(array( - 'timestamp' => 'Occurence' + 'timestamp' => $this->translate('Occurence') )); $this->view->history = $query->paginate(); } @@ -650,22 +666,10 @@ class Monitoring_ListController extends Controller if ($sort = $this->params->get('sort')) { $query->order($sort, $this->params->get('dir')); } - $this->applyRestrictions($query); $this->handleFormatRequest($query); return $query; } - /** - * Apply current user's `monitoring/filter' restrictions on the given data view - */ - protected function applyRestrictions($query) - { - foreach ($this->getRestrictions('monitoring/filter') as $restriction) { - // TODO: $query->applyFilter(Filter::fromQueryString()); - } - return $query; - } - protected function extraColumns() { $columns = preg_split( diff --git a/modules/monitoring/application/controllers/MultiController.php b/modules/monitoring/application/controllers/MultiController.php deleted file mode 100644 index 52d927ffb..000000000 --- a/modules/monitoring/application/controllers/MultiController.php +++ /dev/null @@ -1,282 +0,0 @@ -backend->select()->from( - 'hostStatus', - array( - 'host_name', - 'host_in_downtime', - 'host_passive_checks_enabled', - 'host_obsessing', - 'host_state', - 'host_notifications_enabled', - 'host_event_handler_enabled', - 'host_flap_detection_enabled', - 'host_active_checks_enabled', - // columns intended for filter-request - 'host_problem', - 'host_handled' - ) - )->getQuery(); - $this->applyQueryFilter($query); - $hosts = $query->fetchAll(); - - $comments = $this->backend->select()->from('comment', array( - 'comment_internal_id', - 'comment_host', - )); - $this->applyQueryFilter($comments); - $uniqueComments = array_keys($this->getUniqueValues($comments->getQuery()->fetchAll(), 'comment_internal_id')); - - // Populate view - $this->view->objects = $this->view->hosts = $hosts; - $this->view->problems = $this->getProblems($hosts); - $this->view->comments = $uniqueComments; - $this->view->hostnames = $this->getProperties($hosts, 'host_name'); - $this->view->downtimes = $this->getDowntimes($hosts); - $this->view->errors = $errors; - $this->view->states = $this->countStates($hosts, 'host', 'host_name'); - $this->view->pie = $this->createPie( - $this->view->states, - $this->view->getHelper('MonitoringState')->getHostStateColors(), - mt('monitoring', 'Host State') - ); - - // Handle configuration changes - $this->handleConfigurationForm(array( - 'host_passive_checks_enabled' => $this->translate('Passive Checks'), - 'host_active_checks_enabled' => $this->translate('Active Checks'), - 'host_notifications_enabled' => $this->translate('Notifications'), - 'host_event_handler_enabled' => $this->translate('Event Handler'), - 'host_flap_detection_enabled' => $this->translate('Flap Detection'), - 'host_obsessing' => $this->translate('Obsessing') - )); - } - - public function serviceAction() - { - $errors = array(); - $query = $this->backend->select()->from('serviceStatus', array( - 'host_name', - 'host_state', - 'service_description', - 'service_handled', - 'service_state', - 'service_in_downtime', - 'service_passive_checks_enabled', - 'service_notifications_enabled', - 'service_event_handler_enabled', - 'service_flap_detection_enabled', - 'service_active_checks_enabled', - 'service_obsessing', - // also accept all filter-requests from ListView - 'service_problem', - 'service_severity', - 'service_last_check', - 'service_state_type', - 'host_severity', - 'host_address', - 'host_last_check' - )); - - $this->applyQueryFilter($query); - $services = $query->getQuery()->fetchAll(); - - $comments = $this->backend->select()->from('comment', array( - 'comment_internal_id', - 'comment_host', - 'comment_service' - )); - $this->applyQueryFilter($comments); - $uniqueComments = array_keys($this->getUniqueValues($comments->getQuery()->fetchAll(), 'comment_internal_id')); - - // populate the view - $this->view->objects = $this->view->services = $services; - $this->view->problems = $this->getProblems($services); - $this->view->comments = $uniqueComments; - $this->view->hostnames = $this->getProperties($services, 'host_name'); - $this->view->servicenames = $this->getProperties($services, 'service_description'); - $this->view->downtimes = $this->getDowntimes($services); - $this->view->service_states = $this->countStates($services, 'service'); - $this->view->host_states = $this->countStates($services, 'host', 'host_name'); - $this->view->service_pie = $this->createPie( - $this->view->service_states, - $this->view->getHelper('MonitoringState')->getServiceStateColors(), - mt('monitoring', 'Service State') - ); - $this->view->host_pie = $this->createPie( - $this->view->host_states, - $this->view->getHelper('MonitoringState')->getHostStateColors(), - mt('monitoring', 'Host State') - ); - $this->view->errors = $errors; - - $this->handleConfigurationForm(array( - 'service_passive_checks_enabled' => $this->translate('Passive Checks'), - 'service_active_checks_enabled' => $this->translate('Active Checks'), - 'service_notifications_enabled' => $this->translate('Notifications'), - 'service_event_handler_enabled' => $this->translate('Event Handler'), - 'service_flap_detection_enabled' => $this->translate('Flap Detection'), - 'service_obsessing' => $this->translate('Obsessing'), - )); - } - - protected function applyQueryFilter($query) - { - $params = clone $this->params; - $modifyFilter = $params->shift('modifyFilter'); - - $filter = Filter::fromQueryString((string) $params); - if ($modifyFilter) { - $this->view->filterWidget = Widget::create('filterEditor', array( - 'filter' => $filter, - 'query' => $query - )); - } - $this->view->filter = $filter; - $query->applyFilter($filter); - return $query; - } - - /** - * Create an array with all unique values as keys. - * - * @param array $values The array containing the objects - * @param $key The key to access - * - * @return array - */ - private function getUniqueValues($values, $key) - { - $unique = array(); - foreach ($values as $value) { - if (is_array($value)) { - $unique[$value[$key]] = $value[$key]; - } else { - $unique[$value->$key] = $value->$key; - } - } - return $unique; - } - - /** - * Get the numbers of problems of the given objects - * - * @param $objects The objects containing the problems - * - * @return int The problem count - */ - private function getProblems($objects) - { - $problems = 0; - foreach ($objects as $object) { - if (property_exists($object, 'host_unhandled_service_count')) { - $problems += $object->host_unhandled_service_count; - } else if ( - property_exists($object, 'service_handled') && - !$object->service_handled && - $object->service_state > 0 - ) { - $problems++; - } - } - return $problems; - } - - private function countStates($objects, $type = 'host', $unique = null) - { - $known = array(); - if ($type === 'host') { - $states = array_fill_keys($this->view->getHelper('MonitoringState')->getHostStateNames(), 0); - } else { - $states = array_fill_keys($this->view->getHelper('MonitoringState')->getServiceStateNames(), 0); - } - foreach ($objects as $object) { - if (isset($unique)) { - if (array_key_exists($object->$unique, $known)) { - continue; - } - $known[$object->$unique] = true; - } - $states[$this->view->monitoringState($object, $type)]++; - } - return $states; - } - - private function createPie($states, $colors, $title) - { - $chart = new InlinePie(array_values($states), $title, $colors); - $chart->setLabel(array_keys($states))->setHeight(100)->setWidth(100); - $chart->setTitle($title); - return $chart; - } - - - private function getComments($objects) - { - $unique = array(); - foreach ($objects as $object) { - $unique = array_merge($unique, $this->getUniqueValues($object->comments, 'comment_internal_id')); - } - return array_keys($unique); - } - - private function getProperties($objects, $property) - { - $objectnames = array(); - foreach ($objects as $object) { - $objectnames[] = $object->$property; - } - return $objectnames; - } - - private function getDowntimes($objects) - { - $downtimes = array(); - foreach ($objects as $object) - { - if ( - (property_exists($object, 'host_in_downtime') && $object->host_in_downtime) || - (property_exists($object, 'service_in_downtime') && $object->service_in_downtime) - ) { - $downtimes[] = true; - } - } - return $downtimes; - } - - - /** - * Handle the form to edit configuration flags. - * - * @param $flags array The used flags. - */ - private function handleConfigurationForm(array $flags) - { - $this->view->form = $form = new MultiCommandFlagForm($flags); - $this->view->formElements = $form->buildCheckboxes(); - $form->setRequest($this->_request); - if ($form->isSubmittedAndValid()) { - // TODO: Handle commands - $changed = $form->getChangedValues(); - } - if ($this->_request->isPost() === false) { - $this->view->form->initFromItems($this->view->objects); - } - } -} diff --git a/modules/monitoring/application/controllers/ProcessController.php b/modules/monitoring/application/controllers/ProcessController.php index 62334d7e8..bb5a4e5c2 100644 --- a/modules/monitoring/application/controllers/ProcessController.php +++ b/modules/monitoring/application/controllers/ProcessController.php @@ -64,8 +64,9 @@ class Monitoring_ProcessController extends Controller 'process_performance_data' ) ) - ->getQuery() - ->fetchRow(); + ->getQuery(); + $this->handleFormatRequest($programStatus); + $programStatus = $programStatus->fetchRow(); if ($programStatus === false) { return $this->render('not-running', true, null); } diff --git a/modules/monitoring/application/controllers/ServiceController.php b/modules/monitoring/application/controllers/ServiceController.php index 06417cc6e..4e4e67402 100644 --- a/modules/monitoring/application/controllers/ServiceController.php +++ b/modules/monitoring/application/controllers/ServiceController.php @@ -26,20 +26,15 @@ class Monitoring_ServiceController extends MonitoredObjectController public function init() { $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')); } $this->object = $service; $this->createTabs(); - } - - /** - * Show a service - */ - public function showAction() - { $this->getTabs()->activate('service'); - parent::showAction(); } /** @@ -47,6 +42,8 @@ class Monitoring_ServiceController extends MonitoredObjectController */ public function acknowledgeProblemAction() { + $this->assertPermission('monitoring/command/acknowledge-problem'); + $this->view->title = $this->translate('Acknowledge Service Problem'); $this->handleCommandForm(new AcknowledgeProblemCommandForm()); } @@ -56,6 +53,8 @@ class Monitoring_ServiceController extends MonitoredObjectController */ public function addCommentAction() { + $this->assertPermission('monitoring/command/comment/add'); + $this->view->title = $this->translate('Add Service Comment'); $this->handleCommandForm(new AddCommentCommandForm()); } @@ -65,6 +64,8 @@ class Monitoring_ServiceController extends MonitoredObjectController */ public function rescheduleCheckAction() { + $this->assertPermission('monitoring/command/schedule-check'); + $this->view->title = $this->translate('Reschedule Service Check'); $this->handleCommandForm(new ScheduleServiceCheckCommandForm()); } @@ -74,6 +75,8 @@ class Monitoring_ServiceController extends MonitoredObjectController */ public function scheduleDowntimeAction() { + $this->assertPermission('monitoring/command/downtime/schedule'); + $this->view->title = $this->translate('Schedule Service Downtime'); $this->handleCommandForm(new ScheduleServiceDowntimeCommandForm()); } @@ -83,6 +86,8 @@ class Monitoring_ServiceController extends MonitoredObjectController */ public function processCheckResultAction() { + $this->assertPermission('monitoring/command/process-check-result'); + $this->view->title = $this->translate('Submit Passive Service Check Result'); $this->handleCommandForm(new ProcessCheckResultCommandForm()); } diff --git a/modules/monitoring/application/controllers/ServicesController.php b/modules/monitoring/application/controllers/ServicesController.php index cdf86f460..dc7feb2da 100644 --- a/modules/monitoring/application/controllers/ServicesController.php +++ b/modules/monitoring/application/controllers/ServicesController.php @@ -74,8 +74,10 @@ class Monitoring_ServicesController extends Controller 'service_obsessing'*/ )); $unhandledObjects = array(); + $unhandledFilterExpressions = array(); $acknowledgedObjects = array(); $objectsInDowntime = array(); + $downtimeFilterExpressions = array(); $serviceStates = array( Service::getStateText(Service::STATE_OK) => 0, Service::getStateText(Service::STATE_WARNING) => 0, @@ -94,12 +96,20 @@ class Monitoring_ServicesController extends Controller /** @var Service $service */ if ((bool) $service->problem === true && (bool) $service->handled === false) { $unhandledObjects[] = $service; + $unhandledFilterExpressions[] = Filter::matchAll( + Filter::where('host', $service->getHost()->getName()), + Filter::where('service', $service->getName()) + ); } if ((bool) $service->acknowledged === true) { $acknowledgedObjects[] = $service; } if ((bool) $service->in_downtime === true) { $objectsInDowntime[] = $service; + $downtimeFilterExpressions[] = Filter::matchAll( + Filter::where('downtime_host', $service->getHost()->getName()), + Filter::where('downtime_service', $service->getName()) + ); } ++$serviceStates[$service::getStateText($service->state)]; if (! isset($knownHostStates[$service->getHost()->getName()])) { @@ -125,16 +135,15 @@ class Monitoring_ServicesController extends Controller $this->view->serviceStates = $serviceStates; $this->view->objects = $this->serviceList; $this->view->unhandledObjects = $unhandledObjects; - $this->view->acknowledgeUnhandledLink = Url::fromRequest() - ->setPath('monitoring/services/acknowledge-problem') - ->addParams(array('service_problem' => 1, 'service_handled' => 0)); - $this->view->downtimeUnhandledLink = Url::fromRequest() - ->setPath('monitoring/services/schedule-downtime') - ->addParams(array('service_problem' => 1, 'service_handled' => 0)); + $unhandledFilterQueryString = Filter::matchAny($unhandledFilterExpressions)->toQueryString(); + $this->view->acknowledgeUnhandledLink = Url::fromPath('monitoring/services/acknowledge-problem') + ->setQueryString($unhandledFilterQueryString); + $this->view->downtimeUnhandledLink = Url::fromPath('monitoring/services/schedule-downtime') + ->setQueryString($unhandledFilterQueryString); $this->view->acknowledgedObjects = $acknowledgedObjects; $this->view->objectsInDowntime = $objectsInDowntime; - $this->view->inDowntimeLink = Url::fromRequest() - ->setPath('monitoring/list/downtimes'); + $this->view->inDowntimeLink = Url::fromPath('monitoring/list/downtimes') + ->setQueryString(Filter::matchAny($downtimeFilterExpressions)->toQueryString()); $this->view->havingCommentsLink = Url::fromRequest() ->setPath('monitoring/list/comments'); $this->view->serviceStatesPieChart = $this->createPieChart( @@ -153,10 +162,9 @@ class Monitoring_ServicesController extends Controller { $chart = new InlinePie(array_values($states), $title, $colors); return $chart - ->setLabel(array_map('strtoupper', array_keys($states))) - ->setHeight(100) - ->setWidth(100) - ->setTitle($title); + ->setSize(75) + ->setTitle('') + ->setSparklineClass('sparkline-multi'); } /** diff --git a/modules/monitoring/application/controllers/ShowController.php b/modules/monitoring/application/controllers/ShowController.php index efec6665a..0b7a2f897 100644 --- a/modules/monitoring/application/controllers/ShowController.php +++ b/modules/monitoring/application/controllers/ShowController.php @@ -73,9 +73,8 @@ class Monitoring_ShowController extends Controller public function historyAction() { $this->getTabs()->activate('history'); - //$this->view->object->populate(); $this->view->object->fetchEventHistory(); - $this->view->history = $this->view->object->eventhistory->paginate($this->params->get('limit', 50)); + $this->view->history = $this->view->object->eventhistory->getQuery()->paginate($this->params->get('limit', 50)); $this->handleFormatRequest($this->view->object->eventhistory); $this->fetchHostStats(); } @@ -166,8 +165,10 @@ class Monitoring_ShowController extends Controller 'notification_output', 'notification_contact', 'notification_start_time', - 'notification_state' - ))->order('notification_start_time'); + 'notification_state', + 'host_display_name', + 'service_display_name' + )); $notifications->where('contact_object_id', $contact->contact_object_id); diff --git a/modules/monitoring/application/forms/Command/Instance/DisableNotificationsExpireCommandForm.php b/modules/monitoring/application/forms/Command/Instance/DisableNotificationsExpireCommandForm.php index 0e64a4b03..21d926b58 100644 --- a/modules/monitoring/application/forms/Command/Instance/DisableNotificationsExpireCommandForm.php +++ b/modules/monitoring/application/forms/Command/Instance/DisableNotificationsExpireCommandForm.php @@ -21,7 +21,7 @@ class DisableNotificationsExpireCommandForm extends CommandForm */ public function init() { - $this->setSubmitLabel(mt('monitoring', 'Disable Notifications')); + $this->setSubmitLabel($this->translate('Disable Notifications')); } /** @@ -30,8 +30,7 @@ class DisableNotificationsExpireCommandForm extends CommandForm */ public function getHelp() { - return mt( - 'monitoring', + return $this->translate( 'This command is used to disable host and service notifications for a specific time.' ); } @@ -49,8 +48,8 @@ class DisableNotificationsExpireCommandForm extends CommandForm 'expire_time', array( 'required' => true, - 'label' => mt('monitoring', 'Expire Time'), - 'description' => mt('monitoring', 'Set the expire time.'), + 'label' => $this->translate('Expire Time'), + 'description' => $this->translate('Set the expire time.'), 'value' => $expireTime ) ); @@ -67,7 +66,7 @@ class DisableNotificationsExpireCommandForm extends CommandForm $disableNotifications ->setExpireTime($this->getElement('expire_time')->getValue()->getTimestamp()); $this->getTransport($this->request)->send($disableNotifications); - Notification::success(mt('monitoring', 'Disabling host and service notifications..')); + Notification::success($this->translate('Disabling host and service notifications..')); return true; } } diff --git a/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php b/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php index 291619b2f..469c1b6eb 100644 --- a/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php +++ b/modules/monitoring/application/forms/Command/Instance/ToggleInstanceFeaturesCommandForm.php @@ -61,13 +61,13 @@ class ToggleInstanceFeaturesCommandForm extends CommandForm if ((bool) $this->status->notifications_enabled) { $notificationDescription = sprintf( '%s', - mt('monitoring', 'Disable notifications for a specific time on a program-wide basis'), + $this->translate('Disable notifications for a specific time on a program-wide basis'), $this->getView()->href('monitoring/process/disable-notifications'), - mt('monitoring', 'Disable temporarily') + $this->translate('Disable temporarily') ); } elseif ($this->status->disable_notif_expire_time) { $notificationDescription = sprintf( - mt('monitoring', 'Notifications will be re-enabled in %s'), + $this->translate('Notifications will be re-enabled in %s'), $this->getView()->timeUntil($this->status->disable_notif_expire_time) ); } else { @@ -78,7 +78,7 @@ class ToggleInstanceFeaturesCommandForm extends CommandForm 'checkbox', ToggleInstanceFeatureCommand::FEATURE_ACTIVE_HOST_CHECKS, array( - 'label' => mt('monitoring', 'Active Host Checks Being Executed'), + 'label' => $this->translate('Active Host Checks Being Executed'), 'autosubmit' => true ) ), @@ -86,7 +86,7 @@ class ToggleInstanceFeaturesCommandForm extends CommandForm 'checkbox', ToggleInstanceFeatureCommand::FEATURE_ACTIVE_SERVICE_CHECKS, array( - 'label' => mt('monitoring', 'Active Service Checks Being Executed'), + 'label' => $this->translate('Active Service Checks Being Executed'), 'autosubmit' => true ) ), @@ -94,7 +94,7 @@ class ToggleInstanceFeaturesCommandForm extends CommandForm 'checkbox', ToggleInstanceFeatureCommand::FEATURE_EVENT_HANDLERS, array( - 'label' => mt('monitoring', 'Event Handlers Enabled'), + 'label' => $this->translate('Event Handlers Enabled'), 'autosubmit' => true ) ), @@ -102,7 +102,7 @@ class ToggleInstanceFeaturesCommandForm extends CommandForm 'checkbox', ToggleInstanceFeatureCommand::FEATURE_FLAP_DETECTION, array( - 'label' => mt('monitoring', 'Flap Detection Enabled'), + 'label' => $this->translate('Flap Detection Enabled'), 'autosubmit' => true ) ), @@ -110,7 +110,7 @@ class ToggleInstanceFeaturesCommandForm extends CommandForm 'checkbox', ToggleInstanceFeatureCommand::FEATURE_NOTIFICATIONS, array( - 'label' => mt('monitoring', 'Notifications Enabled'), + 'label' => $this->translate('Notifications Enabled'), 'autosubmit' => true, 'description' => $notificationDescription, 'decorators' => array( @@ -129,7 +129,7 @@ class ToggleInstanceFeaturesCommandForm extends CommandForm 'checkbox', ToggleInstanceFeatureCommand::FEATURE_HOST_OBSESSING, array( - 'label' => mt('monitoring', 'Obsessing Over Hosts'), + 'label' => $this->translate('Obsessing Over Hosts'), 'autosubmit' => true ) ), @@ -137,7 +137,7 @@ class ToggleInstanceFeaturesCommandForm extends CommandForm 'checkbox', ToggleInstanceFeatureCommand::FEATURE_SERVICE_OBSESSING, array( - 'label' => mt('monitoring', 'Obsessing Over Services'), + 'label' => $this->translate('Obsessing Over Services'), 'autosubmit' => true ) ), @@ -145,7 +145,7 @@ class ToggleInstanceFeaturesCommandForm extends CommandForm 'checkbox', ToggleInstanceFeatureCommand::FEATURE_PASSIVE_HOST_CHECKS, array( - 'label' => mt('monitoring', 'Passive Host Checks Being Accepted'), + 'label' => $this->translate('Passive Host Checks Being Accepted'), 'autosubmit' => true ) ), @@ -153,7 +153,7 @@ class ToggleInstanceFeaturesCommandForm extends CommandForm 'checkbox', ToggleInstanceFeatureCommand::FEATURE_PASSIVE_SERVICE_CHECKS, array( - 'label' => mt('monitoring', 'Passive Service Checks Being Accepted'), + 'label' => $this->translate('Passive Service Checks Being Accepted'), 'autosubmit' => true ) ), @@ -161,7 +161,7 @@ class ToggleInstanceFeaturesCommandForm extends CommandForm 'checkbox', ToggleInstanceFeatureCommand::FEATURE_PERFORMANCE_DATA, array( - 'label' => mt('monitoring', 'Performance Data Being Processed'), + 'label' => $this->translate('Performance Data Being Processed'), 'autosubmit' => true ) ) @@ -198,7 +198,7 @@ class ToggleInstanceFeaturesCommandForm extends CommandForm ->setEnabled($enabled); $this->getTransport($this->request)->send($toggleFeature); } - Notification::success(mt('monitoring', 'Toggling feature..')); + Notification::success($this->translate('Toggling feature..')); return true; } } diff --git a/modules/monitoring/application/forms/Command/Object/AcknowledgeProblemCommandForm.php b/modules/monitoring/application/forms/Command/Object/AcknowledgeProblemCommandForm.php index 25ac76c25..df3731837 100644 --- a/modules/monitoring/application/forms/Command/Object/AcknowledgeProblemCommandForm.php +++ b/modules/monitoring/application/forms/Command/Object/AcknowledgeProblemCommandForm.php @@ -31,8 +31,7 @@ class AcknowledgeProblemCommandForm extends ObjectsCommandForm */ public function getHelp() { - return mt( - 'monitoring', + return $this->translate( 'This command is used to acknowledge host or service problems. When a problem is acknowledged,' . ' future notifications about problems are temporarily disabled until the host or service' . ' recovers.' @@ -51,9 +50,8 @@ class AcknowledgeProblemCommandForm extends ObjectsCommandForm 'comment', array( 'required' => true, - 'label' => mt('monitoring', 'Comment'), - 'description' => mt( - 'monitoring', + 'label' => $this->translate('Comment'), + 'description' => $this->translate( 'If you work with other administrators, you may find it useful to share information about the' . ' the host or service that is having problems. Make sure you enter a brief description of' . ' what you are doing.' @@ -64,9 +62,8 @@ class AcknowledgeProblemCommandForm extends ObjectsCommandForm 'checkbox', 'persistent', array( - 'label' => mt('monitoring', 'Persistent Comment'), - 'description' => mt( - 'monitoring', + 'label' => $this->translate('Persistent Comment'), + 'description' => $this->translate( 'If you would like the comment to remain even when the acknowledgement is removed, check this' . ' option.' ) @@ -76,8 +73,10 @@ class AcknowledgeProblemCommandForm extends ObjectsCommandForm 'checkbox', 'expire', array( - 'label' => mt('monitoring', 'Use Expire Time'), - 'description' => mt('monitoring', 'If the acknowledgement should expire, check this option.'), + 'label' => $this->translate('Use Expire Time'), + 'description' => $this->translate( + 'If the acknowledgement should expire, check this option.' + ), 'autosubmit' => true ) ) @@ -89,10 +88,9 @@ class AcknowledgeProblemCommandForm extends ObjectsCommandForm 'dateTimePicker', 'expire_time', array( - 'label' => mt('monitoring', 'Expire Time'), + 'label' => $this->translate('Expire Time'), 'value' => $expireTime, - 'description' => mt( - 'monitoring', + 'description' => $this->translate( 'Enter the expire date and time for this acknowledgement here. Icinga will delete the' . ' acknowledgement after this time expired.' ) @@ -114,10 +112,9 @@ class AcknowledgeProblemCommandForm extends ObjectsCommandForm 'checkbox', 'sticky', array( - 'label' => mt('monitoring', 'Sticky Acknowledgement'), + 'label' => $this->translate('Sticky Acknowledgement'), 'value' => true, - 'description' => mt( - 'monitoring', + 'description' => $this->translate( 'If you want the acknowledgement to disable notifications until the host or service recovers,' . ' check this option.' ) @@ -127,10 +124,9 @@ class AcknowledgeProblemCommandForm extends ObjectsCommandForm 'checkbox', 'notify', array( - 'label' => mt('monitoring', 'Send Notification'), + 'label' => $this->translate('Send Notification'), 'value' => true, - 'description' => mt( - 'monitoring', + 'description' => $this->translate( 'If you do not want an acknowledgement notification to be sent out to the appropriate contacts,' . ' uncheck this option.' ) diff --git a/modules/monitoring/application/forms/Command/Object/AddCommentCommandForm.php b/modules/monitoring/application/forms/Command/Object/AddCommentCommandForm.php index f5adf6c71..e7f7e91f9 100644 --- a/modules/monitoring/application/forms/Command/Object/AddCommentCommandForm.php +++ b/modules/monitoring/application/forms/Command/Object/AddCommentCommandForm.php @@ -29,8 +29,7 @@ class AddCommentCommandForm extends ObjectsCommandForm */ public function getHelp() { - return mt( - 'monitoring', + return $this->translate( 'This command is used to add host or service comments.' ); } @@ -47,9 +46,8 @@ class AddCommentCommandForm extends ObjectsCommandForm 'comment', array( 'required' => true, - 'label' => mt('monitoring', 'Comment'), - 'description' => mt( - 'monitoring', + 'label' => $this->translate('Comment'), + 'description' => $this->translate( 'If you work with other administrators, you may find it useful to share information about the' . ' the host or service that is having problems. Make sure you enter a brief description of' . ' what you are doing.' @@ -60,10 +58,9 @@ class AddCommentCommandForm extends ObjectsCommandForm 'checkbox', 'persistent', array( - 'label' => mt('monitoring', 'Persistent'), + 'label' => $this->translate('Persistent'), 'value' => true, - 'description' => mt( - 'monitoring', + 'description' => $this->translate( 'If you uncheck this option, the comment will automatically be deleted the next time Icinga is' . ' restarted.' ) diff --git a/modules/monitoring/application/forms/Command/Object/CheckNowCommandForm.php b/modules/monitoring/application/forms/Command/Object/CheckNowCommandForm.php index 01006683f..1054aae05 100644 --- a/modules/monitoring/application/forms/Command/Object/CheckNowCommandForm.php +++ b/modules/monitoring/application/forms/Command/Object/CheckNowCommandForm.php @@ -35,8 +35,8 @@ class CheckNowCommandForm extends ObjectsCommandForm array( 'ignore' => true, 'type' => 'submit', - 'value' => mt('monitoring', 'Check now'), - 'label' => ' ' . mt('monitoring', 'Check now'), + 'value' => $this->translate('Check now'), + 'label' => ' ' . $this->translate('Check now'), 'decorators' => array('ViewHelper'), 'escape' => false, 'class' => 'link-like' diff --git a/modules/monitoring/application/forms/Command/Object/DeleteCommentCommandForm.php b/modules/monitoring/application/forms/Command/Object/DeleteCommentCommandForm.php index 3d85afcec..0f7858ad9 100644 --- a/modules/monitoring/application/forms/Command/Object/DeleteCommentCommandForm.php +++ b/modules/monitoring/application/forms/Command/Object/DeleteCommentCommandForm.php @@ -55,7 +55,7 @@ class DeleteCommentCommandForm extends ObjectsCommandForm array( 'ignore' => true, 'label' => 'X', - 'title' => mt('monitoring', 'Delete comment'), + 'title' => $this->translate('Delete comment'), 'decorators' => array('ViewHelper') ) ); @@ -80,7 +80,7 @@ class DeleteCommentCommandForm extends ObjectsCommandForm if (! empty($redirect)) { $this->setRedirectUrl($redirect); } - Notification::success(mt('monitoring', 'Deleting comment..')); + Notification::success($this->translate('Deleting comment..')); return true; } } diff --git a/modules/monitoring/application/forms/Command/Object/DeleteDowntimeCommandForm.php b/modules/monitoring/application/forms/Command/Object/DeleteDowntimeCommandForm.php index 1c7095b82..43ca52b05 100644 --- a/modules/monitoring/application/forms/Command/Object/DeleteDowntimeCommandForm.php +++ b/modules/monitoring/application/forms/Command/Object/DeleteDowntimeCommandForm.php @@ -55,7 +55,7 @@ class DeleteDowntimeCommandForm extends ObjectsCommandForm array( 'ignore' => true, 'label' => 'X', - 'title' => mt('monitoring', 'Delete downtime'), + 'title' => $this->translate('Delete downtime'), 'decorators' => array('ViewHelper') ) ); @@ -80,7 +80,7 @@ class DeleteDowntimeCommandForm extends ObjectsCommandForm if (! empty($redirect)) { $this->setRedirectUrl($redirect); } - Notification::success(mt('monitoring', 'Deleting downtime..')); + Notification::success($this->translate('Deleting downtime..')); return true; } } diff --git a/modules/monitoring/application/forms/Command/Object/ProcessCheckResultCommandForm.php b/modules/monitoring/application/forms/Command/Object/ProcessCheckResultCommandForm.php index 48ee00ab3..44e248956 100644 --- a/modules/monitoring/application/forms/Command/Object/ProcessCheckResultCommandForm.php +++ b/modules/monitoring/application/forms/Command/Object/ProcessCheckResultCommandForm.php @@ -29,8 +29,7 @@ class ProcessCheckResultCommandForm extends ObjectsCommandForm */ public function getHelp() { - return mt( - 'monitoring', + return $this->translate( 'This command is used to submit passive host or service check results.' ); } @@ -53,17 +52,17 @@ class ProcessCheckResultCommandForm extends ObjectsCommandForm 'status', array( 'required' => true, - 'label' => mt('monitoring', 'Status'), - 'description' => mt('monitoring', 'The state this check result should report'), + 'label' => $this->translate('Status'), + 'description' => $this->translate('The state this check result should report'), 'multiOptions' => $object->getType() === $object::TYPE_HOST ? array( - ProcessCheckResultCommand::HOST_UP => mt('monitoring', 'UP', 'icinga.state'), - ProcessCheckResultCommand::HOST_DOWN => mt('monitoring', 'DOWN', 'icinga.state'), - ProcessCheckResultCommand::HOST_UNREACHABLE => mt('monitoring', 'UNREACHABLE', 'icinga.state') + ProcessCheckResultCommand::HOST_UP => $this->translate('UP', 'icinga.state'), + ProcessCheckResultCommand::HOST_DOWN => $this->translate('DOWN', 'icinga.state'), + ProcessCheckResultCommand::HOST_UNREACHABLE => $this->translate('UNREACHABLE', 'icinga.state') ) : array( - ProcessCheckResultCommand::SERVICE_OK => mt('monitoring', 'OK', 'icinga.state'), - ProcessCheckResultCommand::SERVICE_WARNING => mt('monitoring', 'WARNING', 'icinga.state'), - ProcessCheckResultCommand::SERVICE_CRITICAL => mt('monitoring', 'CRITICAL', 'icinga.state'), - ProcessCheckResultCommand::SERVICE_UNKNOWN => mt('monitoring', 'UNKNOWN', 'icinga.state') + ProcessCheckResultCommand::SERVICE_OK => $this->translate('OK', 'icinga.state'), + ProcessCheckResultCommand::SERVICE_WARNING => $this->translate('WARNING', 'icinga.state'), + ProcessCheckResultCommand::SERVICE_CRITICAL => $this->translate('CRITICAL', 'icinga.state'), + ProcessCheckResultCommand::SERVICE_UNKNOWN => $this->translate('UNKNOWN', 'icinga.state') ) ) ); @@ -72,8 +71,8 @@ class ProcessCheckResultCommandForm extends ObjectsCommandForm 'output', array( 'required' => true, - 'label' => mt('monitoring', 'Output'), - 'description' => mt('monitoring', 'The plugin output of this check result') + 'label' => $this->translate('Output'), + 'description' => $this->translate('The plugin output of this check result') ) ); $this->addElement( @@ -81,9 +80,8 @@ class ProcessCheckResultCommandForm extends ObjectsCommandForm 'perfdata', array( 'allowEmpty' => true, - 'label' => mt('monitoring', 'Performance Data'), - 'description' => mt( - 'monitoring', + 'label' => $this->translate('Performance Data'), + 'description' => $this->translate( 'The performance data of this check result. Leave empty' . ' if this check result has no performance data' ) diff --git a/modules/monitoring/application/forms/Command/Object/ScheduleHostCheckCommandForm.php b/modules/monitoring/application/forms/Command/Object/ScheduleHostCheckCommandForm.php index 82a9b2e52..949ec33e1 100644 --- a/modules/monitoring/application/forms/Command/Object/ScheduleHostCheckCommandForm.php +++ b/modules/monitoring/application/forms/Command/Object/ScheduleHostCheckCommandForm.php @@ -24,9 +24,8 @@ class ScheduleHostCheckCommandForm extends ScheduleServiceCheckCommandForm 'checkbox', 'all_services', array( - 'label' => mt('monitoring', 'All Services'), - 'description' => mt( - 'monitoring', + 'label' => $this->translate('All Services'), + 'description' => $this->translate( 'Schedule check for all services on the hosts and the hosts themselves.' ) ) diff --git a/modules/monitoring/application/forms/Command/Object/ScheduleHostDowntimeCommandForm.php b/modules/monitoring/application/forms/Command/Object/ScheduleHostDowntimeCommandForm.php index beb0793ef..f84069a9a 100644 --- a/modules/monitoring/application/forms/Command/Object/ScheduleHostDowntimeCommandForm.php +++ b/modules/monitoring/application/forms/Command/Object/ScheduleHostDowntimeCommandForm.php @@ -27,9 +27,8 @@ class ScheduleHostDowntimeCommandForm extends ScheduleServiceDowntimeCommandForm 'checkbox', 'all_services', array( - 'label' => mt('monitoring', 'All Services'), - 'description' => mt( - 'monitoring', + 'label' => $this->translate('All Services'), + 'description' => $this->translate( 'Schedule downtime for all services on the hosts and the hosts themselves.' ) ) @@ -38,15 +37,14 @@ class ScheduleHostDowntimeCommandForm extends ScheduleServiceDowntimeCommandForm 'select', 'child_hosts', array( - 'label' => mt('monitoring', 'Child Hosts'), + 'label' => $this->translate('Child Hosts'), 'required' => true, 'multiOptions' => array( - 0 => mt('monitoring', 'Do nothing with child hosts'), - 1 => mt('monitoring', 'Schedule triggered downtime for all child hosts'), - 2 => mt('monitoring', 'Schedule non-triggered downtime for all child hosts') + 0 => $this->translate('Do nothing with child hosts'), + 1 => $this->translate('Schedule triggered downtime for all child hosts'), + 2 => $this->translate('Schedule non-triggered downtime for all child hosts') ), - 'description' => mt( - 'monitoring', + 'description' => $this->translate( 'Define what should be done with the child hosts of the hosts.' ) ) diff --git a/modules/monitoring/application/forms/Command/Object/ScheduleServiceCheckCommandForm.php b/modules/monitoring/application/forms/Command/Object/ScheduleServiceCheckCommandForm.php index 9e04a2254..b34472d49 100644 --- a/modules/monitoring/application/forms/Command/Object/ScheduleServiceCheckCommandForm.php +++ b/modules/monitoring/application/forms/Command/Object/ScheduleServiceCheckCommandForm.php @@ -32,8 +32,7 @@ class ScheduleServiceCheckCommandForm extends ObjectsCommandForm */ public function getHelp() { - return mt( - 'monitoring', + return $this->translate( 'This command is used to schedule the next check of hosts or services. Icinga will re-queue the' . ' hosts or services to be checked at the time you specify.' ); @@ -52,8 +51,7 @@ class ScheduleServiceCheckCommandForm extends ObjectsCommandForm 'note', 'command-info', array( - 'value' => mt( - 'monitoring', + 'value' => $this->translate( 'This command is used to schedule the next check of hosts or services. Icinga will re-queue the' . ' hosts or services to be checked at the time you specify.' ) @@ -64,8 +62,10 @@ class ScheduleServiceCheckCommandForm extends ObjectsCommandForm 'check_time', array( 'required' => true, - 'label' => mt('monitoring', 'Check Time'), - 'description' => mt('monitoring', 'Set the date and time when the check should be scheduled.'), + 'label' => $this->translate('Check Time'), + 'description' => $this->translate( + 'Set the date and time when the check should be scheduled.' + ), 'value' => $checkTime ) ), @@ -73,9 +73,8 @@ class ScheduleServiceCheckCommandForm extends ObjectsCommandForm 'checkbox', 'force_check', array( - 'label' => mt('monitoring', 'Force Check'), - 'description' => mt( - 'monitoring', + 'label' => $this->translate('Force Check'), + 'description' => $this->translate( 'If you select this option, Icinga will force a check regardless of both what time the' . ' scheduled check occurs and whether or not checks are enabled.' ) diff --git a/modules/monitoring/application/forms/Command/Object/ScheduleServiceDowntimeCommandForm.php b/modules/monitoring/application/forms/Command/Object/ScheduleServiceDowntimeCommandForm.php index 9961d4b65..4f66898f6 100644 --- a/modules/monitoring/application/forms/Command/Object/ScheduleServiceDowntimeCommandForm.php +++ b/modules/monitoring/application/forms/Command/Object/ScheduleServiceDowntimeCommandForm.php @@ -42,8 +42,7 @@ class ScheduleServiceDowntimeCommandForm extends ObjectsCommandForm */ public function getHelp() { - return mt( - 'monitoring', + return $this->translate( 'This command is used to schedule host and service downtimes. During the specified downtime,' . ' Icinga will not send notifications out about the hosts and services. When the scheduled' . ' downtime expires, Icinga will send out notifications for the hosts and services as it' @@ -67,9 +66,8 @@ class ScheduleServiceDowntimeCommandForm extends ObjectsCommandForm 'comment', array( 'required' => true, - 'label' => mt('monitoring', 'Comment'), - 'description' => mt( - 'monitoring', + 'label' => $this->translate('Comment'), + 'description' => $this->translate( 'If you work with other administrators, you may find it useful to share information about the' . ' the host or service that is having problems. Make sure you enter a brief description of' . ' what you are doing.' @@ -81,8 +79,8 @@ class ScheduleServiceDowntimeCommandForm extends ObjectsCommandForm 'start', array( 'required' => true, - 'label' => mt('monitoring', 'Start Time'), - 'description' => mt('monitoring', 'Set the start date and time for the downtime.'), + 'label' => $this->translate('Start Time'), + 'description' => $this->translate('Set the start date and time for the downtime.'), 'value' => $start ) ), @@ -91,8 +89,8 @@ class ScheduleServiceDowntimeCommandForm extends ObjectsCommandForm 'end', array( 'required' => true, - 'label' => mt('monitoring', 'End Time'), - 'description' => mt('monitoring', 'Set the end date and time for the downtime.'), + 'label' => $this->translate('End Time'), + 'description' => $this->translate('Set the end date and time for the downtime.'), 'value' => $end ) ), @@ -102,17 +100,16 @@ class ScheduleServiceDowntimeCommandForm extends ObjectsCommandForm array( 'required' => true, 'autosubmit' => true, - 'label' => mt('monitoring', 'Type'), - 'description' => mt( - 'monitoring', + 'label' => $this->translate('Type'), + 'description' => $this->translate( 'If you select the fixed option, the downtime will be in effect between the start and end' . ' times you specify whereas a flexible downtime starts when the host or service enters a' . ' problem state sometime between the start and end times you specified and lasts as long' . ' as the duration time you enter. The duration fields do not apply for fixed downtimes.' ), 'multiOptions' => array( - self::FIXED => mt('monitoring', 'Fixed'), - self::FLEXIBLE => mt('monitoring', 'Flexible') + self::FIXED => $this->translate('Fixed'), + self::FLEXIBLE => $this->translate('Flexible') ), 'validators' => array( array( @@ -141,7 +138,7 @@ class ScheduleServiceDowntimeCommandForm extends ObjectsCommandForm 'hours', array( 'required' => true, - 'label' => mt('monitoring', 'Hours'), + 'label' => $this->translate('Hours'), 'value' => 2, 'min' => -1 ) @@ -151,7 +148,7 @@ class ScheduleServiceDowntimeCommandForm extends ObjectsCommandForm 'minutes', array( 'required' => true, - 'label' => mt('monitoring', 'Minutes'), + 'label' => $this->translate('Minutes'), 'value' => 0, 'min' => -1 ) @@ -161,9 +158,8 @@ class ScheduleServiceDowntimeCommandForm extends ObjectsCommandForm array('hours', 'minutes'), 'duration', array( - 'legend' => mt('monitoring', 'Flexible Duration'), - 'description' => mt( - 'monitoring', + 'legend' => $this->translate('Flexible Duration'), + 'description' => $this->translate( 'Enter here the duration of the downtime. The downtime will be automatically deleted after this' . ' time expired.' ), diff --git a/modules/monitoring/application/forms/Command/Object/ToggleObjectFeaturesCommandForm.php b/modules/monitoring/application/forms/Command/Object/ToggleObjectFeaturesCommandForm.php index c33527895..bf0a1d8b1 100644 --- a/modules/monitoring/application/forms/Command/Object/ToggleObjectFeaturesCommandForm.php +++ b/modules/monitoring/application/forms/Command/Object/ToggleObjectFeaturesCommandForm.php @@ -33,7 +33,7 @@ class ToggleObjectFeaturesCommandForm extends ObjectsCommandForm 'checkbox', ToggleObjectFeatureCommand::FEATURE_ACTIVE_CHECKS, array( - 'label' => mt('monitoring', 'Active Checks'), + 'label' => $this->translate('Active Checks'), 'autosubmit' => true ) ), @@ -41,7 +41,7 @@ class ToggleObjectFeaturesCommandForm extends ObjectsCommandForm 'checkbox', ToggleObjectFeatureCommand::FEATURE_PASSIVE_CHECKS, array( - 'label' => mt('monitoring', 'Passive Checks'), + 'label' => $this->translate('Passive Checks'), 'autosubmit' => true ) ), @@ -49,7 +49,7 @@ class ToggleObjectFeaturesCommandForm extends ObjectsCommandForm 'checkbox', ToggleObjectFeatureCommand::FEATURE_OBSESSING, array( - 'label' => mt('monitoring', 'Obsessing'), + 'label' => $this->translate('Obsessing'), 'autosubmit' => true ) ), @@ -57,7 +57,7 @@ class ToggleObjectFeaturesCommandForm extends ObjectsCommandForm 'checkbox', ToggleObjectFeatureCommand::FEATURE_NOTIFICATIONS, array( - 'label' => mt('monitoring', 'Notifications'), + 'label' => $this->translate('Notifications'), 'autosubmit' => true ) ), @@ -65,7 +65,7 @@ class ToggleObjectFeaturesCommandForm extends ObjectsCommandForm 'checkbox', ToggleObjectFeatureCommand::FEATURE_EVENT_HANDLER, array( - 'label' => mt('monitoring', 'Event Handler'), + 'label' => $this->translate('Event Handler'), 'autosubmit' => true ) ), @@ -73,7 +73,7 @@ class ToggleObjectFeaturesCommandForm extends ObjectsCommandForm 'checkbox', ToggleObjectFeatureCommand::FEATURE_FLAP_DETECTION, array( - 'label' => mt('monitoring', 'Flap Detection'), + 'label' => $this->translate('Flap Detection'), 'autosubmit' => true ) ) @@ -95,7 +95,7 @@ class ToggleObjectFeaturesCommandForm extends ObjectsCommandForm $element = $this->getElement($feature); $element->setChecked($object->{$feature}); if ((bool) $object->{$feature . '_changed'} === true) { - $element->setDescription(mt('monitoring', 'changed')); + $element->setDescription($this->translate('changed')); } } return $this; @@ -120,7 +120,7 @@ class ToggleObjectFeaturesCommandForm extends ObjectsCommandForm } } } - Notification::success(mt('monitoring', 'Toggling feature..')); + Notification::success($this->translate('Toggling feature..')); return true; } } diff --git a/modules/monitoring/application/forms/Config/BackendConfigForm.php b/modules/monitoring/application/forms/Config/BackendConfigForm.php index 4b1aa65b6..ca45c068b 100644 --- a/modules/monitoring/application/forms/Config/BackendConfigForm.php +++ b/modules/monitoring/application/forms/Config/BackendConfigForm.php @@ -5,10 +5,10 @@ namespace Icinga\Module\Monitoring\Forms\Config; use InvalidArgumentException; -use Icinga\Web\Notification; -use Icinga\Forms\ConfigForm; use Icinga\Application\Config; use Icinga\Exception\ConfigurationError; +use Icinga\Forms\ConfigForm; +use Icinga\Web\Notification; /** * Form class for creating/modifying monitoring backends @@ -18,7 +18,7 @@ class BackendConfigForm extends ConfigForm /** * The available monitoring backend resources split by type * - * @var array + * @type array */ protected $resources; @@ -28,15 +28,15 @@ class BackendConfigForm extends ConfigForm public function init() { $this->setName('form_config_monitoring_backends'); - $this->setSubmitLabel(mt('monitoring', 'Save Changes')); + $this->setSubmitLabel($this->translate('Save Changes')); } /** * Set the resource configuration to use * - * @param Config $resources The resource configuration + * @param Config $resourceConfig The resource configuration * - * @return self + * @return $this * * @throws ConfigurationError In case there are no valid monitoring backend resources */ @@ -50,7 +50,7 @@ class BackendConfigForm extends ConfigForm } if (empty($resources)) { - throw new ConfigurationError(mt('monitoring', 'Could not find any valid monitoring backend resources')); + throw new ConfigurationError($this->translate('Could not find any valid monitoring backend resources')); } $this->resources = $resources; @@ -64,7 +64,7 @@ class BackendConfigForm extends ConfigForm * * @param array $values The values to extend the configuration with * - * @return self + * @return $this * * @throws InvalidArgumentException In case the backend does already exist */ @@ -72,9 +72,9 @@ class BackendConfigForm extends ConfigForm { $name = isset($values['name']) ? $values['name'] : ''; if (! $name) { - throw new InvalidArgumentException(mt('monitoring', 'Monitoring backend name missing')); + throw new InvalidArgumentException($this->translate('Monitoring backend name missing')); } elseif ($this->config->hasSection($name)) { - throw new InvalidArgumentException(mt('monitoring', 'Monitoring backend already exists')); + throw new InvalidArgumentException($this->translate('Monitoring backend already exists')); } unset($values['name']); @@ -95,11 +95,11 @@ class BackendConfigForm extends ConfigForm public function edit($name, array $values) { if (! $name) { - throw new InvalidArgumentException(mt('monitoring', 'Old monitoring backend name missing')); + throw new InvalidArgumentException($this->translate('Old monitoring backend name missing')); } elseif (! ($newName = isset($values['name']) ? $values['name'] : '')) { - throw new InvalidArgumentException(mt('monitoring', 'New monitoring backend name missing')); + throw new InvalidArgumentException($this->translate('New monitoring backend name missing')); } elseif (! $this->config->hasSection($name)) { - throw new InvalidArgumentException(mt('monitoring', 'Unknown monitoring backend provided')); + throw new InvalidArgumentException($this->translate('Unknown monitoring backend provided')); } unset($values['name']); @@ -119,9 +119,9 @@ class BackendConfigForm extends ConfigForm public function remove($name) { if (! $name) { - throw new InvalidArgumentException(mt('monitoring', 'Monitoring backend name missing')); + throw new InvalidArgumentException($this->translate('Monitoring backend name missing')); } elseif (! $this->config->hasSection($name)) { - throw new InvalidArgumentException(mt('monitoring', 'Unknown monitoring backend provided')); + throw new InvalidArgumentException($this->translate('Unknown monitoring backend provided')); } $backendConfig = $this->config->getSection($name); @@ -131,23 +131,21 @@ class BackendConfigForm extends ConfigForm /** * Add or edit a monitoring backend and save the configuration - * - * @see Form::onSuccess() */ public function onSuccess() { $monitoringBackend = $this->request->getQuery('backend'); try { - if ($monitoringBackend === null) { // create new backend + if ($monitoringBackend === null) { // Create new backend $this->add($this->getValues()); - $message = mt('monitoring', 'Monitoring backend "%s" has been successfully created'); - } else { // edit existing backend + $message = $this->translate('Monitoring backend "%s" has been successfully created'); + } else { // Edit existing backend $this->edit($monitoringBackend, $this->getValues()); - $message = mt('monitoring', 'Monitoring backend "%s" has been successfully changed'); + $message = $this->translate('Monitoring backend "%s" has been successfully changed'); } } catch (InvalidArgumentException $e) { Notification::error($e->getMessage()); - return; + return null; } if ($this->save()) { @@ -160,18 +158,16 @@ class BackendConfigForm extends ConfigForm /** * Populate the form in case a monitoring backend is being edited * - * @see Form::onRequest() - * - * @throws ConfigurationError In case the backend name is missing in the request or is invalid + * @throws ConfigurationError In case the backend name is missing in the request or is invalid */ public function onRequest() { $monitoringBackend = $this->request->getQuery('backend'); if ($monitoringBackend !== null) { if ($monitoringBackend === '') { - throw new ConfigurationError(mt('monitoring', 'Monitoring backend name missing')); + throw new ConfigurationError($this->translate('Monitoring backend name missing')); } elseif (! $this->config->hasSection($monitoringBackend)) { - throw new ConfigurationError(mt('monitoring', 'Unknown monitoring backend provided')); + throw new ConfigurationError($this->translate('Unknown monitoring backend provided')); } $backendConfig = $this->config->getSection($monitoringBackend)->toArray(); @@ -181,7 +177,8 @@ class BackendConfigForm extends ConfigForm } /** - * @see Form::createElements() + * (non-PHPDoc) + * @see Form::createElements() For the method documentation. */ public function createElements(array $formData) { @@ -200,7 +197,7 @@ class BackendConfigForm extends ConfigForm 'disabled', array( 'required' => true, - 'label' => mt('monitoring', 'Disable This Backend') + 'label' => $this->translate('Disable This Backend') ) ); $this->addElement( @@ -208,8 +205,8 @@ class BackendConfigForm extends ConfigForm 'name', array( 'required' => true, - 'label' => mt('monitoring', 'Backend Name'), - 'description' => mt('monitoring', 'The identifier of this backend') + 'label' => $this->translate('Backend Name'), + 'description' => $this->translate('The identifier of this backend') ) ); $this->addElement( @@ -218,8 +215,8 @@ class BackendConfigForm extends ConfigForm array( 'required' => true, 'autosubmit' => true, - 'label' => mt('monitoring', 'Backend Type'), - 'description' => mt('monitoring', 'The data source used for retrieving monitoring information'), + 'label' => $this->translate('Backend Type'), + 'description' => $this->translate('The data source used for retrieving monitoring information'), 'multiOptions' => $resourceTypes, 'value' => $resourceType ) @@ -230,8 +227,8 @@ class BackendConfigForm extends ConfigForm 'resource', array( 'required' => true, - 'label' => mt('monitoring', 'Resource'), - 'description' => mt('monitoring', 'The resource to use'), + 'label' => $this->translate('Resource'), + 'description' => $this->translate('The resource to use'), 'multiOptions' => $this->resources[$resourceType], 'autosubmit' => true ) @@ -253,8 +250,8 @@ class BackendConfigForm extends ConfigForm array( 'value' => sprintf( '%s', - $this->getView()->href('/icingaweb/config/editresource', array('resource' => $resourceName)), - mt('monitoring', 'Show resource configuration') + $this->getView()->url('config/editresource', array('resource' => $resourceName)), + $this->translate('Show resource configuration') ), 'escape' => false ) diff --git a/modules/monitoring/application/forms/Config/Instance/LocalInstanceForm.php b/modules/monitoring/application/forms/Config/Instance/LocalInstanceForm.php index daabe7e02..405bac144 100644 --- a/modules/monitoring/application/forms/Config/Instance/LocalInstanceForm.php +++ b/modules/monitoring/application/forms/Config/Instance/LocalInstanceForm.php @@ -28,9 +28,9 @@ class LocalInstanceForm extends Form 'path', array( 'required' => true, - 'label' => mt('monitoring', 'Command File'), + 'label' => $this->translate('Command File'), 'value' => '/var/run/icinga2/cmd/icinga2.cmd', - 'description' => mt('monitoring', 'Path to the local Icinga command file') + 'description' => $this->translate('Path to the local Icinga command file') ) ); return $this; diff --git a/modules/monitoring/application/forms/Config/Instance/RemoteInstanceForm.php b/modules/monitoring/application/forms/Config/Instance/RemoteInstanceForm.php index 7c55f655a..47b2a0316 100644 --- a/modules/monitoring/application/forms/Config/Instance/RemoteInstanceForm.php +++ b/modules/monitoring/application/forms/Config/Instance/RemoteInstanceForm.php @@ -29,8 +29,8 @@ class RemoteInstanceForm extends Form 'host', array( 'required' => true, - 'label' => mt('monitoring', 'Host'), - 'description' => mt('monitoring', + 'label' => $this->translate('Host'), + 'description' => $this->translate( 'Hostname or address of the remote Icinga instance' ) ) @@ -40,8 +40,8 @@ class RemoteInstanceForm extends Form 'port', array( 'required' => true, - 'label' => mt('monitoring', 'Port'), - 'description' => mt('monitoring', 'SSH port to connect to on the remote Icinga instance'), + 'label' => $this->translate('Port'), + 'description' => $this->translate('SSH port to connect to on the remote Icinga instance'), 'value' => 22 ) ), @@ -50,8 +50,8 @@ class RemoteInstanceForm extends Form 'user', array( 'required' => true, - 'label' => mt('monitoring', 'User'), - 'description' => mt('monitoring', + 'label' => $this->translate('User'), + 'description' => $this->translate( 'User to log in as on the remote Icinga instance. Please note that key-based SSH login must be' . ' possible for this user' ) @@ -62,9 +62,9 @@ class RemoteInstanceForm extends Form 'path', array( 'required' => true, - 'label' => mt('monitoring', 'Command File'), + 'label' => $this->translate('Command File'), 'value' => '/var/run/icinga2/cmd/icinga2.cmd', - 'description' => mt('monitoring', 'Path to the Icinga command file on the remote Icinga instance') + 'description' => $this->translate('Path to the Icinga command file on the remote Icinga instance') ) ) )); diff --git a/modules/monitoring/application/forms/Config/InstanceConfigForm.php b/modules/monitoring/application/forms/Config/InstanceConfigForm.php index b89e48c0a..5618f27ee 100644 --- a/modules/monitoring/application/forms/Config/InstanceConfigForm.php +++ b/modules/monitoring/application/forms/Config/InstanceConfigForm.php @@ -25,7 +25,7 @@ class InstanceConfigForm extends ConfigForm public function init() { $this->setName('form_config_monitoring_instance'); - $this->setSubmitLabel(mt('monitoring', 'Save Changes')); + $this->setSubmitLabel($this->translate('Save Changes')); } /** @@ -48,7 +48,7 @@ class InstanceConfigForm extends ConfigForm break; default: throw new InvalidArgumentException( - sprintf(mt('monitoring', 'Invalid instance type "%s" given'), $type) + sprintf($this->translate('Invalid instance type "%s" given'), $type) ); } return $form; @@ -69,10 +69,10 @@ class InstanceConfigForm extends ConfigForm { $name = isset($values['name']) ? $values['name'] : ''; if (! $name) { - throw new InvalidArgumentException(mt('monitoring', 'Instance name missing')); + throw new InvalidArgumentException($this->translate('Instance name missing')); } if ($this->config->hasSection($name)) { - throw new InvalidArgumentException(mt('monitoring', 'Instance already exists')); + throw new InvalidArgumentException($this->translate('Instance already exists')); } unset($values['name']); @@ -93,11 +93,11 @@ class InstanceConfigForm extends ConfigForm public function edit($name, array $values) { if (! $name) { - throw new InvalidArgumentException(mt('monitoring', 'Old instance name missing')); + throw new InvalidArgumentException($this->translate('Old instance name missing')); } elseif (! ($newName = isset($values['name']) ? $values['name'] : '')) { - throw new InvalidArgumentException(mt('monitoring', 'New instance name missing')); + throw new InvalidArgumentException($this->translate('New instance name missing')); } elseif (! $this->config->hasSection($name)) { - throw new InvalidArgumentException(mt('monitoring', 'Unknown instance name provided')); + throw new InvalidArgumentException($this->translate('Unknown instance name provided')); } unset($values['name']); @@ -117,9 +117,9 @@ class InstanceConfigForm extends ConfigForm public function remove($name) { if (! $name) { - throw new InvalidArgumentException(mt('monitoring', 'Instance name missing')); + throw new InvalidArgumentException($this->translate('Instance name missing')); } elseif (! $this->config->hasSection($name)) { - throw new InvalidArgumentException(mt('monitoring', 'Unknown instance name provided')); + throw new InvalidArgumentException($this->translate('Unknown instance name provided')); } $instanceConfig = $this->config->getSection($name); @@ -136,10 +136,10 @@ class InstanceConfigForm extends ConfigForm $instanceName = $this->request->getQuery('instance'); if ($instanceName !== null) { if (! $instanceName) { - throw new ConfigurationError(mt('monitoring', 'Instance name missing')); + throw new ConfigurationError($this->translate('Instance name missing')); } if (! $this->config->hasSection($instanceName)) { - throw new ConfigurationError(mt('monitoring', 'Unknown instance name given')); + throw new ConfigurationError($this->translate('Unknown instance name given')); } $instanceConfig = $this->config->getSection($instanceName)->toArray(); @@ -158,10 +158,10 @@ class InstanceConfigForm extends ConfigForm try { if ($instanceName === null) { // create new instance $this->add($this->getValues()); - $message = mt('monitoring', 'Instance "%s" created successfully.'); + $message = $this->translate('Instance "%s" created successfully.'); } else { // edit existing instance $this->edit($instanceName, $this->getValues()); - $message = mt('monitoring', 'Instance "%s" edited successfully.'); + $message = $this->translate('Instance "%s" edited successfully.'); } } catch (InvalidArgumentException $e) { Notification::error($e->getMessage()); @@ -189,7 +189,7 @@ class InstanceConfigForm extends ConfigForm 'name', array( 'required' => true, - 'label' => mt('monitoring', 'Instance Name') + 'label' => $this->translate('Instance Name') ) ), array( @@ -198,10 +198,10 @@ class InstanceConfigForm extends ConfigForm array( 'required' => true, 'autosubmit' => true, - 'label' => mt('monitoring', 'Instance Type'), + 'label' => $this->translate('Instance Type'), 'multiOptions' => array( - LocalCommandFile::TRANSPORT => mt('monitoring', 'Local Command File'), - RemoteCommandFile::TRANSPORT => mt('monitoring', 'Remote Command File') + LocalCommandFile::TRANSPORT => $this->translate('Local Command File'), + RemoteCommandFile::TRANSPORT => $this->translate('Remote Command File') ), 'value' => $instanceType ) diff --git a/modules/monitoring/application/forms/Config/SecurityConfigForm.php b/modules/monitoring/application/forms/Config/SecurityConfigForm.php index 40c0b7b8c..b202f5938 100644 --- a/modules/monitoring/application/forms/Config/SecurityConfigForm.php +++ b/modules/monitoring/application/forms/Config/SecurityConfigForm.php @@ -18,7 +18,7 @@ class SecurityConfigForm extends ConfigForm public function init() { $this->setName('form_config_monitoring_security'); - $this->setSubmitLabel(mt('monitoring', 'Save Changes')); + $this->setSubmitLabel($this->translate('Save Changes')); } /** @@ -29,7 +29,7 @@ class SecurityConfigForm extends ConfigForm $this->config->setSection('security', $this->getValues()); if ($this->save()) { - Notification::success(mt('monitoring', 'New security configuration has successfully been stored')); + Notification::success($this->translate('New security configuration has successfully been stored')); } else { return false; } @@ -54,8 +54,8 @@ class SecurityConfigForm extends ConfigForm array( 'allowEmpty' => true, 'value' => '*pw*,*pass*,community', - 'label' => mt('monitoring', 'Protected Custom Variables'), - 'description' => mt('monitoring', + 'label' => $this->translate('Protected Custom Variables'), + 'description' => $this->translate( 'Comma separated case insensitive list of protected custom variables.' . ' Use * as a placeholder for zero or more wildcard characters.' . ' Existance of those custom variables will be shown, but their values will be masked.' diff --git a/modules/monitoring/application/forms/EventOverviewForm.php b/modules/monitoring/application/forms/EventOverviewForm.php index 25d268f76..dc697b940 100644 --- a/modules/monitoring/application/forms/EventOverviewForm.php +++ b/modules/monitoring/application/forms/EventOverviewForm.php @@ -44,7 +44,7 @@ class EventOverviewForm extends Form 'checkbox', 'statechange', array( - 'label' => t('State Changes'), + 'label' => $this->translate('State Changes'), 'class' => 'autosubmit', 'decorators' => $decorators, 'value' => strpos($url, $this->stateChangeFilter()->toQueryString()) === false ? 0 : 1 @@ -54,7 +54,7 @@ class EventOverviewForm extends Form 'checkbox', 'downtime', array( - 'label' => t('Downtimes'), + 'label' => $this->translate('Downtimes'), 'class' => 'autosubmit', 'decorators' => $decorators, 'value' => strpos($url, $this->downtimeFilter()->toQueryString()) === false ? 0 : 1 @@ -64,7 +64,7 @@ class EventOverviewForm extends Form 'checkbox', 'comment', array( - 'label' => t('Comments'), + 'label' => $this->translate('Comments'), 'class' => 'autosubmit', 'decorators' => $decorators, 'value' => strpos($url, $this->commentFilter()->toQueryString()) === false ? 0 : 1 @@ -74,7 +74,7 @@ class EventOverviewForm extends Form 'checkbox', 'notification', array( - 'label' => t('Notifications'), + 'label' => $this->translate('Notifications'), 'class' => 'autosubmit', 'decorators' => $decorators, 'value' => strpos($url, $this->notificationFilter()->toQueryString()) === false ? 0 : 1 @@ -84,7 +84,7 @@ class EventOverviewForm extends Form 'checkbox', 'flapping', array( - 'label' => t('Flapping'), + 'label' => $this->translate('Flapping'), 'class' => 'autosubmit', 'decorators' => $decorators, 'value' => strpos($url, $this->flappingFilter()->toQueryString()) === false ? 0 : 1 diff --git a/modules/monitoring/application/forms/Setup/BackendPage.php b/modules/monitoring/application/forms/Setup/BackendPage.php index 1f6ef6894..b5ab2ffd6 100644 --- a/modules/monitoring/application/forms/Setup/BackendPage.php +++ b/modules/monitoring/application/forms/Setup/BackendPage.php @@ -20,7 +20,7 @@ class BackendPage extends Form 'note', 'title', array( - 'value' => mt('monitoring', 'Monitoring Backend', 'setup.page.title'), + 'value' => $this->translate('Monitoring Backend', 'setup.page.title'), 'decorators' => array( 'ViewHelper', array('HtmlTag', array('tag' => 'h2')) @@ -31,8 +31,7 @@ class BackendPage extends Form 'note', 'description', array( - 'value' => mt( - 'monitoring', + 'value' => $this->translate( 'Please configure below how Icinga Web 2 should retrieve monitoring information.' ) ) @@ -44,8 +43,8 @@ class BackendPage extends Form array( 'required' => true, 'value' => 'icinga', - 'label' => mt('monitoring', 'Backend Name'), - 'description' => mt('monitoring', 'The identifier of this backend') + 'label' => $this->translate('Backend Name'), + 'description' => $this->translate('The identifier of this backend') ) ); @@ -60,8 +59,10 @@ class BackendPage extends Form 'type', array( 'required' => true, - 'label' => mt('monitoring', 'Backend Type'), - 'description' => mt('monitoring', 'The data source used for retrieving monitoring information'), + 'label' => $this->translate('Backend Type'), + 'description' => $this->translate( + 'The data source used for retrieving monitoring information' + ), 'multiOptions' => $resourceTypes ) ); diff --git a/modules/monitoring/application/forms/Setup/IdoResourcePage.php b/modules/monitoring/application/forms/Setup/IdoResourcePage.php index 189d65fea..c28b52e6b 100644 --- a/modules/monitoring/application/forms/Setup/IdoResourcePage.php +++ b/modules/monitoring/application/forms/Setup/IdoResourcePage.php @@ -28,7 +28,7 @@ class IdoResourcePage extends Form 'note', 'title', array( - 'value' => mt('monitoring', 'Monitoring IDO Resource', 'setup.page.title'), + 'value' => $this->translate('Monitoring IDO Resource', 'setup.page.title'), 'decorators' => array( 'ViewHelper', array('HtmlTag', array('tag' => 'h2')) @@ -39,8 +39,7 @@ class IdoResourcePage extends Form 'note', 'description', array( - 'value' => mt( - 'monitoring', + 'value' => $this->translate( 'Please fill out the connection details below to access' . ' the IDO database of your monitoring environment.' ) @@ -91,8 +90,10 @@ class IdoResourcePage extends Form 'skip_validation', array( 'required' => true, - 'label' => t('Skip Validation'), - 'description' => t('Check this to not to validate connectivity with the given database server') + 'label' => $this->translate('Skip Validation'), + 'description' => $this->translate( + 'Check this to not to validate connectivity with the given database server' + ) ) ); } diff --git a/modules/monitoring/application/forms/Setup/InstancePage.php b/modules/monitoring/application/forms/Setup/InstancePage.php index dccfd1d91..8f151554d 100644 --- a/modules/monitoring/application/forms/Setup/InstancePage.php +++ b/modules/monitoring/application/forms/Setup/InstancePage.php @@ -20,7 +20,7 @@ class InstancePage extends Form 'note', 'title', array( - 'value' => mt('monitoring', 'Monitoring Instance', 'setup.page.title'), + 'value' => $this->translate('Monitoring Instance', 'setup.page.title'), 'decorators' => array( 'ViewHelper', array('HtmlTag', array('tag' => 'h2')) @@ -31,8 +31,7 @@ class InstancePage extends Form 'note', 'description', array( - 'value' => mt( - 'monitoring', + 'value' => $this->translate( 'Please define the settings specific to your monitoring instance below.' ) ) diff --git a/modules/monitoring/application/forms/Setup/LivestatusResourcePage.php b/modules/monitoring/application/forms/Setup/LivestatusResourcePage.php index 4faa17416..245d2abcc 100644 --- a/modules/monitoring/application/forms/Setup/LivestatusResourcePage.php +++ b/modules/monitoring/application/forms/Setup/LivestatusResourcePage.php @@ -28,7 +28,7 @@ class LivestatusResourcePage extends Form 'note', 'title', array( - 'value' => mt('monitoring', 'Monitoring Livestatus Resource', 'setup.page.title'), + 'value' => $this->translate('Monitoring Livestatus Resource', 'setup.page.title'), 'decorators' => array( 'ViewHelper', array('HtmlTag', array('tag' => 'h2')) @@ -39,8 +39,7 @@ class LivestatusResourcePage extends Form 'note', 'description', array( - 'value' => mt( - 'monitoring', + 'value' => $this->translate( 'Please fill out the connection details below to access the Livestatus' . ' socket interface for your monitoring environment.' ) @@ -91,8 +90,10 @@ class LivestatusResourcePage extends Form 'skip_validation', array( 'required' => true, - 'label' => t('Skip Validation'), - 'description' => t('Check this to not to validate connectivity with the given Livestatus socket') + 'label' => $this->translate('Skip Validation'), + 'description' => $this->translate( + 'Check this to not to validate connectivity with the given Livestatus socket' + ) ) ); } diff --git a/modules/monitoring/application/forms/Setup/SecurityPage.php b/modules/monitoring/application/forms/Setup/SecurityPage.php index 0c7d3d1de..ba8083e50 100644 --- a/modules/monitoring/application/forms/Setup/SecurityPage.php +++ b/modules/monitoring/application/forms/Setup/SecurityPage.php @@ -20,7 +20,7 @@ class SecurityPage extends Form 'note', 'title', array( - 'value' => mt('monitoring', 'Monitoring Security', 'setup.page.title'), + 'value' => $this->translate('Monitoring Security', 'setup.page.title'), 'decorators' => array( 'ViewHelper', array('HtmlTag', array('tag' => 'h2')) @@ -31,8 +31,7 @@ class SecurityPage extends Form 'note', 'description', array( - 'value' => mt( - 'monitoring', + 'value' => $this->translate( 'To protect your monitoring environment against prying eyes please fill out the settings below.' ) ) diff --git a/modules/monitoring/application/forms/Setup/WelcomePage.php b/modules/monitoring/application/forms/Setup/WelcomePage.php index d910e2e01..f79eb6c62 100644 --- a/modules/monitoring/application/forms/Setup/WelcomePage.php +++ b/modules/monitoring/application/forms/Setup/WelcomePage.php @@ -19,10 +19,7 @@ class WelcomePage extends Form 'note', 'welcome', array( - 'value' => mt( - 'monitoring', - 'Welcome to the configuration of the monitoring module for Icinga Web 2!' - ), + 'value' => $this->translate('Welcome to the configuration of the monitoring module for Icinga Web 2!'), 'decorators' => array( 'ViewHelper', array('HtmlTag', array('tag' => 'h2')) @@ -34,7 +31,7 @@ class WelcomePage extends Form 'note', 'core_hint', array( - 'value' => mt('monitoring', 'This is the core module for Icinga Web 2.') + 'value' => $this->translate('This is the core module for Icinga Web 2.') ) ); @@ -42,8 +39,7 @@ class WelcomePage extends Form 'note', 'description', array( - 'value' => mt( - 'monitoring', + 'value' => $this->translate( 'It offers various status and reporting views with powerful filter capabilities that allow' . ' you to keep track of the most important events in your monitoring environment.' ) diff --git a/modules/monitoring/application/forms/StatehistoryForm.php b/modules/monitoring/application/forms/StatehistoryForm.php index 9fa1bdc26..d859f5815 100644 --- a/modules/monitoring/application/forms/StatehistoryForm.php +++ b/modules/monitoring/application/forms/StatehistoryForm.php @@ -19,7 +19,7 @@ class StatehistoryForm extends Form public function init() { $this->setName('form_event_overview'); - $this->setSubmitLabel(mt('monitoring', 'Apply')); + $this->setSubmitLabel($this->translate('Apply')); } /** @@ -65,14 +65,14 @@ class StatehistoryForm extends Form 'select', 'from', array( - 'label' => mt('monitoring', 'From'), + 'label' => $this->translate('From'), 'value' => $this->getRequest()->getParam('from', strtotime('3 months ago')), 'multiOptions' => array( - strtotime('midnight 3 months ago') => mt('monitoring', '3 Months'), - strtotime('midnight 4 months ago') => mt('monitoring', '4 Months'), - strtotime('midnight 8 months ago') => mt('monitoring', '8 Months'), - strtotime('midnight 12 months ago') => mt('monitoring', '1 Year'), - strtotime('midnight 24 months ago') => mt('monitoring', '2 Years') + strtotime('midnight 3 months ago') => $this->translate('3 Months'), + strtotime('midnight 4 months ago') => $this->translate('4 Months'), + strtotime('midnight 8 months ago') => $this->translate('8 Months'), + strtotime('midnight 12 months ago') => $this->translate('1 Year'), + strtotime('midnight 24 months ago') => $this->translate('2 Years') ), 'class' => 'autosubmit' ) @@ -81,10 +81,10 @@ class StatehistoryForm extends Form 'select', 'to', array( - 'label' => mt('monitoring', 'To'), + 'label' => $this->translate('To'), 'value' => $this->getRequest()->getParam('to', time()), 'multiOptions' => array( - time() => mt('monitoring', 'Today') + time() => $this->translate('Today') ), 'class' => 'autosubmit' ) @@ -95,11 +95,11 @@ class StatehistoryForm extends Form 'select', 'objecttype', array( - 'label' => mt('monitoring', 'Object type'), + 'label' => $this->translate('Object type'), 'value' => $objectType, 'multiOptions' => array( - 'services' => mt('monitoring', 'Services'), - 'hosts' => mt('monitoring', 'Hosts') + 'services' => $this->translate('Services'), + 'hosts' => $this->translate('Hosts') ), 'class' => 'autosubmit' ) @@ -113,13 +113,13 @@ class StatehistoryForm extends Form 'select', 'state', array( - 'label' => mt('monitoring', 'State'), + 'label' => $this->translate('State'), 'value' => $serviceState, 'multiOptions' => array( - 'cnt_critical_hard' => mt('monitoring', 'Critical'), - 'cnt_warning_hard' => mt('monitoring', 'Warning'), - 'cnt_unknown_hard' => mt('monitoring', 'Unknown'), - 'cnt_ok' => mt('monitoring', 'Ok') + 'cnt_critical_hard' => $this->translate('Critical'), + 'cnt_warning_hard' => $this->translate('Warning'), + 'cnt_unknown_hard' => $this->translate('Unknown'), + 'cnt_ok' => $this->translate('Ok') ), 'class' => 'autosubmit' ) @@ -133,12 +133,12 @@ class StatehistoryForm extends Form 'select', 'state', array( - 'label' => mt('monitoring', 'State'), + 'label' => $this->translate('State'), 'value' => $hostState, 'multiOptions' => array( - 'cnt_up' => mt('monitoring', 'Up'), - 'cnt_down_hard' => mt('monitoring', 'Down'), - 'cnt_unreachable_hard' => mt('monitoring', 'Unreachable') + 'cnt_up' => $this->translate('Up'), + 'cnt_down_hard' => $this->translate('Down'), + 'cnt_unreachable_hard' => $this->translate('Unreachable') ), 'class' => 'autosubmit' ) diff --git a/modules/monitoring/application/views/helpers/Link.php b/modules/monitoring/application/views/helpers/Link.php new file mode 100644 index 000000000..0d8c35861 --- /dev/null +++ b/modules/monitoring/application/views/helpers/Link.php @@ -0,0 +1,59 @@ +view->qlink( + $linkText, + $this->view->href('monitoring/host/show', array('host' => $host)) + ); + } + + /** + * Create a service link + * + * @param string $service Service name + * @param string $serviceLinkText Text for the service link, e.g. the service's display name + * @param string $host Hostname + * @param string $hostLinkText Text for the host link, e.g. the host's display name + * + * @return string + */ + public function service($service, $serviceLinkText, $host, $hostLinkText) + { + return sprintf( + $this->view->translate('%s on %s', 'Service running on host'), + $this->view->qlink( + $serviceLinkText, + $this->view->href('monitoring/service/show', array('host' => $host, 'service' => $service)) + ), + $this->host($host, $hostLinkText) + ); + } +} diff --git a/modules/monitoring/application/views/helpers/MonitoringState.php b/modules/monitoring/application/views/helpers/MonitoringState.php deleted file mode 100644 index 13bd93ea7..000000000 --- a/modules/monitoring/application/views/helpers/MonitoringState.php +++ /dev/null @@ -1,108 +0,0 @@ - 'pending', null => 'pending'); - private $hoststates = array('up', 'down', 'unreachable', 99 => 'pending', null => 'pending'); - - /** - * @deprecated Not used anywhere. - */ - public function monitoringState($object, $type = 'service') - { - if ($type === 'service') { - return $this->servicestates[$object->service_state]; - } elseif ($type === 'host') { - return $this->hoststates[$object->host_state]; - } - } - - /** - * @deprecated Not used anywhere. - */ - public function monitoringStateById($id, $type = 'service') - { - if ($type === 'service') { - return $this->servicestates[$id]; - } elseif ($type === 'host') { - return $this->hoststates[$id]; - } - } - - /** - * @deprecated Monitoring colors are clustered. - */ - public function getServiceStateColors() - { - return array('#44bb77', '#FFCC66', '#FF5566', '#E066FF', '#77AAFF'); - } - - /** - * @deprecated Monitoring colors are clustered. - */ - public function getHostStateColors() - { - return array('#44bb77', '#FF5566', '#E066FF', '#77AAFF'); - } - - /** - * @deprecated The service object must know about it's possible states. - */ - public function getServiceStateNames() - { - return array_values($this->servicestates); - } - - /** - * @deprecated The host object must know about it's possible states. - */ - public function getHostStateNames() - { - return array_values($this->hoststates); - } - - /** - * @deprecated Not used anywhere. - */ - public function getStateFlags($object, $type = 'service') - { - $state_classes = array(); - if ($type === 'host') { - $state_classes[] = $this->monitoringState($object, "host"); - if ($object->host_acknowledged || $object->host_in_downtime) { - $state_classes[] = 'handled'; - } - if ($object->host_last_state_change > (time() - 600)) { - $state_classes[] = 'new'; - } - } else { - $state_classes[] = $this->monitoringState($object, "service"); - if ($object->service_acknowledged || $object->service_in_downtime) { - $state_classes[] = 'handled'; - } - if ($object->service_last_state_change > (time() - 600)) { - $state_classes[] = 'new'; - } - } - - return $state_classes; - } - - /** - * @deprecated Not used anywhere. - */ - public function getStateTitle($object, $type) - { - return sprintf( - '%s %s %s', - $this->view->translate(strtoupper($this->monitoringState($object, $type))), - $this->view->translate('since'), - date('Y-m-d H:i:s', $object->{$type.'_last_state_change'}) - ); - } -} diff --git a/modules/monitoring/application/views/helpers/Perfdata.php b/modules/monitoring/application/views/helpers/Perfdata.php index eb649e77d..4c2bee89a 100644 --- a/modules/monitoring/application/views/helpers/Perfdata.php +++ b/modules/monitoring/application/views/helpers/Perfdata.php @@ -8,34 +8,52 @@ use Icinga\Module\Monitoring\Plugin\Perfdata; use Icinga\Module\Monitoring\Plugin\PerfdataSet; class Zend_View_Helper_Perfdata extends Zend_View_Helper_Abstract -{ - public function perfdata($perfdataStr, $compact = false) +{# + + /** + * Display the given perfdata string to the user + * + * @param $perfdataStr The perfdata string + * @param bool $compact Whether to display the perfdata in compact mode + * @param $color The color indicating the perfdata state + * + * @return string + */ + public function perfdata($perfdataStr, $compact = false, $color = Perfdata::PERFDATA_OK) { - $pset = PerfdataSet::fromString($perfdataStr)->asArray(); - $onlyPieChartData = array_filter($pset, function ($e) { return $e->getPercentage() > 0; }); - if ($compact) { - $onlyPieChartData = array_slice($onlyPieChartData, 0, 5); - } else { - $nonPieChartData = array_filter($pset, function ($e) { return $e->getPercentage() == 0; }); - } + $pieChartData = PerfdataSet::fromString($perfdataStr)->asArray(); $result = ''; - $table = array(); - foreach ($onlyPieChartData as $perfdata) { - $pieChart = $this->createInlinePie($perfdata); - if ($compact) { - $result .= $pieChart->render(); + $table = array( + '' . implode( + '', + array('', t('Label'), t('Value'), t('Min'), t('Max'), t('Warning'), t('Critical')) + ) . '' + ); + foreach ($pieChartData as $perfdata) { + + if ($compact && $perfdata->isVisualizable()) { + $result .= $perfdata->asInlinePie($color)->render(); } else { - if (! $perfdata->isPercentage()) { - // TODO: Should we trust sprintf-style placeholders in perfdata titles? - $pieChart->setTooltipFormat('{{label}}: {{formatted}} ({{percent}}%)'); + $row = ''; + + $row .= ''; + if ($perfdata->isVisualizable()) { + $row .= $perfdata->asInlinePie($color)->render() . ' '; } - // $pieChart->setStyle('margin: 0.2em 0.5em 0.2em 0.5em;'); - $table[] = '' . $pieChart->render() - . htmlspecialchars($perfdata->getLabel()) - . ' ' - . htmlspecialchars($this->formatPerfdataValue($perfdata)) . - ' '; + $row .= ''; + + if (!$compact) { + foreach ($perfdata->toArray() as $value) { + if ($value === '') { + $value = '-'; + } + $row .= '' . (string)$value . ''; + } + } + + $row .= ''; + $table[] = $row; } } @@ -43,63 +61,7 @@ class Zend_View_Helper_Perfdata extends Zend_View_Helper_Abstract return $result; } else { $pieCharts = empty($table) ? '' : '' . implode("\n", $table) . '
'; - return $pieCharts . "\n" . implode("
\n", $nonPieChartData); + return $pieCharts; } } - - protected function calculatePieChartData(Perfdata $perfdata) - { - $rawValue = $perfdata->getValue(); - $minValue = $perfdata->getMinimumValue() !== null ? $perfdata->getMinimumValue() : 0; - $maxValue = $perfdata->getMaximumValue(); - $usedValue = ($rawValue - $minValue); - $unusedValue = ($maxValue - $minValue) - $usedValue; - - $gray = $unusedValue; - $green = $orange = $red = 0; - // TODO(#6122): Add proper treshold parsing. - if ($perfdata->getCriticalThreshold() && $perfdata->getValue() > $perfdata->getCriticalThreshold()) { - $red = $usedValue; - } elseif ($perfdata->getWarningThreshold() && $perfdata->getValue() > $perfdata->getWarningThreshold()) { - $orange = $usedValue; - } else { - $green = $usedValue; - } - - return array($green, $orange, $red, $gray); - } - - protected function formatPerfdataValue(Perfdata $perfdata) - { - if ($perfdata->isBytes()) { - return Format::bytes($perfdata->getValue()); - } elseif ($perfdata->isSeconds()) { - return Format::seconds($perfdata->getValue()); - } elseif ($perfdata->isPercentage()) { - return $perfdata->getValue() . '%'; - } - - return $perfdata->getValue(); - } - - protected function createInlinePie(Perfdata $perfdata) - { - $pieChart = new InlinePie($this->calculatePieChartData($perfdata), $perfdata->getLabel()); - $pieChart->setLabel(htmlspecialchars($perfdata->getLabel())); - $pieChart->setHideEmptyLabel(); - - //$pieChart->setHeight(32)->setWidth(32); - if ($perfdata->isBytes()) { - $pieChart->setTooltipFormat('{{label}}: {{formatted}} ({{percent}}%)'); - $pieChart->setNumberFormat(InlinePie::NUMBER_FORMAT_BYTES); - } else if ($perfdata->isSeconds()) { - $pieChart->setTooltipFormat('{{label}}: {{formatted}} ({{percent}}%)'); - $pieChart->setNumberFormat(InlinePie::NUMBER_FORMAT_TIME); - } else { - $pieChart->setTooltipFormat('{{label}}: {{formatted}}%'); - $pieChart->setNumberFormat(InlinePie::NUMBER_FORMAT_RATIO); - $pieChart->setHideEmptyLabel(); - } - return $pieChart; - } } diff --git a/modules/monitoring/application/views/helpers/_RenderServicePerfdata.php b/modules/monitoring/application/views/helpers/_RenderServicePerfdata.php deleted file mode 100644 index d7612ac30..000000000 --- a/modules/monitoring/application/views/helpers/_RenderServicePerfdata.php +++ /dev/null @@ -1,25 +0,0 @@ - array("self::renderDiskPie") - ); - - public function renderServicePerfdata($service) - { - if (isset(self::$RENDERMAP[$service->check_command])) { - $fn = self::$RENDERMAP[$service->check_command]; - $fn($service); - } - } - - public static function renderDiskPie($service) { - $perfdata = $service->performance_data; - if(!$perfdata) - return ""; - - } -} diff --git a/modules/monitoring/application/views/scripts/alertsummary/index.phtml b/modules/monitoring/application/views/scripts/alertsummary/index.phtml index 624b942b3..dbfff6433 100644 --- a/modules/monitoring/application/views/scripts/alertsummary/index.phtml +++ b/modules/monitoring/application/views/scripts/alertsummary/index.phtml @@ -1,6 +1,3 @@ -getHelper('MonitoringState'); -?>
tabs ?>
diff --git a/modules/monitoring/application/views/scripts/chart/test.phtml b/modules/monitoring/application/views/scripts/chart/test.phtml index 1c2046bdf..214f44d33 100644 --- a/modules/monitoring/application/views/scripts/chart/test.phtml +++ b/modules/monitoring/application/views/scripts/chart/test.phtml @@ -1,6 +1,5 @@ -mah -
-render(); -?> -
\ No newline at end of file + +
+ render() ?> +
+ \ No newline at end of file diff --git a/modules/monitoring/application/views/scripts/command/list.phtml b/modules/monitoring/application/views/scripts/command/list.phtml deleted file mode 100644 index 747dd4b5e..000000000 --- a/modules/monitoring/application/views/scripts/command/list.phtml +++ /dev/null @@ -1,10 +0,0 @@ -

- \ No newline at end of file diff --git a/modules/monitoring/application/views/scripts/command/renderform.phtml b/modules/monitoring/application/views/scripts/command/renderform.phtml deleted file mode 100644 index 9c8e79428..000000000 --- a/modules/monitoring/application/views/scripts/command/renderform.phtml +++ /dev/null @@ -1,25 +0,0 @@ -
-tabs ?> -
-
-objects) && !empty($this->objects) && isset($this->objects[0]->host_name)): ?> - - - - - - - - -objects as $object): ?> - - - - - - -
icon('host') ?> Hosticon('conf') ?> Service
host_name; ?>service_description) ? $object->service_description : '') ?>
- - -form ?> -
diff --git a/modules/monitoring/application/views/scripts/config/index.phtml b/modules/monitoring/application/views/scripts/config/index.phtml index b1729f9b1..deca8d468 100644 --- a/modules/monitoring/application/views/scripts/config/index.phtml +++ b/modules/monitoring/application/views/scripts/config/index.phtml @@ -1,4 +1,4 @@ -
+

translate('Monitoring Backends') ?>

diff --git a/modules/monitoring/application/views/scripts/config/security.phtml b/modules/monitoring/application/views/scripts/config/security.phtml index 71f2a341a..2a84b2469 100644 --- a/modules/monitoring/application/views/scripts/config/security.phtml +++ b/modules/monitoring/application/views/scripts/config/security.phtml @@ -1,4 +1,4 @@ -
+
tabs ?>
diff --git a/modules/monitoring/application/views/scripts/hosts/show.phtml b/modules/monitoring/application/views/scripts/hosts/show.phtml index 6e114f2d8..f21c09fd1 100644 --- a/modules/monitoring/application/views/scripts/hosts/show.phtml +++ b/modules/monitoring/application/views/scripts/hosts/show.phtml @@ -2,25 +2,31 @@ tabs ?>
- + + translate('No hosts matching the filter') ?>
- translate('Hosts (%u)'), array_sum(array_values($hostStates))) ?> + translatePlural('Host (%u)', 'Hosts (%u)', $hostCount), $hostCount) ?>
- hostStatesPieChart ?> +  hostStatesPieChart ?>
$count) { - echo sprintf('%s: %u
', strtoupper($text), $count); + echo sprintf('%s: %u
', $this->translate(strtoupper($text)), $count); } ?>

- translate('%u Hosts'), - count($objects)) - ?> + translatePlural( + '%u Host', + '%u Hosts', + $hostCount + ), + $hostCount + ) ?>

@@ -59,13 +65,14 @@

+ translatePlural( '%u Unhandled Host Problem', '%u Unhandled Host Problems', - count($unhandledObjects) + $unhandledCount ), - count($unhandledObjects) + $unhandledCount ) ?>

@@ -86,13 +93,14 @@

+ translatePlural( '%u Acknowledged Host Problem', '%u Acknowledged Host Problems', - count($acknowledgedObjects) + $acknowledgedCount ), - count($acknowledgedObjects) + $acknowledgedCount ) ?>

@@ -102,25 +110,27 @@

+ icon('plug') ?> - translatePlural( '%u host is in downtime', '%u hosts are in downtime', - count($objectsInDowntime) + $inDowntimeCount ), - count($objectsInDowntime) - ); ?> + $inDowntimeCount + ) ?>

- getComments())): ?> + getComments()) ?> +

icon('comment') ?> - translate(sprintf('%u comments', count($objects->getComments()))) ?> + translatePlural( + '%u comment', + '%u comments', + $havingCommentsCount + ), + $havingCommentsCount + ) ?>

diff --git a/modules/monitoring/application/views/scripts/layout/topbar.phtml b/modules/monitoring/application/views/scripts/layout/topbar.phtml deleted file mode 100644 index f7c58db85..000000000 --- a/modules/monitoring/application/views/scripts/layout/topbar.phtml +++ /dev/null @@ -1,65 +0,0 @@ - - - diff --git a/modules/monitoring/application/views/scripts/list/comments.phtml b/modules/monitoring/application/views/scripts/list/comments.phtml index 677010f1b..857017b4d 100644 --- a/modules/monitoring/application/views/scripts/list/comments.phtml +++ b/modules/monitoring/application/views/scripts/list/comments.phtml @@ -50,21 +50,13 @@ objecttype === 'service'): ?> - icon('conf'); ?> - service; ?> - - - translate('on') . ' ' . $comment->host; ?> - + icon('service') ?> + link()->service( + $comment->service, $comment->service_display_name, $comment->host, $comment->host_display_name + ) ?> - icon('host'); ?> - host; ?> - + icon('host') ?> + link()->host($comment->host, $comment->host_display_name) ?>
icon('comment'); ?> author) @@ -83,18 +75,20 @@ date('H:i', $comment->expiration) ) : $this->translate('This comment does not expire.'); ?> + populate(array('comment_id' => $comment->id, 'redirect' => $this->url)); if ($comment->objecttype === 'host') { - $delCommentForm->setAction($this->url('monitoring/host/remove-comment', array('host' => $comment->host))); + $delCommentForm->setAction($this->url('monitoring/host/delete-comment', array('host' => $comment->host))); } else { - $delCommentForm->setAction($this->url('monitoring/service/remove-comment', array('host' => $comment->host, 'service' => $comment->service))); + $delCommentForm->setAction($this->url('monitoring/service/delete-comment', array('host' => $comment->host, 'service' => $comment->service))); } echo $delCommentForm; ?> + diff --git a/modules/monitoring/application/views/scripts/list/components/servicesummary.phtml b/modules/monitoring/application/views/scripts/list/components/servicesummary.phtml index dab7071a1..c870b09b0 100644 --- a/modules/monitoring/application/views/scripts/list/components/servicesummary.phtml +++ b/modules/monitoring/application/views/scripts/list/components/servicesummary.phtml @@ -12,7 +12,7 @@ $currentUrl = Url::fromRequest()->getRelativeUrl(); $this->stats->services_ok, $selfUrl, array('service_state' => 0), - array('title' => sprintf($this->translate('Services with state %s'), strtoupper($this->translate('ok')))) + array('title' => sprintf($this->translate('Services with state %s'), $this->translate('OK'))) ) ?> @@ -44,7 +44,7 @@ foreach (array(2 => 'critical', 3 => 'unknown', 1 => 'warning') as $stateId => $ $this->stats->$unhandled, $selfUrl, $paramsUnhandled, - array('title' => sprintf($this->translate('Unhandled services with state %s'), strtoupper($this->translate($state)))) + array('title' => sprintf($this->translate('Unhandled services with state %s'), $this->translate(strtoupper($state)))) ); } if ($this->stats->$handled) { @@ -61,7 +61,7 @@ foreach (array(2 => 'critical', 3 => 'unknown', 1 => 'warning') as $stateId => $ $this->stats->$handled, $selfUrl, $paramsHandled, - array('title' => sprintf($this->translate('Handled services with state %s'), strtoupper($this->translate($state)))) + array('title' => sprintf($this->translate('Handled services with state %s'), $this->translate(strtoupper($state)))) ); if ($this->stats->$unhandled) { echo "\n"; @@ -77,7 +77,7 @@ foreach (array(2 => 'critical', 3 => 'unknown', 1 => 'warning') as $stateId => $ $this->stats->services_pending, $selfUrl, array('service_state' => 99), - array('title' => sprintf($this->translate('Services with state %s'), strtoupper($this->translate('pending')))) + array('title' => sprintf($this->translate('Services with state %s'), $this->translate('PENDING'))) ) ?> diff --git a/modules/monitoring/application/views/scripts/list/contacts.phtml b/modules/monitoring/application/views/scripts/list/contacts.phtml index f6face461..d8d2a2e72 100644 --- a/modules/monitoring/application/views/scripts/list/contacts.phtml +++ b/modules/monitoring/application/views/scripts/list/contacts.phtml @@ -1,7 +1,3 @@ -getHelper('MonitoringState'); -$contactHelper = $this->getHelper('ContactFlags'); -?>
tabs ?>
diff --git a/modules/monitoring/application/views/scripts/list/downtimes.phtml b/modules/monitoring/application/views/scripts/list/downtimes.phtml index 37b34fe5e..eaf4b7f8e 100644 --- a/modules/monitoring/application/views/scripts/list/downtimes.phtml +++ b/modules/monitoring/application/views/scripts/list/downtimes.phtml @@ -31,8 +31,10 @@ use Icinga\Module\Monitoring\Object\Service; service)) { + $isService = true; $stateName = Service::getStateText($downtime->service_state); } else { + $isService = false; $stateName = Host::getStateText($downtime->host_state); } ?> @@ -52,31 +54,25 @@ use Icinga\Module\Monitoring\Object\Service; ?> - service)): ?> - - service; ?> - - - translate('on'); ?> host; ?> - + + icon('service') ?> + link()->service( + $downtime->service, $downtime->service_display_name, $downtime->host, $downtime->host_display_name + ) ?> - - host; ?> - + icon('host') ?> + link()->host($downtime->host, $downtime->host_display_name) ?>
- icon('comment'); ?> [author; ?>] comment; ?> + icon('comment') ?> [escape($downtime->author) ?>] escape($downtime->comment) ?>
is_flexible): ?> is_in_effect): ?> translate('This flexible downtime was started on %s at %s and lasts for %s until %s at %s.'), + isset($downtime->service) + ? $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), @@ -85,7 +81,9 @@ use Icinga\Module\Monitoring\Object\Service; ); ?> translate('This flexible downtime has been scheduled to start between %s - %s and to last for %s.'), + isset($downtime->service) + ? $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) @@ -94,7 +92,9 @@ use Icinga\Module\Monitoring\Object\Service; is_in_effect): ?> translate('This fixed downtime was started on %s at %s and expires on %s at %s.'), + isset($downtime->service) + ? $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), @@ -102,7 +102,9 @@ use Icinga\Module\Monitoring\Object\Service; ); ?> translate('This fixed downtime has been scheduled to start on %s at %s and to end on %s at %s.'), + isset($downtime->service) + ? $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), @@ -112,6 +114,7 @@ use Icinga\Module\Monitoring\Object\Service; + + diff --git a/modules/monitoring/application/views/scripts/list/eventhistory.phtml b/modules/monitoring/application/views/scripts/list/eventhistory.phtml index a9516aab1..0b6b9bcec 100644 --- a/modules/monitoring/application/views/scripts/list/eventhistory.phtml +++ b/modules/monitoring/application/views/scripts/list/eventhistory.phtml @@ -70,21 +70,13 @@ use Icinga\Module\Monitoring\Object\Service; $icon = $isService ? 'service' : 'host'; $msg = '[ ' . $event->attempt . '/' . $event->max_attempts . ' ] ' . $event->output; $stateName = $isService ? Service::getStateText($event->state) : Host::getStateText($event->state); - $title = strtoupper( - $isService - ? Service::getStateText($event->state, true) - : Host::getStateText($event->state, true) - ); + $title = $isService ? Service::getStateText($event->state, true) : Host::getStateText($event->state, true); break; case 'soft_state': $icon = 'lightbulb'; $msg = '[ ' . $event->attempt . '/' . $event->max_attempts . ' ] ' . $event->output; $stateName = $isService ? Service::getStateText($event->state) : Host::getStateText($event->state); - $title = strtoupper( - $isService - ? Service::getStateText($event->state, true) - : Host::getStateText($event->state, true) - ); + $title = $isService ? Service::getStateText($event->state, true) : Host::getStateText($event->state, true); break; case 'dt_start': $icon = 'starttime'; @@ -106,25 +98,15 @@ use Icinga\Module\Monitoring\Object\Service; - - service; ?> - - - translate('on') . ' ' . $event->host; ?> - + link()->service( + $event->service, $event->service_display_name, $event->host, $event->host_display_name + ) ?> - - host; ?> - + link()->host($event->host, $event->host_display_name) ?>
- icon($icon, $title); ?> + icon($icon, $title); ?> escape($msg) ?>
diff --git a/modules/monitoring/application/views/scripts/list/hostgroups.phtml b/modules/monitoring/application/views/scripts/list/hostgroups.phtml index 6238c1963..9e773c61a 100644 --- a/modules/monitoring/application/views/scripts/list/hostgroups.phtml +++ b/modules/monitoring/application/views/scripts/list/hostgroups.phtml @@ -79,8 +79,8 @@ - - hostgroup; ?> + + escape($h->hostgroup_alias) ?> diff --git a/modules/monitoring/application/views/scripts/list/hosts.phtml b/modules/monitoring/application/views/scripts/list/hosts.phtml index 3953db975..55242101c 100644 --- a/modules/monitoring/application/views/scripts/list/hosts.phtml +++ b/modules/monitoring/application/views/scripts/list/hosts.phtml @@ -1,8 +1,6 @@ getHelper('MonitoringState'); - if ($this->compact): ?>
@@ -82,7 +80,7 @@ if ($hosts->count() === 0) { - host_state, true)); ?>
+ host_state, true); ?>
host_state !== 99): ?> prefixedTimeSince($host->host_last_state_change, true) ?> host_state > 0 && (int) $host->host_state_type === 0): ?> @@ -98,7 +96,7 @@ if ($hosts->count() === 0) { icon($this->resolveMacros($host->host_icon_image, $host)) ?> - host_name ?> + escape($host->host_display_name) ?> host_unhandled_services) && $host->host_unhandled_services > 0): ?> host_unhandled_services), @@ -110,15 +108,14 @@ if ($hosts->count() === 0) { $host->host_unhandled_services), 'monitoring/show/services', array( - 'host' => $host->host_name, - 'service_problem' => 1, - 'service_acknowledged' => 0, - 'service_in_downtime' => 0 + 'host' => $host->host_name, + 'service_problem' => 1, + 'service_handled' => 0 ), array('style' => 'font-weight: normal') ) ?>) -

escape(substr(strip_tags($host->host_output), 0, 10000)) ?>

+

escape($this->ellipsis($host->host_output, 10000)) ?>

extraColumns as $col): ?> escape($host->$col) ?> diff --git a/modules/monitoring/application/views/scripts/list/notifications.phtml b/modules/monitoring/application/views/scripts/list/notifications.phtml index 845effbc5..44f33851f 100644 --- a/modules/monitoring/application/views/scripts/list/notifications.phtml +++ b/modules/monitoring/application/views/scripts/list/notifications.phtml @@ -5,85 +5,72 @@ use Icinga\Module\Monitoring\Object\Service; ?> -compact): ?> +compact): ?>
- tabs ?> -
- translate('Sort by') ?> sortControl->render($this) ?> -
- widget('limiter') ?> - paginationControl($notifications, null, null, array('preserve' => $this->preserve)) ?> -
+ tabs ?> +
+ translate('Sort by') ?> sortControl->render($this) ?> +
+ widget('limiter') ?> + paginationControl($notifications, null, null, array('preserve' => $this->preserve)) ?> +
-inline): ?>
- + + translate('No notifications matching the filter') ?> + -notifications)) { - echo 'No notifications yet
'; - return; -} -?> - - - -service)) { - $isService = true; - $href = $this->href('monitoring/show/service', array( - 'host' => $notification->host, - 'service' => $notification->service - )); - $stateName = Service::getStateText($notification->notification_state); - } else { - $isService = false; - $href = $this->href('monitoring/show/host', array( - 'host' => $notification->host - )); - $stateName = Host::getStateText($notification->notification_state); - } -?> - - - - - - -
- dateTimeRenderer($notification->notification_start_time)->render( - $this->translate('on %s', 'datetime'), - $this->translate('at %s', 'time'), - $this->translate('%s ago', 'timespan') - ); - ?> - - - service ?> on host ?> - - host ?> - -
- escape(substr(strip_tags($notification->notification_output), 0, 10000)); ?> -
- contact): ?> - - Sent to escape($notification->notification_contact) ?> - - -
- -inline): ?> + + + service)) { + $isService = true; + $stateName = Service::getStateText($notification->notification_state); + } else { + $isService = false; + $stateName = Host::getStateText($notification->notification_state); + } + ?> + + + + + + +
+ dateTimeRenderer($notification->notification_start_time)->render( + $this->translate('on %s', 'datetime'), + $this->translate('at %s', 'time'), + $this->translate('%s ago', 'timespan') + ) ?> + + + icon('service') ?> + link()->service( + $notification->service, + $notification->service_display_name, + $notification->host, + $notification->host_display_name + ) ?> + + icon('host') ?> + link()->host($notification->host, $notification->host_display_name) ?> + +
+ escape($this->ellipsis($notification->notification_output, 10000)) ?> +
+ contact): ?> + + translate('Sent to %s'), + $this->qlink( + $notification->notification_contact, + 'monitoring/show/contact', + array('contact' => $notification->notification_contact) + ) + ) ?> + + +
- diff --git a/modules/monitoring/application/views/scripts/list/servicegroups.phtml b/modules/monitoring/application/views/scripts/list/servicegroups.phtml index 09abae6a1..71195ba61 100644 --- a/modules/monitoring/application/views/scripts/list/servicegroups.phtml +++ b/modules/monitoring/application/views/scripts/list/servicegroups.phtml @@ -80,7 +80,7 @@ - servicegroup; ?> + translate($s->servicegroup_alias) ?> diff --git a/modules/monitoring/application/views/scripts/list/services.phtml b/modules/monitoring/application/views/scripts/list/services.phtml index 994304f08..45d59adf5 100644 --- a/modules/monitoring/application/views/scripts/list/services.phtml +++ b/modules/monitoring/application/views/scripts/list/services.phtml @@ -2,8 +2,6 @@ use Icinga\Module\Monitoring\Object\Host; use Icinga\Module\Monitoring\Object\Service; -$helper = $this->getHelper('MonitoringState'); - $selfUrl = 'monitoring/list/services'; if (!$this->compact): ?> @@ -58,7 +56,7 @@ foreach ($services as $service): ?> - service_state, true)); ?>
+ service_state, true); ?>
compact): ?>prefixedTimeSince($service->service_last_state_change); ?>timeSince($service->service_last_state_change); ?> service_state > 0 && (int) $service->service_state_type === 0): ?>
@@ -106,12 +104,12 @@ foreach ($services as $service): service_icon_image && ! preg_match('/[\'"]/', $service->service_icon_image)): ?> icon($this->resolveMacros($service->service_icon_image, $service)) ?> -service_display_name ?>showHost): ?> on host_name; ?> +escape($service->service_display_name) ?>showHost): ?> on escape($service->host_display_name) ?> host_state != 0): ?> - (host_state, true)); ?>) + (host_state, true); ?>)
-

escape(substr(strip_tags($service->service_output), 0, 10000)); ?>

+

escape($this->ellipsis($service->service_output, 10000)); ?>

extraColumns as $col): ?> escape($service->$col) ?> diff --git a/modules/monitoring/application/views/scripts/multi/components/comments.phtml b/modules/monitoring/application/views/scripts/multi/components/comments.phtml deleted file mode 100644 index f0b262c9d..000000000 --- a/modules/monitoring/application/views/scripts/multi/components/comments.phtml +++ /dev/null @@ -1,25 +0,0 @@ -is_service ? 'Services' : 'Hosts'; - -?> - translate('Comments') ?> - - icon('cancel') - ?> translate('Remove Comments') ?>
- icon('bell-off-empty') - ?> translate('Delay Notifications') ?>
- - icon('ok') ?> Acknowledge - - - comments . - - diff --git a/modules/monitoring/application/views/scripts/multi/components/downtimes.phtml b/modules/monitoring/application/views/scripts/multi/components/downtimes.phtml deleted file mode 100644 index af8d841b4..000000000 --- a/modules/monitoring/application/views/scripts/multi/components/downtimes.phtml +++ /dev/null @@ -1,19 +0,0 @@ -is_service ? 'Services' : 'Hosts'; - -?> - - Downtimes - - icon('cancel') ?>Remove Downtimes
- icon('plug') - ?> Schedule Downtimes - - - Change downtimes. - - diff --git a/modules/monitoring/application/views/scripts/multi/components/flags.phtml b/modules/monitoring/application/views/scripts/multi/components/flags.phtml deleted file mode 100644 index 1269e2f49..000000000 --- a/modules/monitoring/application/views/scripts/multi/components/flags.phtml +++ /dev/null @@ -1,25 +0,0 @@ -
- - form->getElements() as $name => $element): - if ($element instanceof \Icinga\Web\Form\Element\TriStateCheckbox): - $element->setDecorators(array('ViewHelper')); - ?> - - - - - - - - - - - -
render() ?>
render() ?>
-
\ No newline at end of file diff --git a/modules/monitoring/application/views/scripts/multi/components/objectlist.phtml b/modules/monitoring/application/views/scripts/multi/components/objectlist.phtml deleted file mode 100644 index 879a13a1d..000000000 --- a/modules/monitoring/application/views/scripts/multi/components/objectlist.phtml +++ /dev/null @@ -1,65 +0,0 @@ -is_service) { - $links[] = $this->qlink( - $object->host_name . ' ' . $object->service_description, - 'monitoring/show/service', - array( - 'host' => $object->host_name, - 'service' => $object->service_description - ) - ); - } else { - $links[] = $this->qlink( - $object->host_name, - 'monitoring/show/host', - array( - 'host' => $object->host_name - ) - ); - } -} - -if ($this->is_service) { - $objectName = $this->translate('Services'); - $link = 'monitoring/list/services'; - $target = array( - 'host' => $this->hostquery, - 'service' => $this->servicequery - ); -} else { - $objectName = $this->translate('Hosts'); - $link = 'monitoring/list/hosts'; - $target = array( - 'host' => $this->hostquery - ); -} - -$more = clone $this->url; - - -?> -qlink( - $this->translate('List all'), - $more->setPath($link), - null, - array('title' => $this->translate('List all selected objects')) -) ?> - - 5) { - echo ' ' . sprintf($this->translate('and %d more'), count($objects) - 5); -} - -?> - - diff --git a/modules/monitoring/application/views/scripts/multi/components/summary.phtml b/modules/monitoring/application/views/scripts/multi/components/summary.phtml deleted file mode 100644 index d832624c7..000000000 --- a/modules/monitoring/application/views/scripts/multi/components/summary.phtml +++ /dev/null @@ -1,59 +0,0 @@ -getHelper('CommandForm'); -$servicequery = isset($this->servicequery) ? $this->servicequery : ''; -$objectName = $this->is_service ? $this->translate('Services') : $this->translate('Hosts'); - -$params = array( - 'host' => $this->target['host'], - 'service' => null, - 'checktime' => time(), - 'forcecheck' => '1' -); -if (array_key_exists('service', $this->target)) { - $params['service'] = $this->target['service']; -} else { - unset($params['service']); -} -?> - - - - icon('rescheduel') - ?> Recheck
- icon('reschedule') - ?> Reschedule
- - Perform actions on . - - - - problems ?> Problems - - icon('plug') - ?> Schedule Downtimes - - problems, - count($this->objects), - $objectName - ) ?> - - - unhandled) ?> Unhandled - - icon('ok') - ?> Acknowledge
- icon('remove_petrol.png') ?> Remove Acknowledgements - - diff --git a/modules/monitoring/application/views/scripts/multi/host.phtml b/modules/monitoring/application/views/scripts/multi/host.phtml deleted file mode 100644 index 6179f6339..000000000 --- a/modules/monitoring/application/views/scripts/multi/host.phtml +++ /dev/null @@ -1,62 +0,0 @@ -is_service = false; -$this->hostquery = implode($this->hostnames, ','); -$this->target = array('host' => $this->hostquery); -?> - -
- tabs; ?> -
- -
- - - -

Summary for hosts

- render('multi/components/objectlist.phtml'); ?> - - - - - - - - - - -
-

Hosts

-
- pie->render(); ?> - - $count) { - if ($count > 0) { - echo ucfirst($state) . ': ' . $count . '
'; - } - } - ?> -
- -

icon('host')?> Host Actions

- - - - render('multi/components/summary.phtml'); ?> - render('multi/components/comments.phtml'); ?> - render('multi/components/downtimes.phtml'); ?> - -
- - render('multi/components/flags.phtml') ?> - -
- - - - diff --git a/modules/monitoring/application/views/scripts/multi/service.phtml b/modules/monitoring/application/views/scripts/multi/service.phtml deleted file mode 100644 index dc2e9f19e..000000000 --- a/modules/monitoring/application/views/scripts/multi/service.phtml +++ /dev/null @@ -1,61 +0,0 @@ -is_service = true; -$this->hostquery = implode($this->hostnames, ','); -$this->servicequery = implode($this->servicenames, ','); -$this->target = array( - 'host' => $this->hostquery, - 'service' => $this->servicequery -); -?> - -
-tabs ?> -
- -
- - - -

Summary for services

- - - - - - - - - - - - -
Services Hosts
service_pie->render() ?> $count) { - if ($count > 0) { - echo ucfirst($state) . ': ' . $count . '
'; - } - } - - ?>
host_pie->render() ?> $count) { - if ($count > 0) { - echo ucfirst($state) . ': ' . $count . '
'; - } - } - ?>
- -

icon('conf')?> Service Actions

- - - - render('multi/components/objectlist.phtml') ?> - render('multi/components/summary.phtml') ?> - render('multi/components/comments.phtml') ?> - render('multi/components/downtimes.phtml') ?> - -
- - render('multi/components/flags.phtml') ?> - -
diff --git a/modules/monitoring/application/views/scripts/partials/command-form.phtml b/modules/monitoring/application/views/scripts/partials/command-form.phtml index 9832bfe17..380687a00 100644 --- a/modules/monitoring/application/views/scripts/partials/command-form.phtml +++ b/modules/monitoring/application/views/scripts/partials/command-form.phtml @@ -1,5 +1,5 @@
- tabs->showOnlyCloseButton() ?> + tabs->remove('dashboard') ?>

icon('help', $form->getHelp()) ?>

diff --git a/modules/monitoring/application/views/scripts/process/info.phtml b/modules/monitoring/application/views/scripts/process/info.phtml index 02b8eeb80..92bb6cb63 100644 --- a/modules/monitoring/application/views/scripts/process/info.phtml +++ b/modules/monitoring/application/views/scripts/process/info.phtml @@ -26,11 +26,11 @@ $cp = $this->checkPerformance()->create($this->checkperformance); translate('Last Status Update'); ?> - timeSince($this->programStatus->status_update_time) ?> ago + translate('%s ago'), $this->timeSince($this->programStatus->status_update_time)); ?> translate('Last External Command Check'); ?> - timeSince($this->programStatus->last_command_check) ?> ago + translate('%s ago'), $this->timeSince($this->programStatus->last_command_check)); ?> translate('Last Log File Rotation'); ?> diff --git a/modules/monitoring/application/views/scripts/services/show.phtml b/modules/monitoring/application/views/scripts/services/show.phtml index 18071c152..522d32ce7 100644 --- a/modules/monitoring/application/views/scripts/services/show.phtml +++ b/modules/monitoring/application/views/scripts/services/show.phtml @@ -2,34 +2,36 @@ tabs ?>
- + + translate('No services matching the filter') ?>
- translate('Services (%u)'), array_sum(array_values($serviceStates))) ?> + translatePlural('Service (%u)', 'Services (%u)', $serviceCount), $serviceCount) ?>
- serviceStatesPieChart ?> +  serviceStatesPieChart ?>
$count) { - echo sprintf(' %s: %u
', strtoupper($text), $count); + echo sprintf(' %s: %u
', $this->translate(strtoupper($text)), $count); } ?>
- translate('Hosts (%u)'), array_sum(array_values($hostStates))) ?> + + translatePlural('Host (%u)', 'Hosts (%u)', $hostCount), $hostCount) ?>
- hostStatesPieChart ?> +  hostStatesPieChart ?>
$count) { - echo sprintf('%s: %u
', strtoupper($text), $count); + echo sprintf('%s: %u
', $this->translate(strtoupper($text)), $count); } ?>
@@ -68,13 +70,14 @@

+ translatePlural( '%u Unhandled Service Problem', '%u Unhandled Service Problems', - count($unhandledObjects) + $unhandledCount ), - count($unhandledObjects) + $unhandledCount ) ?>

@@ -95,13 +98,14 @@

+ translatePlural( '%u Acknowledged Service Problem', '%u Acknowledged Service Problems', - count($acknowledgedObjects) + $acknowledgedCount ), - count($acknowledgedObjects) + $acknowledgedCount ) ?>

@@ -111,20 +115,36 @@

+ icon('plug') ?> - translate(sprintf('%u services are in downtime', count($objectsInDowntime))) ?> + translatePlural( + '%u service is in downtime', + '%u services are in downtime', + $inDowntimeCount + ), + $inDowntimeCount + ) ?>

- getComments())): ?> + getComments()) ?> +

icon('comment') ?> - translate(sprintf('%u comments', count($objects->getComments()))) ?> + translatePlural( + '%u comment', + '%u comments', + $havingCommentsCount + ), + $havingCommentsCount + ) ?>

diff --git a/modules/monitoring/application/views/scripts/show/components/acknowledgement.phtml b/modules/monitoring/application/views/scripts/show/components/acknowledgement.phtml index 9b323e2f5..8da35590f 100644 --- a/modules/monitoring/application/views/scripts/show/components/acknowledgement.phtml +++ b/modules/monitoring/application/views/scripts/show/components/acknowledgement.phtml @@ -7,33 +7,40 @@ if (in_array((int) $object->state, array(0, 99))) { return; } -if ($object->getType() === $object::TYPE_HOST) { - $ackLink = $this->href( - 'monitoring/host/acknowledge-problem', - array('host' => $object->getName()) - ); -} else { - $ackLink = $this->href( - 'monitoring/service/acknowledge-problem', - array('host' => $object->getHost()->getName(), 'service' => $object->getName()) - ); -} - if ($object->acknowledged): ?> translate('Acknowledged') ?> - + + + translate('Not acknowledged') ?> - hasPermission('monitoring/command/acknowledge-problem')) { + if ($object->getType() === $object::TYPE_HOST) { + $ackLink = $this->href( + 'monitoring/host/acknowledge-problem', + array('host' => $object->getName()) + ); + } else { + $ackLink = $this->href( + 'monitoring/service/acknowledge-problem', + array('host' => $object->getHost()->getName(), 'service' => $object->getName()) + ); + } ?> - + icon('ok') ?> translate('Acknowledge') ?> + diff --git a/modules/monitoring/application/views/scripts/show/components/checkstatistics.phtml b/modules/monitoring/application/views/scripts/show/components/checkstatistics.phtml index 50b40cdcc..ec0c2792a 100644 --- a/modules/monitoring/application/views/scripts/show/components/checkstatistics.phtml +++ b/modules/monitoring/application/views/scripts/show/components/checkstatistics.phtml @@ -1,19 +1,13 @@ getType() === $object::TYPE_HOST) { - $reschedule = $this->href( - 'monitoring/host/reschedule-check', - array('host' => $object->getName()) - ); + $isService = false; $checkAttempts = $object->host_current_check_attempt . '/' . $object->host_max_check_attempts; $stateType = (int) $object->host_state_type; } else { - $reschedule = $this->href( - 'monitoring/service/reschedule-check', - array('host' => $object->getHost()->getName(), 'service' => $object->getName()) - ); + $isService = true; $checkAttempts = $object->service_attempt; $stateType = (int) $object->service_state_type; } @@ -23,36 +17,53 @@ if ($object->getType() === $object::TYPE_HOST) { translate('Last check') ?> - + timeSince($object->last_check) ?> translate('Next check') ?> - - icon('reschedule') ?> translate('Reschedule') ?> + hasPermission('monitoring/command/schedule-check')) { + if ($isService) { + $reschedule = $this->href( + 'monitoring/service/reschedule-check', + array('host' => $object->getHost()->getName(), 'service' => $object->getName()) + ); + } else { + $reschedule = $this->href( + 'monitoring/host/reschedule-check', + array('host' => $object->getName()) + ); + } + ?> + + icon('reschedule') ?> + translate('Reschedule') ?> + timeUntil($object->next_check) ?> translate('Check attempts') ?> - translate('(soft state)') ?> + (translate('soft state') ?>) - translate('(hard state)') ?> + (translate('hard state') ?>) check_execution_time): ?> - - translate('Check execution time') ?> - check_execution_time ?>s - + + translate('Check execution time') ?> + check_execution_time ?>s + check_latency): ?> - - translate('Check latency') ?> - check_latency ?>s - + + translate('Check latency') ?> + check_latency ?>s + diff --git a/modules/monitoring/application/views/scripts/show/components/command.phtml b/modules/monitoring/application/views/scripts/show/components/command.phtml index a13ed1bee..a74b5b884 100644 --- a/modules/monitoring/application/views/scripts/show/components/command.phtml +++ b/modules/monitoring/application/views/scripts/show/components/command.phtml @@ -3,24 +3,32 @@ $parts = explode('!', $object->check_command); $command = array_shift($parts); -?> - translate('Command') ?> - - escape($command) ?> - passive_checks_enabled): ?> - getType() === $object::TYPE_HOST): ?> - icon('reply'); ?> translate('Process check result'); ?> - - icon('reply'); ?> translate('Process check result'); ?> - - +?> + + + translate('Command') ?> + + escape($command) ?> + hasPermission('monitoring/command/schedule-check') && $object->passive_checks_enabled): ?> + getType() === $object::TYPE_HOST) { + $processCheckResult = $this->href( + 'monitoring/host/process-check-result', + array('host' => $object->getName()) + ); + } else { + $processCheckResult = $this->href( + 'monitoring/service/process-check-result', + array('host' => $object->getHost()->getName(), 'service' => $object->getName()) + ); + } ?> + + icon('reply') ?> + translate('Process check result') ?> + + + + \n %s\n %s\n\n"; diff --git a/modules/monitoring/application/views/scripts/show/components/comments.phtml b/modules/monitoring/application/views/scripts/show/components/comments.phtml index 07968dfc8..a6503a70b 100644 --- a/modules/monitoring/application/views/scripts/show/components/comments.phtml +++ b/modules/monitoring/application/views/scripts/show/components/comments.phtml @@ -1,26 +1,27 @@ translate('Comments') ?> - getType() === $object::TYPE_HOST) { - $addCommentLink = $this->href( - 'monitoring/host/add-comment', - array('host' => $object->getName()) - ); - } else { - $addCommentLink = $this->href( - 'monitoring/service/add-comment', - array('host' => $object->getHost()->getName(), 'service' => $object->getName()) - ); - } - + hasPermission('monitoring/command/comment/add')) { + /** @type \Icinga\Module\Monitoring\Object\MonitoredObject $object */ + if ($object->getType() === $object::TYPE_HOST) { + $addCommentLink = $this->href( + 'monitoring/host/add-comment', + array('host' => $object->getName()) + ); + } else { + $addCommentLink = $this->href( + 'monitoring/service/add-comment', + array('host' => $object->getHost()->getName(), 'service' => $object->getName()) + ); + } ?> - - icon('comment') ?> translate('Add comment') ?> + + icon('comment') ?> + translate('Add comment') ?> + @@ -28,16 +29,12 @@ foreach ($object->comments as $comment) { // Ticket hook sample - $text = $this->tickets ? preg_replace_callback( + $commentText = $this->tickets ? preg_replace_callback( $this->tickets->getPattern(), array($this->tickets, 'createLink'), $this->escape($comment->comment) ) : $this->escape($comment->comment); - - $form = clone $delCommentForm; - $form->populate(array('comment_id' => $comment->id)); - ?> @@ -46,14 +43,19 @@ foreach ($object->comments as $comment) {
- (type) ?>): + populate(array('comment_id' => $comment->id)); + echo $delCommentForm; + } ?> + (type) ?>): - ', $text) ?> +
- + diff --git a/modules/monitoring/application/views/scripts/show/components/downtime.phtml b/modules/monitoring/application/views/scripts/show/components/downtime.phtml index 2cd7147f1..4aa1e21c1 100644 --- a/modules/monitoring/application/views/scripts/show/components/downtime.phtml +++ b/modules/monitoring/application/views/scripts/show/components/downtime.phtml @@ -1,25 +1,27 @@ translate('Downtimes') ?> - getType() === $object::TYPE_HOST) { - $scheduleDowntimeLink = $this->href( - 'monitoring/host/schedule-downtime', - array('host' => $object->getName()) - ); - } else { - $scheduleDowntimeLink = $this->href( - 'monitoring/service/schedule-downtime', - array('host' => $object->getHost()->getName(), 'service' => $object->getName()) - ); - } + hasPermission('monitoring/command/downtime/schedule')) { + /** @type \Icinga\Module\Monitoring\Object\MonitoredObject $object */ + if ($object->getType() === $object::TYPE_HOST) { + $scheduleDowntimeLink = $this->href( + 'monitoring/host/schedule-downtime', + array('host' => $object->getName()) + ); + } else { + $scheduleDowntimeLink = $this->href( + 'monitoring/service/schedule-downtime', + array('host' => $object->getHost()->getName(), 'service' => $object->getName()) + ); + } ?> - - icon('plug') ?> translate('Schedule downtime') ?> + + icon('plug') ?> + translate('Schedule downtime') ?> + @@ -27,15 +29,12 @@ foreach ($object->downtimes as $downtime) { // Ticket hook sample - $text = $this->tickets ? preg_replace_callback( + $commentText = $this->tickets ? preg_replace_callback( $this->tickets->getPattern(), array($this->tickets, 'createLink'), $this->escape($downtime->comment) ) : $this->escape($downtime->comment); - $form = clone $delDowntimeForm; - $form->populate(array('downtime_id' => $downtime->id)); - if ((bool) $downtime->is_in_effect) { $state = 'in downtime since ' . $this->timeSince($downtime->start); } else { @@ -54,14 +53,19 @@ foreach ($object->downtimes as $downtime) {
- + populate(array('downtime_id' => $downtime->id)); + echo $delDowntimeForm; + } ?> + - ', $text) ?> +
- + diff --git a/modules/monitoring/application/views/scripts/show/components/header.phtml b/modules/monitoring/application/views/scripts/show/components/header.phtml index ccf7d2d5e..8ba84da43 100644 --- a/modules/monitoring/application/views/scripts/show/components/header.phtml +++ b/modules/monitoring/application/views/scripts/show/components/header.phtml @@ -3,37 +3,44 @@ use Icinga\Module\Monitoring\Object\Host; use Icinga\Module\Monitoring\Object\Service; -$showService = $object->getType() === $object::TYPE_SERVICE; +$isService = $object->getType() === $object::TYPE_SERVICE; ?> -compact): ?> + +compact): ?> + - - + + + + + + + - - - - - - -
> - host_state, true)); ?>
- prefixedTimeSince($object->host_last_state_change, true) ?> -
escape($object->host_name) ?>host_address && $object->host_address !== $object->host_name): ?> -
escape($object->host_address) ?> - -
> + host_state, true); ?>
+ prefixedTimeSince($object->host_last_state_change, true) ?> +
+ escape($object->host_display_name) ?> + host_display_name !== $object->host_name): ?> + (escape($object->host_name) ?>) + + host_address && $object->host_address !== $object->host_name): ?> +
+ escape($object->host_address) ?> + +
+ service_state, true); ?>
+ prefixedTimeSince($object->service_last_state_change, true) ?> +
+ translate('Service') ?>: escape($object->service_display_name) ?> + service_display_name !== $object->service_description): ?> + (escape($object->service_description) ?>) + + render('show/components/statusIcons.phtml') ?> +
- service_state, true)); ?>
- prefixedTimeSince($object->service_last_state_change, true) ?> -
translate('Service') ?>: escape($object->service_description) ?> - - render('show/components/statusIcons.phtml') ?> - -
 
diff --git a/modules/monitoring/application/views/scripts/show/components/hostgroups.phtml b/modules/monitoring/application/views/scripts/show/components/hostgroups.phtml index 40db3e5c4..165df627a 100644 --- a/modules/monitoring/application/views/scripts/show/components/hostgroups.phtml +++ b/modules/monitoring/application/views/scripts/show/components/hostgroups.phtml @@ -4,7 +4,7 @@ if (empty($object->hostgroups)) return; $list = array(); foreach ($object->hostgroups as $name => $alias) { - $list[] = $this->qlink($alias, 'monitoring/list/services', array( + $list[] = $this->qlink($alias, 'monitoring/list/hosts', array( 'hostgroup' => $name )); } diff --git a/modules/monitoring/application/views/scripts/show/components/hostservicesummary.phtml b/modules/monitoring/application/views/scripts/show/components/hostservicesummary.phtml index 3c603786a..641dd026a 100644 --- a/modules/monitoring/application/views/scripts/show/components/hostservicesummary.phtml +++ b/modules/monitoring/application/views/scripts/show/components/hostservicesummary.phtml @@ -17,7 +17,7 @@ $currentUrl = Url::fromRequest()->without('limit')->getRelativeUrl(); $object->stats->services_ok, $selfUrl, array('service_state' => 0), - array('title' => sprintf($this->translate('Services with state %s'), strtoupper($this->translate('ok')))) + array('title' => sprintf($this->translate('Services with state %s'), $this->translate('OK'))) ) ?> 'critical', 3 => 'unknown', 1 => 'warning') as $stateId => $ $object->stats->$unhandled, $selfUrl, $paramsUnhandled, - array('title' => sprintf($this->translate('Unhandled services with state %s'), strtoupper($this->translate($state)))) + array('title' => sprintf($this->translate('Unhandled services with state %s'), $this->translate(strtoupper($state)))) ); } if ($object->stats->$handled) { @@ -65,7 +65,7 @@ foreach (array(2 => 'critical', 3 => 'unknown', 1 => 'warning') as $stateId => $ $object->stats->$handled, $selfUrl, $paramsHandled, - array('title' => sprintf($this->translate('Handled services with state %s'), strtoupper($this->translate($state)))) + array('title' => sprintf($this->translate('Handled services with state %s'), $this->translate(strtoupper($state)))) ); if ($object->stats->$unhandled) { echo "\n"; @@ -81,7 +81,7 @@ foreach (array(2 => 'critical', 3 => 'unknown', 1 => 'warning') as $stateId => $ $object->stats->services_pending, $selfUrl, array('service_state' => 99), - array('title' => sprintf($this->translate('Services with state %s'), strtoupper($this->translate('pending')))) + array('title' => sprintf($this->translate('Services with state %s'), $this->translate('PENDING'))) ) ?> diff --git a/modules/monitoring/application/views/scripts/show/history.phtml b/modules/monitoring/application/views/scripts/show/history.phtml index 5b922d4a0..40fb15363 100644 --- a/modules/monitoring/application/views/scripts/show/history.phtml +++ b/modules/monitoring/application/views/scripts/show/history.phtml @@ -92,21 +92,13 @@ function contactsLink($match, $view) { $msg = '[ ' . $event->attempt . '/' . $event->max_attempts . ' ] ' . $this->escape($event->output); $stateClass = $isService ? Service::getStateText($event->state) : Host::getStateText($event->state); $icon = 'attention-alt'; - $title = strtoupper( - $isService - ? Service::getStateText($event->state) - : Host::getStateText($event->state) - ); + $title = $isService ? Service::getStateText($event->state) : Host::getStateText($event->state); break; case 'soft_state': $icon = 'spinner'; $msg = '[ ' . $event->attempt . '/' . $event->max_attempts . ' ] ' . $this->escape($event->output); $stateClass = $isService ? Service::getStateText($event->state) : Host::getStateText($event->state); - $title = strtoupper( - $isService - ? Service::getStateText($event->state) - : Host::getStateText($event->state) - ); + $title = $isService ? Service::getStateText($event->state) : Host::getStateText($event->state); break; case 'dt_start': $icon = 'downtime_start'; @@ -136,19 +128,24 @@ $output = $this->tickets ? preg_replace_callback( ?> - qlink( - $this->escape($event->service_description), - 'monitoring/show/service', - array( - 'host' => $event->host_name, - 'service' => $event->service_description) - ) : $this->escape($event->service_description); ?> translate('on') . ' ' . $this->escape($event->host_name); ?> + translate('%s on %s', 'Service running on host'), + $hostContext ? $this->qlink( + $this->escape($event->service_display_name), + 'monitoring/show/service', + array( + 'host' => $event->host_name, + 'service' => $event->service_description + ) + ) : $this->escape($event->service_display_name), + $event->host_display_name + ) ?> escape($event->host_name); ?>
- icon($icon, $title); ?> + icon($icon, $title); ?> escape($msg) ?>
diff --git a/modules/monitoring/configuration.php b/modules/monitoring/configuration.php index d61e32858..72df4e73f 100644 --- a/modules/monitoring/configuration.php +++ b/modules/monitoring/configuration.php @@ -1,53 +1,68 @@ providePermission( 'monitoring/command/*', $this->translate('Allow all commands') ); -$this->providePermission( - 'monitoring/command/schedule*', - $this->translate('Allow all scheduling checks and downtimes') -); $this->providePermission( 'monitoring/command/schedule-check', $this->translate('Allow scheduling host and service checks') ); -$this->providePermission( - 'monitoring/command/schedule-downtime', - $this->translate('Allow scheduling host and service downtimes') -); $this->providePermission( 'monitoring/command/acknowledge-problem', $this->translate('Allow acknowledging host and service problems') ); -$this->providePermission( - 'monitoring/command/add-comment', - $this->translate('Allow commenting on hosts and services') -); -$this->providePermission( - 'monitoring/command/remove*', - $this->translate('Allow removing problem acknowledgements, host and service comments and downtimes') -); $this->providePermission( 'monitoring/command/remove-acknowledgement', $this->translate('Allow removing problem acknowledgements') ); $this->providePermission( - 'monitoring/command/remove-comment', - $this->translate('Allow removing host and service comments') + 'monitoring/command/comment/*', + $this->translate('Allow adding and deleting host and service comments') ); $this->providePermission( - 'monitoring/command/remove-downtime', - $this->translate('Allow removing host and service downtimes') + 'monitoring/command/comment/add', + $this->translate('Allow commenting on hosts and services') +); +$this->providePermission( + 'monitoring/command/comment/delete', + $this->translate('Allow deleting host and service comments') +); +$this->providePermission( + 'monitoring/command/downtime/*', + $this->translate('Allow scheduling and deleting host and service downtimes') +); +$this->providePermission( + 'monitoring/command/downtime/schedule', + $this->translate('Allow scheduling host and service downtimes') +); +$this->providePermission( + 'monitoring/command/downtime/delete', + $this->translate('Allow deleting host and service downtimes') +); +$this->providePermission( + 'monitoring/command/process-check-result', + $this->translate('Allow processing host and service check results') +); +$this->providePermission( + 'monitoring/command/feature/program', + $this->translate('Allow processing commands for toggling features on a program-wide basis') +); +$this->providePermission( + 'monitoring/command/feature/object', + $this->translate('Allow processing commands for toggling features on host and service objects') ); $this->provideRestriction( - 'monitoring/filter', - $this->translate('Restrict views to the hosts and services that match the filter') + 'monitoring/hosts/filter', + $this->translate('Restrict hosts view to the hosts that match the filter') +); + +$this->provideRestriction( + 'monitoring/services/filter', + $this->translate('Restrict services view to the services that match the filter') ); $this->provideConfigTab('backends', array( @@ -127,22 +142,27 @@ $section->add($this->translate('Hostgroups'), array( 'url' => 'monitoring/list/hostgroups', 'priority' => 60 )); -$section->add($this->translate('Contactgroups'), array( - 'url' => 'monitoring/list/contactgroups', - 'priority' => 61 -)); -$section->add($this->translate('Downtimes'), array( - 'url' => 'monitoring/list/downtimes', - 'priority' => 71 -)); -$section->add($this->translate('Comments'), array( - 'url' => 'monitoring/list/comments?comment_type=(comment|ack)', - 'priority' => 70 -)); $section->add($this->translate('Contacts'), array( 'url' => 'monitoring/list/contacts', 'priority' => 70 )); +$section->add($this->translate('Contactgroups'), array( + 'url' => 'monitoring/list/contactgroups', + 'priority' => 70 +)); +$section->add($this->translate('Comments'), array( + 'url' => 'monitoring/list/comments?comment_type=(comment|ack)', + 'priority' => 80 +)); +$section->add($this->translate('Downtimes'), array( + 'url' => 'monitoring/list/downtimes', + 'priority' => 80 +)); +$section->add($this->translate('Notifications'), array( + 'url' => 'monitoring/list/notifications', + 'priority' => 80 +)); + /* * History Section diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommentQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommentQuery.php index 5145a96ad..a522d702e 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommentQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommentQuery.php @@ -23,6 +23,12 @@ class CommentQuery extends IdoQuery 'comment_service' => 'so.name2 COLLATE latin1_general_ci', 'service' => 'so.name2 COLLATE latin1_general_ci', // #7278, #7279 'comment_objecttype' => "CASE WHEN ho.object_id IS NOT NULL THEN 'host' ELSE CASE WHEN so.object_id IS NOT NULL THEN 'service' ELSE NULL END END", + ), + 'hosts' => array( + 'host_display_name' => 'CASE WHEN sh.display_name IS NOT NULL THEN sh.display_name ELSE h.display_name END' + ), + 'services' => array( + 'service_display_name' => 's.display_name' ) ); @@ -44,4 +50,29 @@ class CommentQuery extends IdoQuery ); $this->joinedVirtualTables = array('comments' => true); } + + protected function joinHosts() + { + $this->select->joinLeft( + array('h' => $this->prefix . 'hosts'), + 'h.host_object_id = ho.object_id', + array() + ); + return $this; + } + + protected function joinServices() + { + $this->select->joinLeft( + array('s' => $this->prefix . 'services'), + 's.service_object_id = so.object_id', + array() + ); + $this->select->joinLeft( + array('sh' => $this->prefix . 'hosts'), + 'sh.host_object_id = s.host_object_id', + array() + ); + return $this; + } } diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimeQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimeQuery.php index a53fd18e9..efc10f6a5 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimeQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/DowntimeQuery.php @@ -1,47 +1,41 @@ array( - 'downtime_author' => 'sd.author_name', - 'author' => 'sd.author_name', - 'downtime_comment' => 'sd.comment_data', - 'downtime_entry_time' => 'UNIX_TIMESTAMP(sd.entry_time)', - 'downtime_is_fixed' => 'sd.is_fixed', - 'downtime_is_flexible' => 'CASE WHEN sd.is_fixed = 0 THEN 1 ELSE 0 END', - 'downtime_triggered_by_id' => 'sd.triggered_by_id', - 'downtime_scheduled_start' => 'UNIX_TIMESTAMP(sd.scheduled_start_time)', - 'downtime_scheduled_end' => 'UNIX_TIMESTAMP(sd.scheduled_end_time)', - 'downtime_start' => "UNIX_TIMESTAMP(CASE WHEN UNIX_TIMESTAMP(sd.trigger_time) > 0 then sd.trigger_time ELSE sd.scheduled_start_time END)", - 'downtime_end' => 'CASE WHEN sd.is_fixed > 0 THEN UNIX_TIMESTAMP(sd.scheduled_end_time) ELSE UNIX_TIMESTAMP(sd.trigger_time) + sd.duration END', - 'downtime_duration' => 'sd.duration', - 'downtime_is_in_effect' => 'sd.is_in_effect', - 'downtime_internal_id' => 'sd.internal_downtime_id', - 'downtime_host' => 'CASE WHEN ho.name1 IS NULL THEN so.name1 ELSE ho.name1 END COLLATE latin1_general_ci', // #7278, #7279 - 'host' => 'CASE WHEN ho.name1 IS NULL THEN so.name1 ELSE ho.name1 END COLLATE latin1_general_ci', - 'downtime_service' => 'so.name2 COLLATE latin1_general_ci', - 'service' => 'so.name2 COLLATE latin1_general_ci', // #7278, #7279 - 'downtime_objecttype' => "CASE WHEN ho.object_id IS NOT NULL THEN 'host' ELSE CASE WHEN so.object_id IS NOT NULL THEN 'service' ELSE NULL END END", - 'downtime_host_state' => 'CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL THEN 99 ELSE hs.current_state END', - 'downtime_service_state' => 'CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL THEN 99 ELSE ss.current_state END' + 'downtime_author' => 'sd.author_name', + 'author' => 'sd.author_name', + 'downtime_comment' => 'sd.comment_data', + 'downtime_entry_time' => 'UNIX_TIMESTAMP(sd.entry_time)', + 'downtime_is_fixed' => 'sd.is_fixed', + 'downtime_is_flexible' => 'CASE WHEN sd.is_fixed = 0 THEN 1 ELSE 0 END', + 'downtime_triggered_by_id' => 'sd.triggered_by_id', + 'downtime_scheduled_start' => 'UNIX_TIMESTAMP(sd.scheduled_start_time)', + 'downtime_scheduled_end' => 'UNIX_TIMESTAMP(sd.scheduled_end_time)', + 'downtime_start' => "UNIX_TIMESTAMP(CASE WHEN UNIX_TIMESTAMP(sd.trigger_time) > 0 then sd.trigger_time ELSE sd.scheduled_start_time END)", + 'downtime_end' => 'CASE WHEN sd.is_fixed > 0 THEN UNIX_TIMESTAMP(sd.scheduled_end_time) ELSE UNIX_TIMESTAMP(sd.trigger_time) + sd.duration END', + 'downtime_duration' => 'sd.duration', + 'downtime_is_in_effect' => 'sd.is_in_effect', + 'downtime_internal_id' => 'sd.internal_downtime_id', + 'downtime_host' => 'CASE WHEN ho.name1 IS NULL THEN so.name1 ELSE ho.name1 END COLLATE latin1_general_ci', // #7278, #7279 + 'host' => 'CASE WHEN ho.name1 IS NULL THEN so.name1 ELSE ho.name1 END COLLATE latin1_general_ci', + 'downtime_service' => 'so.name2 COLLATE latin1_general_ci', + 'service' => 'so.name2 COLLATE latin1_general_ci', // #7278, #7279 + 'downtime_objecttype' => "CASE WHEN ho.object_id IS NOT NULL THEN 'host' ELSE CASE WHEN so.object_id IS NOT NULL THEN 'service' ELSE NULL END END", + 'downtime_host_state' => 'CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL THEN 99 ELSE hs.current_state END', + 'downtime_service_state' => 'CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL THEN 99 ELSE ss.current_state END' ), + 'hosts' => array( + 'host_display_name' => 'CASE WHEN sh.display_name IS NOT NULL THEN sh.display_name ELSE h.display_name END' + ), + 'services' => array( + 'service_display_name' => 's.display_name' + ) ); - /** - * Join with scheduleddowntime - */ protected function joinBaseTables() { $this->select->from( @@ -70,4 +64,29 @@ class DowntimeQuery extends IdoQuery ); $this->joinedVirtualTables = array('downtime' => true); } + + protected function joinHosts() + { + $this->select->joinLeft( + array('h' => $this->prefix . 'hosts'), + 'h.host_object_id = ho.object_id', + array() + ); + return $this; + } + + protected function joinServices() + { + $this->select->joinLeft( + array('s' => $this->prefix . 'services'), + 's.service_object_id = so.object_id', + array() + ); + $this->select->joinLeft( + array('sh' => $this->prefix . 'hosts'), + 'sh.host_object_id = s.host_object_id', + array() + ); + return $this; + } } diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/EventHistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/EventHistoryQuery.php index 2d5a0a2d8..2896f9536 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/EventHistoryQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/EventHistoryQuery.php @@ -1,11 +1,9 @@ array( - 'cnt_notification' => "SUM(CASE eh.type WHEN 'notify' THEN 1 ELSE 0 END)", - 'cnt_hard_state' => "SUM(CASE eh.type WHEN 'hard_state' THEN 1 ELSE 0 END)", - 'cnt_soft_state' => "SUM(CASE eh.type WHEN 'hard_state' THEN 1 ELSE 0 END)", - 'cnt_downtime_start' => "SUM(CASE eh.type WHEN 'dt_start' THEN 1 ELSE 0 END)", - 'cnt_downtime_end' => "SUM(CASE eh.type WHEN 'dt_end' THEN 1 ELSE 0 END)", - 'host' => 'eho.name1 COLLATE latin1_general_ci', - 'service' => 'eho.name2 COLLATE latin1_general_ci', - 'host_name' => 'eho.name1 COLLATE latin1_general_ci', - 'service_description' => 'eho.name2 COLLATE latin1_general_ci', - 'object_type' => 'eh.object_type', - 'timestamp' => 'eh.timestamp', - 'state' => 'eh.state', - 'attempt' => 'eh.attempt', - 'max_attempts' => 'eh.max_attempts', - 'output' => 'eh.output', // we do not want long_output - 'type' => 'eh.type', - 'service_host_name' => 'eho.name1 COLLATE latin1_general_ci', - 'service_description' => 'eho.name2 COLLATE latin1_general_ci' + 'cnt_notification' => "SUM(CASE eh.type WHEN 'notify' THEN 1 ELSE 0 END)", + 'cnt_hard_state' => "SUM(CASE eh.type WHEN 'hard_state' THEN 1 ELSE 0 END)", + 'cnt_soft_state' => "SUM(CASE eh.type WHEN 'hard_state' THEN 1 ELSE 0 END)", + 'cnt_downtime_start' => "SUM(CASE eh.type WHEN 'dt_start' THEN 1 ELSE 0 END)", + 'cnt_downtime_end' => "SUM(CASE eh.type WHEN 'dt_end' THEN 1 ELSE 0 END)", + 'host' => 'eho.name1 COLLATE latin1_general_ci', + 'service' => 'eho.name2 COLLATE latin1_general_ci', + 'host_name' => 'eho.name1 COLLATE latin1_general_ci', + 'service_description' => 'eho.name2 COLLATE latin1_general_ci', + 'object_type' => 'eh.object_type', + 'timestamp' => 'eh.timestamp', + 'state' => 'eh.state', + 'attempt' => 'eh.attempt', + 'max_attempts' => 'eh.max_attempts', + 'output' => 'eh.output', // we do not want long_output + 'type' => 'eh.type', + 'service_host_name' => 'eho.name1 COLLATE latin1_general_ci' ), 'hostgroups' => array( - 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci', + 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci', ), + 'hosts' => array( + 'host_display_name' => 'CASE WHEN sh.display_name IS NOT NULL THEN sh.display_name ELSE h.display_name END' + ), + 'services' => array( + 'service_display_name' => 's.display_name' + ) ); protected $useSubqueryCount = true; @@ -84,20 +87,20 @@ class EventHistoryQuery extends IdoQuery public function addFilter(Filter $filter) { - foreach ($this->subQueries as $sub) { - $sub->applyFilter(clone $filter); - } - return $this; + foreach ($this->subQueries as $sub) { + $sub->applyFilter(clone $filter); + } + return $this; } - public function where($condition, $value = null) - { - $this->requireColumn($condition); - foreach ($this->subQueries as $sub) { - $sub->where($condition, $value); - } - return $this; - } + public function where($condition, $value = null) + { + $this->requireColumn($condition); + foreach ($this->subQueries as $sub) { + $sub->where($condition, $value); + } + return $this; + } protected function joinHostgroups() { @@ -117,4 +120,28 @@ class EventHistoryQuery extends IdoQuery return $this; } + protected function joinHosts() + { + $this->select->joinLeft( + array('h' => $this->prefix . 'hosts'), + 'h.host_object_id = eho.object_id', + array() + ); + return $this; + } + + protected function joinServices() + { + $this->select->joinLeft( + array('s' => $this->prefix . 'services'), + 's.service_object_id = eho.object_id', + array() + ); + $this->select->joinLeft( + array('sh' => $this->prefix . 'hosts'), + 'sh.host_object_id = s.host_object_id', + array() + ); + return $this; + } } diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/GroupsummaryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/GroupsummaryQuery.php index 20e98fc63..53c1d7ed7 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/GroupsummaryQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/GroupsummaryQuery.php @@ -11,7 +11,7 @@ class GroupSummaryQuery extends IdoQuery protected $useSubqueryCount = true; protected $columnMap = array( - 'hoststatussummary' => array( + 'hoststatussummary' => array( 'hosts_up' => 'SUM(CASE WHEN object_type = \'host\' AND state = 0 THEN 1 ELSE 0 END)', 'hosts_unreachable' => 'SUM(CASE WHEN object_type = \'host\' AND state = 2 THEN 1 ELSE 0 END)', 'hosts_unreachable_handled' => 'SUM(CASE WHEN object_type = \'host\' AND state = 2 AND acknowledged + in_downtime != 0 THEN 1 ELSE 0 END)', @@ -20,21 +20,22 @@ class GroupSummaryQuery extends IdoQuery 'hosts_down_handled' => 'SUM(CASE WHEN object_type = \'host\' AND state = 1 AND acknowledged + in_downtime != 0 THEN 1 ELSE 0 END)', 'hosts_down_unhandled' => 'SUM(CASE WHEN object_type = \'host\' AND state = 1 AND acknowledged + in_downtime = 0 THEN 1 ELSE 0 END)', 'hosts_pending' => 'SUM(CASE WHEN object_type = \'host\' AND state = 99 THEN 1 ELSE 0 END)', - 'hostgroup' => 'hostgroup' + 'hostgroup' => 'hostgroup', + 'hostgroup_alias' => 'hostgroup_alias' ), - 'servicestatussummary' => array( - 'services_total' => 'SUM(CASE WHEN object_type = \'service\' THEN 1 ELSE 0 END)', - 'services_ok' => 'SUM(CASE WHEN object_type = \'service\' AND state = 0 THEN 1 ELSE 0 END)', - 'services_pending' => 'SUM(CASE WHEN object_type = \'service\' AND state = 99 THEN 1 ELSE 0 END)', - 'services_warning' => 'SUM(CASE WHEN object_type = \'service\' AND state = 1 THEN 1 ELSE 0 END)', - 'services_warning_handled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 1 AND acknowledged + in_downtime + host_state > 0 THEN 1 ELSE 0 END)', - 'services_critical' => 'SUM(CASE WHEN object_type = \'service\' AND state = 2 THEN 1 ELSE 0 END)', - 'services_critical_handled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 2 AND acknowledged + in_downtime + host_state > 0 THEN 1 ELSE 0 END)', - 'services_unknown' => 'SUM(CASE WHEN object_type = \'service\' AND state = 3 THEN 1 ELSE 0 END)', - 'services_unknown_handled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 3 AND acknowledged + in_downtime + host_state > 0 THEN 1 ELSE 0 END)', - 'services_warning_unhandled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 1 AND acknowledged + in_downtime + host_state = 0 THEN 1 ELSE 0 END)', - 'services_critical_unhandled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 2 AND acknowledged + in_downtime + host_state = 0 THEN 1 ELSE 0 END)', - 'services_unknown_unhandled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 3 AND acknowledged + in_downtime + host_state = 0 THEN 1 ELSE 0 END)', + 'servicestatussummary' => array( + 'services_total' => 'SUM(CASE WHEN object_type = \'service\' THEN 1 ELSE 0 END)', + 'services_ok' => 'SUM(CASE WHEN object_type = \'service\' AND state = 0 THEN 1 ELSE 0 END)', + 'services_pending' => 'SUM(CASE WHEN object_type = \'service\' AND state = 99 THEN 1 ELSE 0 END)', + 'services_warning' => 'SUM(CASE WHEN object_type = \'service\' AND state = 1 THEN 1 ELSE 0 END)', + 'services_warning_handled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 1 AND acknowledged + in_downtime + host_state > 0 THEN 1 ELSE 0 END)', + 'services_critical' => 'SUM(CASE WHEN object_type = \'service\' AND state = 2 THEN 1 ELSE 0 END)', + 'services_critical_handled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 2 AND acknowledged + in_downtime + host_state > 0 THEN 1 ELSE 0 END)', + 'services_unknown' => 'SUM(CASE WHEN object_type = \'service\' AND state = 3 THEN 1 ELSE 0 END)', + 'services_unknown_handled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 3 AND acknowledged + in_downtime + host_state > 0 THEN 1 ELSE 0 END)', + 'services_warning_unhandled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 1 AND acknowledged + in_downtime + host_state = 0 THEN 1 ELSE 0 END)', + 'services_critical_unhandled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 2 AND acknowledged + in_downtime + host_state = 0 THEN 1 ELSE 0 END)', + 'services_unknown_unhandled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 3 AND acknowledged + in_downtime + host_state = 0 THEN 1 ELSE 0 END)', 'services_severity' => 'MAX(CASE WHEN object_type = \'service\' THEN severity ELSE 0 END)', 'services_ok_last_state_change' => 'MAX(CASE WHEN object_type = \'service\' AND state = 0 THEN state_change ELSE 0 END)', 'services_pending_last_state_change' => 'MAX(CASE WHEN object_type = \'service\' AND state = 99 THEN state_change ELSE 0 END)', @@ -44,7 +45,8 @@ class GroupSummaryQuery extends IdoQuery 'services_warning_last_state_change_unhandled' => 'MAX(CASE WHEN object_type = \'service\' AND state = 1 AND acknowledged + in_downtime + host_state = 0 THEN state_change ELSE 0 END)', 'services_critical_last_state_change_unhandled' => 'MAX(CASE WHEN object_type = \'service\' AND state = 2 AND acknowledged + in_downtime + host_state = 0 THEN state_change ELSE 0 END)', 'services_unknown_last_state_change_unhandled' => 'MAX(CASE WHEN object_type = \'service\' AND state = 3 AND acknowledged + in_downtime + host_state = 0 THEN state_change ELSE 0 END)', - 'servicegroup' => 'servicegroup' + 'servicegroup' => 'servicegroup', + 'servicegroup_alias' => 'servicegroup_alias' ) ); @@ -52,14 +54,17 @@ class GroupSummaryQuery extends IdoQuery { $columns = array( 'object_type', - 'host_state', + 'host_state' ); - // Prepend group column since we'll use columns index 0 later for grouping if (in_array('servicegroup', $this->desiredColumns)) { - array_unshift($columns, 'servicegroup'); + $columns[] = 'servicegroup'; + $columns[] = 'servicegroup_alias'; + $groupColumns = array('servicegroup', 'servicegroup_alias'); } else { - array_unshift($columns, 'hostgroup'); + $columns[] = 'hostgroup'; + $columns[] = 'hostgroup_alias'; + $groupColumns = array('hostgroup', 'hostgroup_alias'); } $hosts = $this->createSubQuery( 'Hoststatus', @@ -75,6 +80,7 @@ class GroupSummaryQuery extends IdoQuery $hosts->group(array( 'sgo.name1', 'ho.object_id', + 'sg.alias', 'state', 'acknowledged', 'in_downtime', @@ -92,16 +98,8 @@ class GroupSummaryQuery extends IdoQuery 'severity' => 'service_severity' ) ); - - $groupColumn = 'hostgroup'; - - if (in_array('servicegroup', $this->desiredColumns)) { - $groupColumn = 'servicegroup'; - } - $union = $this->db->select()->union(array($hosts, $services), Zend_Db_Select::SQL_UNION_ALL); - $this->select->from(array('statussummary' => $union), array())->group(array($groupColumn)); - + $this->select->from(array('statussummary' => $union), array())->group($groupColumns); $this->joinedVirtualTables = array( 'servicestatussummary' => true, 'hoststatussummary' => true diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HoststatusQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HoststatusQuery.php index e9903ec86..7cca01d31 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HoststatusQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HoststatusQuery.php @@ -84,10 +84,12 @@ class HoststatusQuery extends IdoQuery END' ), 'hostgroups' => array( - 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci', + 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci', + 'hostgroup_alias' => 'hg.alias' ), 'servicegroups' => array( - 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci', + 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci', + 'servicegroup_alias' => 'sg.alias' ), 'contactgroups' => array( 'contactgroup' => 'contactgroup', diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php index 4682487d2..cf6968ea3 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php @@ -292,7 +292,6 @@ abstract class IdoQuery extends DbQuery $mapped = $this->getMappedField($field); if ($mapped === null) { return stripos($field, 'UNIX_TIMESTAMP') !== false; - return false; } return stripos($mapped, 'UNIX_TIMESTAMP') !== false; } @@ -324,6 +323,11 @@ abstract class IdoQuery extends DbQuery foreach ($columns as $key => & $value) { $value = preg_replace('/ COLLATE .+$/', '', $value); $value = preg_replace('/inet_aton\(([[:word:].]+)\)/i', '$1::inet - \'0.0.0.0\'', $value); + $value = preg_replace( + '/UNIX_TIMESTAMP(\((?>[^()]|(?-1))*\))/i', + 'CASE WHEN ($1 < \'1970-01-03 00:00:00+00\'::timestamp with time zone) THEN 0 ELSE UNIX_TIMESTAMP($1) END', + $value + ); } } } diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/NotificationQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/NotificationQuery.php index 00b6957b8..3181eebbf 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/NotificationQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/NotificationQuery.php @@ -1,41 +1,37 @@ array( - 'notification_output' => 'n.output', - 'notification_start_time' => 'UNIX_TIMESTAMP(n.start_time)', - 'notification_state' => 'n.state', - 'notification_object_id' => 'n.object_id' + 'notification_output' => 'n.output', + 'notification_start_time' => 'UNIX_TIMESTAMP(n.start_time)', + 'notification_state' => 'n.state', + 'notification_object_id' => 'n.object_id' ), 'objects' => array( - 'host' => 'o.name1', - 'service' => 'o.name2' + 'host' => 'o.name1', + 'service' => 'o.name2' ), 'contact' => array( - 'notification_contact' => 'c_o.name1', - 'contact_object_id' => 'c_o.object_id' + 'notification_contact' => 'c_o.name1', + 'contact_object_id' => 'c_o.object_id' ), 'command' => array( - 'notification_command' => 'cmd_o.name1' + 'notification_command' => 'cmd_o.name1' ), 'acknowledgement' => array( 'acknowledgement_entry_time' => 'UNIX_TIMESTAMP(a.entry_time)', 'acknowledgement_author_name' => 'a.author_name', 'acknowledgement_comment_data' => 'a.comment_data' + ), + 'hosts' => array( + 'host_display_name' => 'CASE WHEN sh.display_name IS NOT NULL THEN sh.display_name ELSE h.display_name END' + ), + 'services' => array( + 'service_display_name' => 's.display_name' ) ); @@ -110,4 +106,29 @@ class NotificationQuery extends IdoQuery array() ); } + + protected function joinHosts() + { + $this->select->joinLeft( + array('h' => $this->prefix . 'hosts'), + 'h.host_object_id = o.object_id', + array() + ); + return $this; + } + + protected function joinServices() + { + $this->select->joinLeft( + array('s' => $this->prefix . 'services'), + 's.service_object_id = o.object_id', + array() + ); + $this->select->joinLeft( + array('sh' => $this->prefix . 'hosts'), + 'sh.host_object_id = s.host_object_id', + array() + ); + return $this; + } } diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ProgramstatusQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ProgramstatusQuery.php index e6abd4f77..989c2b698 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ProgramstatusQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ProgramstatusQuery.php @@ -11,17 +11,27 @@ class ProgramstatusQuery extends IdoQuery { protected $columnMap = array( 'programstatus' => array( - 'id' => 'programstatus_id', - 'status_update_time' => 'UNIX_TIMESTAMP(status_update_time)', - 'program_start_time' => 'UNIX_TIMESTAMP(program_start_time)', - 'program_end_time' => 'UNIX_TIMESTAMP(program_end_time)', - 'is_currently_running' => 'is_currently_running', + 'id' => 'programstatus_id', + 'status_update_time' => 'UNIX_TIMESTAMP(programstatus.status_update_time)', + 'program_start_time' => 'UNIX_TIMESTAMP(programstatus.program_start_time)', + 'program_end_time' => 'UNIX_TIMESTAMP(programstatus.program_end_time)', + 'is_currently_running' => 'CASE WHEN (programstatus.is_currently_running = 0) + THEN + 0 + ELSE + CASE WHEN (UNIX_TIMESTAMP(programstatus.status_update_time) + 60 > UNIX_TIMESTAMP(NOW())) + THEN + 1 + ELSE + 0 + END + END', 'process_id' => 'process_id', 'daemon_mode' => 'daemon_mode', - 'last_command_check' => 'UNIX_TIMESTAMP(last_command_check)', - 'last_log_rotation' => 'UNIX_TIMESTAMP(last_log_rotation)', + 'last_command_check' => 'UNIX_TIMESTAMP(programstatus.last_command_check)', + 'last_log_rotation' => 'UNIX_TIMESTAMP(programstatus.last_log_rotation)', 'notifications_enabled' => 'notifications_enabled', - 'disable_notif_expire_time' => 'UNIX_TIMESTAMP(disable_notif_expire_time)', + 'disable_notif_expire_time' => 'UNIX_TIMESTAMP(programstatus.disable_notif_expire_time)', 'active_service_checks_enabled' => 'active_service_checks_enabled', 'passive_service_checks_enabled' => 'passive_service_checks_enabled', 'active_host_checks_enabled' => 'active_host_checks_enabled', diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatehistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatehistoryQuery.php index e979cdc08..dfa81b1ef 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatehistoryQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatehistoryQuery.php @@ -1,6 +1,4 @@ 0, - 'hard_state' => 1, + 'hard_state' => 1 ); protected $columnMap = array( 'statehistory' => array( - 'raw_timestamp' => 'sh.state_time', - 'timestamp' => 'UNIX_TIMESTAMP(sh.state_time)', - 'state_time' => 'sh.state_time', - 'object_id' => 'sho.object_id', - 'type' => "(CASE WHEN sh.state_type = 1 THEN 'hard_state' ELSE 'soft_state' END)", - 'state' => 'sh.state', - 'state_type' => 'sh.state_type', - 'output' => 'sh.output', - 'attempt' => 'sh.current_check_attempt', - 'max_attempts' => 'sh.max_check_attempts', - - 'host' => 'sho.name1 COLLATE latin1_general_ci', - 'service' => 'sho.name2 COLLATE latin1_general_ci', - 'host_name' => 'sho.name1 COLLATE latin1_general_ci', - 'service_description' => 'sho.name2 COLLATE latin1_general_ci', - 'service_host_name' => 'sho.name1 COLLATE latin1_general_ci', - 'service_description' => 'sho.name2 COLLATE latin1_general_ci', - 'object_type' => "CASE WHEN sho.objecttype_id = 1 THEN 'host' ELSE 'service' END" + 'raw_timestamp' => 'sh.state_time', + 'timestamp' => 'UNIX_TIMESTAMP(sh.state_time)', + 'state_time' => 'sh.state_time', + 'object_id' => 'sho.object_id', + 'type' => "(CASE WHEN sh.state_type = 1 THEN 'hard_state' ELSE 'soft_state' END)", + 'state' => 'sh.state', + 'state_type' => 'sh.state_type', + 'output' => 'sh.output', + 'attempt' => 'sh.current_check_attempt', + 'max_attempts' => 'sh.max_check_attempts', + 'host' => 'sho.name1 COLLATE latin1_general_ci', + 'host_name' => 'sho.name1 COLLATE latin1_general_ci', + 'service' => 'sho.name2 COLLATE latin1_general_ci', + 'service_description' => 'sho.name2 COLLATE latin1_general_ci', + 'service_host_name' => 'sho.name1 COLLATE latin1_general_ci', + 'object_type' => "CASE WHEN sho.objecttype_id = 1 THEN 'host' ELSE 'service' END" ) ); diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php index e390aa114..0cc807ac8 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php @@ -118,7 +118,6 @@ class StatusQuery extends IdoQuery 'host_modified_host_attributes' => 'hs.modified_host_attributes', 'host_event_handler' => 'hs.event_handler', - 'host_check_command' => 'hs.check_command', 'host_normal_check_interval' => 'hs.normal_check_interval', 'host_retry_check_interval' => 'hs.retry_check_interval', 'host_check_timeperiod_object_id' => 'hs.check_timeperiod_object_id', @@ -161,10 +160,12 @@ class StatusQuery extends IdoQuery END' ), 'hostgroups' => array( - 'hostgroup' => 'hgo.name1', + 'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci', + 'hostgroup_alias' => 'hg.alias' ), 'servicegroups' => array( - 'servicegroup' => 'sgo.name1', + 'servicegroup' => 'sgo.name1 COLLATE latin1_general_ci', + 'servicegroup_alias' => 'sg.alias' ), 'services' => array( 'service_host_name' => 'so.name1 COLLATE latin1_general_ci', @@ -368,7 +369,7 @@ class StatusQuery extends IdoQuery case 'CASE WHEN ss.current_state = 0 THEN 0 ELSE 1 END': if ($sign !== '=') break; - + if ($expression) { return 'ss.current_state > 0'; } else { @@ -518,12 +519,14 @@ class StatusQuery extends IdoQuery protected function joinServiceproblemsummary() { $sub = new Zend_Db_Expr('(SELECT' - . ' SUM(CASE WHEN (ss.problem_has_been_acknowledged + ss.scheduled_downtime_depth) > 0 THEN 0 ELSE 1 END) AS unhandled_services_count,' - . ' SUM(CASE WHEN (ss.problem_has_been_acknowledged + ss.scheduled_downtime_depth) > 0 THEN 1 ELSE 0 END) AS handled_services_count,' + . ' SUM(CASE WHEN (ss.problem_has_been_acknowledged + ss.scheduled_downtime_depth + COALESCE(hs.current_state, 0)) > 0 THEN 0 ELSE 1 END) AS unhandled_services_count,' + . ' SUM(CASE WHEN (ss.problem_has_been_acknowledged + ss.scheduled_downtime_depth + COALESCE(hs.current_state, 0)) > 0 THEN 1 ELSE 0 END) AS handled_services_count,' . ' s.host_object_id FROM icinga_servicestatus ss' . ' JOIN icinga_services s' . ' ON s.service_object_id = ss.service_object_id' . ' AND ss.current_state > 0' + . ' JOIN icinga_hoststatus hs' + . ' ON hs.host_object_id = s.host_object_id' . ' GROUP BY s.host_object_id)'); $this->select->joinLeft( array('sps' => $sub), diff --git a/modules/monitoring/library/Monitoring/Backend/MonitoringBackend.php b/modules/monitoring/library/Monitoring/Backend/MonitoringBackend.php index c8f75f540..d165f1252 100644 --- a/modules/monitoring/library/Monitoring/Backend/MonitoringBackend.php +++ b/modules/monitoring/library/Monitoring/Backend/MonitoringBackend.php @@ -145,7 +145,7 @@ class MonitoringBackend implements Selectable, Queryable, ConnectionInterface $this->type = lcfirst(substr($class, 0, -7)); } else { throw new ProgrammingError( - '%s is not a valid monitoring backend class name', + '%s is not a valid monitoring backend class name', $class ); } @@ -251,7 +251,7 @@ class MonitoringBackend implements Selectable, Queryable, ConnectionInterface * @param string $name * @param array $columns * - * @return DataView + * @return \Icinga\Module\Monitoring\DataView\DataView */ public function from($name, array $columns = null) { diff --git a/modules/monitoring/library/Monitoring/Controller.php b/modules/monitoring/library/Monitoring/Controller.php index 32bafb8b2..f294e9a2e 100644 --- a/modules/monitoring/library/Monitoring/Controller.php +++ b/modules/monitoring/library/Monitoring/Controller.php @@ -4,9 +4,11 @@ namespace Icinga\Module\Monitoring; +use Icinga\Data\Filter\Filter; +use Icinga\Data\Filterable; +use Icinga\File\Csv; use Icinga\Web\Controller\ModuleActionController; use Icinga\Web\Url; -use Icinga\File\Csv; /** * Base class for all monitoring action controller @@ -60,5 +62,21 @@ class Controller extends ModuleActionController exit; } } + + /** + * Apply a restriction on the given data view + * + * @param string $restriction The name of restriction + * @param Filterable $filterable The filterable to restrict + * + * @return Filterable The filterable + */ + protected function applyRestriction($restriction, Filterable $view) + { + foreach ($this->getRestrictions($restriction) as $filter) { + $view->applyFilter(Filter::fromQueryString($filter)); + } + return $view; + } } diff --git a/modules/monitoring/library/Monitoring/DataView/Comment.php b/modules/monitoring/library/Monitoring/DataView/Comment.php index 4d62fd27c..4cd11e1a1 100644 --- a/modules/monitoring/library/Monitoring/DataView/Comment.php +++ b/modules/monitoring/library/Monitoring/DataView/Comment.php @@ -29,6 +29,8 @@ class Comment extends DataView 'comment_service', 'host', 'service', + 'host_display_name', + 'service_display_name' ); } @@ -43,13 +45,20 @@ class Comment extends DataView 'comment_timestamp' => array( 'order' => self::SORT_DESC ), - 'comment_host' => array( + 'host_display_name' => array( 'columns' => array( - 'comment_host', - 'comment_service' + 'host_display_name', + 'service_display_name' ), 'order' => self::SORT_ASC ), + 'service_display_name' => array( + 'columns' => array( + 'service_display_name', + 'host_display_name' + ), + 'order' => self::SORT_ASC + ) ); } } diff --git a/modules/monitoring/library/Monitoring/DataView/DataView.php b/modules/monitoring/library/Monitoring/DataView/DataView.php index 1fdd8b4f9..da48f31c3 100644 --- a/modules/monitoring/library/Monitoring/DataView/DataView.php +++ b/modules/monitoring/library/Monitoring/DataView/DataView.php @@ -83,6 +83,7 @@ abstract class DataView implements Browsable, Countable, Filterable, Sortable public function dump() { + $this->order(); return $this->query->dump(); } @@ -354,12 +355,21 @@ abstract class DataView implements Browsable, Countable, Filterable, Sortable return $this; } + /** + * @deprecated(EL): Only use DataView::applyFilter() for applying filter because all other functions are missing + * column validation. Filter::matchAny() for the IdoQuery (or the DbQuery or the SimpleQuery I didn't have a look) + * is required for the filter to work properly. + */ public function setFilter(Filter $filter) { $this->query->setFilter($filter); return $this; } + /** + * @deprecated(EL): Only use DataView::applyFilter() for applying filter because all other functions are missing + * column validation. + */ public function addFilter(Filter $filter) { $this->query->addFilter(clone($filter)); diff --git a/modules/monitoring/library/Monitoring/DataView/Downtime.php b/modules/monitoring/library/Monitoring/DataView/Downtime.php index e075d658c..681608b17 100644 --- a/modules/monitoring/library/Monitoring/DataView/Downtime.php +++ b/modules/monitoring/library/Monitoring/DataView/Downtime.php @@ -32,7 +32,9 @@ class Downtime extends DataView 'downtime_host', 'downtime_service', 'downtime_host_state', - 'downtime_service_state' + 'downtime_service_state', + 'host_display_name', + 'service_display_name' ); } @@ -40,18 +42,29 @@ class Downtime extends DataView { return array( 'downtime_is_in_effect' => array( + 'columns' => array( + 'downtime_is_in_effect', + 'downtime_scheduled_start' + ), 'order' => self::SORT_DESC ), 'downtime_start' => array( 'order' => self::SORT_DESC ), - 'downtime_host' => array( + 'host_display_name' => array( 'columns' => array( - 'downtime_host', - 'downtime_service' + 'host_display_name', + 'service_display_name' ), 'order' => self::SORT_ASC ), + 'service_display_name' => array( + 'columns' => array( + 'service_display_name', + 'host_display_name' + ), + 'order' => self::SORT_ASC + ) ); } } diff --git a/modules/monitoring/library/Monitoring/DataView/EventHistory.php b/modules/monitoring/library/Monitoring/DataView/EventHistory.php index 09779b27d..f13815aae 100644 --- a/modules/monitoring/library/Monitoring/DataView/EventHistory.php +++ b/modules/monitoring/library/Monitoring/DataView/EventHistory.php @@ -1,6 +1,4 @@ array( - 'columns' => array('timestamp'), - 'order' => 'DESC' + 'columns' => array('timestamp'), + 'order' => 'DESC' ) ); } diff --git a/modules/monitoring/library/Monitoring/DataView/Groupsummary.php b/modules/monitoring/library/Monitoring/DataView/Groupsummary.php index 7fe6d2e6d..a4736e47c 100644 --- a/modules/monitoring/library/Monitoring/DataView/Groupsummary.php +++ b/modules/monitoring/library/Monitoring/DataView/Groupsummary.php @@ -15,7 +15,9 @@ class Groupsummary extends DataView { return array( 'servicegroup', + 'servicegroup_alias', 'hostgroup', + 'hostgroup_alias', 'hosts_up', 'hosts_unreachable', 'hosts_unreachable_handled', @@ -47,7 +49,7 @@ class Groupsummary extends DataView 'services_unknown_last_state_change_unhandled' ); } - + public function getSortRules() { return array( diff --git a/modules/monitoring/library/Monitoring/DataView/HostStatus.php b/modules/monitoring/library/Monitoring/DataView/HostStatus.php index e9b5b60dd..86bff52bf 100644 --- a/modules/monitoring/library/Monitoring/DataView/HostStatus.php +++ b/modules/monitoring/library/Monitoring/DataView/HostStatus.php @@ -24,6 +24,7 @@ class HostStatus extends DataView return array( 'host', 'host_name', + 'host_display_name', 'host_alias', 'host_address', 'host_state', @@ -90,7 +91,7 @@ class HostStatus extends DataView public function getSortRules() { return array( - 'host_name' => array( + 'host_display_name' => array( 'order' => self::SORT_ASC ), 'host_address' => array( diff --git a/modules/monitoring/library/Monitoring/DataView/Notification.php b/modules/monitoring/library/Monitoring/DataView/Notification.php index 6156a5f15..7f6fd238f 100644 --- a/modules/monitoring/library/Monitoring/DataView/Notification.php +++ b/modules/monitoring/library/Monitoring/DataView/Notification.php @@ -20,7 +20,9 @@ class Notification extends DataView 'notification_start_time', 'notification_contact', 'notification_output', - 'notification_command' + 'notification_command', + 'host_display_name', + 'service_display_name' ); } diff --git a/modules/monitoring/library/Monitoring/DataView/ServiceStatus.php b/modules/monitoring/library/Monitoring/DataView/ServiceStatus.php index 9edcabc87..e7e2accb2 100644 --- a/modules/monitoring/library/Monitoring/DataView/ServiceStatus.php +++ b/modules/monitoring/library/Monitoring/DataView/ServiceStatus.php @@ -25,6 +25,7 @@ class ServiceStatus extends DataView { return array( 'host_name', + 'host_display_name', 'host_state', 'host_state_type', 'host_last_state_change', @@ -123,22 +124,12 @@ class ServiceStatus extends DataView public function getSortRules() { return array( - 'host_name' => array( + 'service_severity' => array( 'columns' => array( - 'service_host_name', - 'service_description' + 'service_severity', + 'service_last_state_change' ), - 'order' => self::SORT_ASC - ), - 'host_address' => array( - 'columns' => array( - 'host_ipv4', - 'service_description' - ), - 'order' => self::SORT_ASC - ), - 'host_last_state_change' => array( - 'order' => self::SORT_ASC + 'order' => self::SORT_DESC ), 'host_severity' => array( 'columns' => array( @@ -147,12 +138,19 @@ class ServiceStatus extends DataView ), 'order' => self::SORT_ASC ), - 'service_severity' => array( + 'host_display_name' => array( 'columns' => array( - 'service_severity', - 'service_last_state_change', + 'host_display_name', + 'service_display_name' ), - 'order' => self::SORT_DESC + 'order' => self::SORT_ASC + ), + 'host_address' => array( + 'columns' => array( + 'host_ipv4', + 'service_display_name' + ), + 'order' => self::SORT_ASC ) ); } diff --git a/modules/monitoring/library/Monitoring/MonitoringWizard.php b/modules/monitoring/library/Monitoring/MonitoringWizard.php index 0ac4c7f63..d7a3671a4 100644 --- a/modules/monitoring/library/Monitoring/MonitoringWizard.php +++ b/modules/monitoring/library/Monitoring/MonitoringWizard.php @@ -4,6 +4,7 @@ namespace Icinga\Module\Monitoring; +use Icinga\Application\Icinga; use Icinga\Web\Form; use Icinga\Web\Wizard; use Icinga\Web\Request; @@ -11,7 +12,6 @@ use Icinga\Module\Setup\Setup; use Icinga\Module\Setup\SetupWizard; use Icinga\Module\Setup\Requirements; use Icinga\Module\Setup\Utils\MakeDirStep; -use Icinga\Module\Setup\Utils\EnableModuleStep; use Icinga\Module\Setup\Forms\SummaryPage; use Icinga\Module\Monitoring\Forms\Setup\WelcomePage; use Icinga\Module\Monitoring\Forms\Setup\BackendPage; @@ -36,7 +36,7 @@ class MonitoringWizard extends Wizard implements SetupWizard $this->addPage(new LivestatusResourcePage()); $this->addPage(new InstancePage()); $this->addPage(new SecurityPage()); - $this->addPage(new SummaryPage()); + $this->addPage(new SummaryPage(array('name' => 'setup_monitoring_summary'))); } /** @@ -46,7 +46,7 @@ class MonitoringWizard extends Wizard implements SetupWizard { if ($page->getName() === 'setup_requirements') { $page->setRequirements($this->getRequirements()); - } elseif ($page->getName() === 'setup_summary') { + } elseif ($page->getName() === 'setup_monitoring_summary') { $page->setSummary($this->getSetup()->getSummary()); $page->setSubjectTitle(mt('monitoring', 'the monitoring module', 'setup.summary.subject')); } elseif ( @@ -78,23 +78,7 @@ class MonitoringWizard extends Wizard implements SetupWizard $skip = $backendData['type'] !== 'livestatus'; } - if ($skip) { - if ($this->hasPageData($newPage->getName())) { - $pageData = & $this->getPageData(); - unset($pageData[$newPage->getName()]); - } - - $pages = $this->getPages(); - if ($this->getDirection() === static::FORWARD) { - $nextPage = $pages[array_search($newPage, $pages, true) + 1]; - $newPage = $this->getNewPage($nextPage->getName(), $newPage); - } else { // $this->getDirection() === static::BACKWARD - $previousPage = $pages[array_search($newPage, $pages, true) - 1]; - $newPage = $this->getNewPage($previousPage->getName(), $newPage); - } - } - - return $newPage; + return $skip ? $this->skipPage($newPage) : $newPage; } /** @@ -124,7 +108,7 @@ class MonitoringWizard extends Wizard implements SetupWizard $pageData = $this->getPageData(); $setup = new Setup(); - $setup->addStep(new MakeDirStep(array($this->getConfigDir() . '/modules/monitoring'), 0775)); + $setup->addStep(new MakeDirStep(array(Icinga::app()->getConfigDir() . '/modules/monitoring'), 2770)); $setup->addStep( new BackendStep(array( @@ -147,8 +131,6 @@ class MonitoringWizard extends Wizard implements SetupWizard )) ); - $setup->addStep(new EnableModuleStep('monitoring')); - return $setup; } @@ -159,21 +141,4 @@ class MonitoringWizard extends Wizard implements SetupWizard { return new Requirements(); } - - /** - * Return the configuration directory of Icinga Web 2 - * - * @return string - */ - protected function getConfigDir() - { - if (array_key_exists('ICINGAWEB_CONFIGDIR', $_SERVER)) { - $configDir = $_SERVER['ICINGAWEB_CONFIGDIR']; - } else { - $configDir = '/etc/icingaweb'; - } - - $canonical = realpath($configDir); - return $canonical ? $canonical : $configDir; - } } diff --git a/modules/monitoring/library/Monitoring/Object/Host.php b/modules/monitoring/library/Monitoring/Object/Host.php index fd08f6a20..8f7df07cb 100644 --- a/modules/monitoring/library/Monitoring/Object/Host.php +++ b/modules/monitoring/library/Monitoring/Object/Host.php @@ -47,7 +47,7 @@ class Host extends MonitoredObject public $prefix = 'host_'; /** - * Host name + * Hostname * * @var string */ @@ -63,8 +63,8 @@ class Host extends MonitoredObject /** * Create a new host * - * @param MonitoringBackend $backend Backend to fetch host information from - * @param string $host Host name + * @param MonitoringBackend $backend Backend to fetch host information from + * @param string $host Hostname */ public function __construct(MonitoringBackend $backend, $host) { @@ -73,7 +73,7 @@ class Host extends MonitoredObject } /** - * Get the host name + * Get the hostname * * @return string */ @@ -91,6 +91,7 @@ class Host extends MonitoredObject { $columns = array( 'host_name', + 'host_display_name', 'host_alias', 'host_address', 'host_state', @@ -172,16 +173,16 @@ class Host extends MonitoredObject $translate = (bool) $translate; switch ((int) $state) { case self::STATE_UP: - $text = $translate ? mt('monitoring', 'up') : 'up'; + $text = $translate ? mt('monitoring', 'UP') : 'up'; break; case self::STATE_DOWN: - $text = $translate ? mt('monitoring', 'down') : 'down'; + $text = $translate ? mt('monitoring', 'DOWN') : 'down'; break; case self::STATE_UNREACHABLE: - $text = $translate ? mt('monitoring', 'unreachable') : 'unreachable'; + $text = $translate ? mt('monitoring', 'UNREACHABLE') : 'unreachable'; break; case self::STATE_PENDING: - $text = $translate ? mt('monitoring', 'pending') : 'pending'; + $text = $translate ? mt('monitoring', 'PENDING') : 'pending'; break; default: throw new InvalidArgumentException('Invalid host state \'%s\'', $state); diff --git a/modules/monitoring/library/Monitoring/Object/MonitoredObject.php b/modules/monitoring/library/Monitoring/Object/MonitoredObject.php index 4be004d99..213cf47b8 100644 --- a/modules/monitoring/library/Monitoring/Object/MonitoredObject.php +++ b/modules/monitoring/library/Monitoring/Object/MonitoredObject.php @@ -7,13 +7,15 @@ namespace Icinga\Module\Monitoring\Object; use InvalidArgumentException; use Icinga\Application\Config; use Icinga\Exception\InvalidPropertyException; +use Icinga\Data\Filter\Filter; +use Icinga\Data\Filterable; use Icinga\Module\Monitoring\Backend\MonitoringBackend; use Icinga\Web\UrlParams; /** * A monitored Icinga object, i.e. host or service */ -abstract class MonitoredObject +abstract class MonitoredObject implements Filterable { /** * Type host @@ -116,6 +118,13 @@ abstract class MonitoredObject */ protected $stats; + /** + * Filter + * + * @type Filter + */ + protected $filter; + /** * Create a monitored object, i.e. host or service * @@ -133,6 +142,35 @@ abstract class MonitoredObject */ abstract protected function getDataView(); + public function applyFilter(Filter $filter) + { + $this->getFilter()->addFilter($filter); + return $this; + } + + public function setFilter(Filter $filter) + { + // Left out on purpose. Interface is deprecated. + } + + public function getFilter() + { + if ($this->filter === null) { + $this->filter = Filter::matchAny(); + } + return $this->filter; + } + + public function addFilter(Filter $filter) + { + // Left out on purpose. Interface is deprecated. + } + + public function where($condition, $value = null) + { + // Left out on purpose. Interface is deprecated. + } + /** * Fetch the object's properties * @@ -140,7 +178,7 @@ abstract class MonitoredObject */ public function fetch() { - $this->properties = $this->getDataView()->getQuery()->fetchRow(); + $this->properties = $this->getDataView()->applyFilter($this->getFilter())->getQuery()->fetchRow(); if ($this->properties === false) { return false; } @@ -408,7 +446,9 @@ abstract class MonitoredObject $eventHistory = $this->backend->select()->from('eventHistory', array( 'object_type', 'host_name', + 'host_display_name', 'service_description', + 'service_display_name', 'timestamp', 'state', 'attempt', @@ -421,7 +461,7 @@ abstract class MonitoredObject if ($this->type === self::TYPE_SERVICE) { $eventHistory->where('service_description', $this->service_description); } - $this->eventhistory = $eventHistory->getQuery(); + $this->eventhistory = $eventHistory; return $this; } diff --git a/modules/monitoring/library/Monitoring/Object/Service.php b/modules/monitoring/library/Monitoring/Object/Service.php index 6d5245f0d..870ff78ba 100644 --- a/modules/monitoring/library/Monitoring/Object/Service.php +++ b/modules/monitoring/library/Monitoring/Object/Service.php @@ -68,9 +68,9 @@ class Service extends MonitoredObject /** * Create a new service * - * @param MonitoringBackend $backend Backend to fetch service information from - * @param string $host Host name the service is running on - * @param string $service Service name + * @param MonitoringBackend $backend Backend to fetch service information from + * @param string $host Hostname the service is running on + * @param string $service Service name */ public function __construct(MonitoringBackend $backend, $host, $service) { @@ -108,6 +108,7 @@ class Service extends MonitoredObject { return $this->backend->select()->from('serviceStatus', array( 'host_name', + 'host_display_name', 'host_state', 'host_state_type', 'host_last_state_change', @@ -213,19 +214,19 @@ class Service extends MonitoredObject $translate = (bool) $translate; switch ((int) $state) { case self::STATE_OK: - $text = $translate ? mt('monitoring', 'ok') : 'ok'; + $text = $translate ? mt('monitoring', 'OK') : 'ok'; break; case self::STATE_WARNING: - $text = $translate ? mt('monitoring', 'warning') : 'warning'; + $text = $translate ? mt('monitoring', 'WARNING') : 'warning'; break; case self::STATE_CRITICAL: - $text = $translate ? mt('monitoring', 'critical') : 'critical'; + $text = $translate ? mt('monitoring', 'CRITICAL') : 'critical'; break; case self::STATE_UNKNOWN: - $text = $translate ? mt('monitoring', 'unknown') : 'unknown'; + $text = $translate ? mt('monitoring', 'UNKNOWN') : 'unknown'; break; case self::STATE_PENDING: - $text = $translate ? mt('monitoring', 'pending') : 'pending'; + $text = $translate ? mt('monitoring', 'PENDING') : 'pending'; break; default: throw new InvalidArgumentException('Invalid service state \'%s\'', $state); diff --git a/modules/monitoring/library/Monitoring/Plugin/Perfdata.php b/modules/monitoring/library/Monitoring/Plugin/Perfdata.php index 6af3cde17..f51801192 100644 --- a/modules/monitoring/library/Monitoring/Plugin/Perfdata.php +++ b/modules/monitoring/library/Monitoring/Plugin/Perfdata.php @@ -4,10 +4,18 @@ namespace Icinga\Module\Monitoring\Plugin; +use Icinga\Util\Format; use InvalidArgumentException; +use Icinga\Exception\ProgrammingError; +use Icinga\Web\Widget\Chart\InlinePie; +use Zend_Controller_Front; class Perfdata { + const PERFDATA_OK = 'ok'; + const PERFDATA_WARNING = 'warning'; + const PERFDATA_CRITICAL = 'critical'; + /** * The performance data value being parsed * @@ -53,6 +61,8 @@ class Perfdata /** * The WARNING threshold * + * TODO: Should be parsed Range-Object instead of string + * * @var string */ protected $warningThreshold; @@ -60,6 +70,8 @@ class Perfdata /** * The CRITICAL threshold * + * TODO: Should be parsed Range-Object instead of string + * * @var string */ protected $criticalThreshold; @@ -159,6 +171,16 @@ class Perfdata return $this->unit === 'c'; } + /** + * Returns whether it is possible to display a visual representation + * + * @return bool True when the perfdata is visualizable + */ + public function isVisualizable() + { + return isset($this->minValue) && isset($this->maxValue) && isset($this->value); + } + /** * Return this perfomance data's label */ @@ -223,7 +245,7 @@ class Perfdata /** * Return the minimum value or null if it is not available * - * @return null|float + * @return null|string */ public function getMinimumValue() { @@ -247,7 +269,7 @@ class Perfdata */ public function __toString() { - return sprintf(strpos($this->label, ' ') === false ? '%s=%s' : "'%s'=%s", $this->label, $this->perfdataValue); + return $this->formatLabel(); } /** @@ -278,10 +300,8 @@ class Perfdata $this->minValue = self::convert($parts[3], $this->unit); } case 3: - // TODO(#6123): Tresholds have the same UOM and need to be converted as well! $this->criticalThreshold = trim($parts[2]) ? trim($parts[2]) : null; case 2: - // TODO(#6123): Tresholds have the same UOM and need to be converted as well! $this->warningThreshold = trim($parts[1]) ? trim($parts[1]) : null; } } @@ -316,4 +336,122 @@ class Perfdata } } } + + protected function calculatePieChartData() + { + $rawValue = $this->getValue(); + $minValue = $this->getMinimumValue() !== null ? $this->getMinimumValue() : 0; + $maxValue = $this->getMaximumValue(); + $usedValue = ($rawValue - $minValue); + $unusedValue = ($maxValue - $minValue) - $usedValue; + + $warningThreshold = $this->convert($this->warningThreshold, $this->unit); + $criticalThreshold = $this->convert($this->criticalThreshold, $this->unit); + + $gray = $unusedValue; + $green = $orange = $red = 0; + + $pieState = self::PERFDATA_OK; + if ($warningThreshold > $criticalThreshold) { + // inverted threshold parsing OK > warning > critical + if (isset($warningThreshold) && $this->value <= $warningThreshold) { + $pieState = self::PERFDATA_WARNING; + } + if (isset($criticalThreshold) && $this->value <= $criticalThreshold) { + $pieState = self::PERFDATA_CRITICAL; + } + + } else { + // TODO: Use standard perfdata range format to decide the state #8194 + + // regular threshold parsing OK < warning < critical + if (isset($warningThreshold) && $rawValue > $warningThreshold) { + $pieState = self::PERFDATA_WARNING; + } + if (isset($criticalThreshold) && $rawValue > $criticalThreshold) { + $pieState = self::PERFDATA_CRITICAL; + } + } + + switch ($pieState) { + case self::PERFDATA_OK: + $green = $usedValue; + break; + + case self::PERFDATA_CRITICAL: + $red = $usedValue; + break; + + case self::PERFDATA_WARNING: + $orange = $usedValue; + break; + } + + return array($green, $orange, $red, $gray); + } + + + public function asInlinePie() + { + if (! $this->isVisualizable()) { + throw new ProgrammingError('Cannot calculate piechart data for unvisualizable perfdata entry.'); + } + + $data = $this->calculatePieChartData(); + $pieChart = new InlinePie($data, $this); + $pieChart->setColors(array('#44bb77', '#ffaa44', '#ff5566', '#ddccdd')); + $pieChart->setSparklineClass('sparkline-perfdata'); + + if (Zend_Controller_Front::getInstance()->getRequest()->isXmlHttpRequest()) { + $pieChart->disableNoScript(); + } + return $pieChart; + } + + /** + * Format the given value depending on the currently used unit + */ + protected function format($value) + { + if ($this->isPercentage()) { + return (string)$value . '%'; + } + if ($this->isBytes()) { + return Format::bytes($value); + } + if ($this->isSeconds()) { + return Format::seconds($value); + } + return number_format($value, 2); + } + + /** + * Format the title string that represents this perfdata set + * + * @param bool $html + * + * @return stringS + */ + public function formatLabel($html = false) + { + return sprintf( + $html ? t('%s %s (%s%%)') : t('%s %s (%s%%)'), + htmlspecialchars($this->getLabel()), + $this->format($this->value), + number_format($this->getPercentage(), 2) + ); + } + + public function toArray() + { + $parts = array( + $this->getLabel(), + 'value' => $this->format($this->getvalue()), + 'min' => isset($this->minValue) && !$this->isPercentage() ? $this->format($this->minValue) : '', + 'max' => isset($this->maxValue) && !$this->isPercentage() ? $this->format($this->maxValue) : '', + 'warn' => isset($this->warningThreshold) ? $this->format(self::convert($this->warningThreshold, $this->unit)) : '', + 'crit' => isset($this->criticalThreshold) ? $this->format(self::convert($this->criticalThreshold, $this->unit)) : '' + ); + return $parts; + } } diff --git a/modules/monitoring/library/Monitoring/Web/Controller/MonitoredObjectController.php b/modules/monitoring/library/Monitoring/Web/Controller/MonitoredObjectController.php index 7ee73d575..5de11e1e2 100644 --- a/modules/monitoring/library/Monitoring/Web/Controller/MonitoredObjectController.php +++ b/modules/monitoring/library/Monitoring/Web/Controller/MonitoredObjectController.php @@ -1,11 +1,8 @@ setAutorefreshInterval(10); - $checkNowForm = new CheckNowCommandForm(); - $checkNowForm - ->setObjects($this->object) - ->handleRequest(); - $this->view->checkNowForm = $checkNowForm; + $auth = $this->Auth(); + if ($auth->hasPermission('monitoring/command/schedule-check')) { + $checkNowForm = new CheckNowCommandForm(); + $checkNowForm + ->setObjects($this->object) + ->handleRequest(); + $this->view->checkNowForm = $checkNowForm; + } if ( ! in_array((int) $this->object->state, array(0, 99))) { if ((bool) $this->object->acknowledged) { - $removeAckForm = new RemoveAcknowledgementCommandForm(); - $removeAckForm - ->setObjects($this->object) - ->handleRequest(); - $this->view->removeAckForm = $removeAckForm; - } else { - $ackForm = new AcknowledgeProblemCommandForm(); - $ackForm - ->setObjects($this->object) - ->handleRequest(); - $this->view->ackForm = $ackForm; + if ($auth->hasPermission('monitoring/command/remove-acknowledgement')) { + $removeAckForm = new RemoveAcknowledgementCommandForm(); + $removeAckForm + ->setObjects($this->object) + ->handleRequest(); + $this->view->removeAckForm = $removeAckForm; + } } } - if (count($this->object->comments) > 0) { + if (count($this->object->comments) > 0 && $auth->hasPermission('monitoring/command/comment/delete')) { $delCommentForm = new DeleteCommentCommandForm(); $delCommentForm ->setObjects($this->object) ->handleRequest(); $this->view->delCommentForm = $delCommentForm; } - if (count($this->object->downtimes > 0)) { + if (count($this->object->downtimes > 0) && $auth->hasPermission('monitoring/command/downtime/delete')) { $delDowntimeForm = new DeleteDowntimeCommandForm(); $delDowntimeForm ->setObjects($this->object) @@ -139,30 +134,20 @@ abstract class MonitoredObjectController extends Controller abstract public function scheduleDowntimeAction(); /** - * Remove a comment + * Delete a comment */ - public function removeCommentAction() + public function deleteCommentAction() { - /* - * TODO(el): This is here because monitoring/list/comments has buttons to remove comments. Because of the nature - * of an action, the form is accessible via GET which does not make much sense because the form requires - * us to populate the ID of the comment which is to be deleted. We may introduce a combo box for choosing - * the comment ID on GET or deny GET access. - */ + $this->assertHttpMethod('POST'); $this->handleCommandForm(new DeleteCommentCommandForm()); } /** - * Remove a downtime + * Delete a downtime */ public function deleteDowntimeAction() { - /* - * TODO(el): This is here because monitoring/list/downtimes has buttons to remove comments. Because of the - * nature of an action, the form is accessible via GET which does not make much sense because the form requires - * us to populate the ID of the downtime which is to be deleted. We may introduce a combo box for choosing - * the downtime ID on GET or deny GET access. - */ + $this->assertHttpMethod('POST'); $this->handleCommandForm(new DeleteDowntimeCommandForm()); } @@ -223,8 +208,6 @@ abstract class MonitoredObjectController extends Controller ) ); } - $tabs - ->extend(new OutputFormat()) - ->extend(new DashboardAction()); + $tabs->extend(new DashboardAction()); } } diff --git a/modules/monitoring/library/Monitoring/Web/Hook/TopBar.php b/modules/monitoring/library/Monitoring/Web/Hook/TopBar.php deleted file mode 100644 index 082a03c5b..000000000 --- a/modules/monitoring/library/Monitoring/Web/Hook/TopBar.php +++ /dev/null @@ -1,61 +0,0 @@ -getQuery()->fetchRow(); - - $serviceSummary = StatusSummaryView::fromRequest( - $request, - array( - 'services_ok', - 'services_critical_handled', - 'services_critical_unhandled', - 'services_warning_handled', - 'services_warning_unhandled', - 'services_unknown_handled', - 'services_unknown_unhandled', - 'services_pending' - ) - )->getQuery()->fetchRow(); - - return $this->getView()->partial( - 'layout/topbar.phtml', - 'monitoring', - array( - 'hostSummary' => $hostSummary, - 'serviceSummary' => $serviceSummary - ) - ); - } -} diff --git a/modules/monitoring/run.php b/modules/monitoring/run.php deleted file mode 100644 index 8f4ee1b67..000000000 --- a/modules/monitoring/run.php +++ /dev/null @@ -1,8 +0,0 @@ -registerHook( - 'TopBar', - 'Icinga\\Module\\Monitoring\\Web\\Hook\\TopBar' -); diff --git a/modules/setup/application/clicommands/ConfigCommand.php b/modules/setup/application/clicommands/ConfigCommand.php index 676572542..e63e770b8 100644 --- a/modules/setup/application/clicommands/ConfigCommand.php +++ b/modules/setup/application/clicommands/ConfigCommand.php @@ -12,56 +12,78 @@ use Icinga\Module\Setup\Webserver; class ConfigCommand extends Command { /** - * Create the configuration directory - * - * This command creates the configuration directory for Icinga Web 2. The `group' argument - * is mandatory and should be the groupname of the user your web server is running as. + * Create Icinga Web 2's configuration directory * * USAGE: * - * icingacli setup config createDirectory [options] + * icingacli setup config directory [options] * * OPTIONS: * - * --mode The access mode to use. Default is: 2770 - * --path The path to the configuration directory. If omitted the default is used. + * --config= Path to Icinga Web 2's configuration files [/etc/icingaweb2] + * + * --mode= The access mode to use [2770] + * + * --group= Owner group for the configuration directory [icingaweb2] * * EXAMPLES: * - * icingacli setup config createDirectory apache - * icingacli setup config createDirectory apache --mode 2775 - * icingacli setup config createDirectory apache --path /some/path + * icingacli setup config directory + * + * icingacli setup config directory --mode 2775 --config /opt/icingaweb2/etc */ - public function createDirectoryAction() + public function directoryAction() { - $group = $this->params->getStandalone(); - if ($group === null) { - $this->fail($this->translate('The `group\' argument is mandatory.')); - return false; + $configDir = trim($this->params->get('config', $this->app->getConfigDir())); + if (strlen($configDir) === 0) { + $this->fail($this->translate( + 'The argument --config expects a path to Icinga Web 2\'s configuration files' + )); } - $path = $this->params->get('path', $this->app->getConfigDir()); - if (file_exists($path)) { - printf($this->translate("Configuration directory already exists at: %s\n"), $path); - return true; + $group = trim($this->params->get('group', 'icingaweb2')); + if (strlen($group) === 0) { + $this->fail($this->translate( + 'The argument --group expects a owner group for the configuration directory' + )); } - $mode = octdec($this->params->get('mode', '2770')); - if (false === mkdir($path)) { - $this->fail(sprintf($this->translate('Unable to create path: %s'), $path)); - return false; + $mode = trim($this->params->get('mode', '2770')); + if (strlen($mode) === 0) { + $this->fail($this->translate( + 'The argument --mode expects an access mode for the configuration directory' + )); } - $old = umask(0); // Prevent $mode from being mangled by the system's umask ($old) - chmod($path, $mode); - umask($old); - - if (chgrp($path, $group) === false) { - $this->fail(sprintf($this->translate('Unable to change the group of "%s" to "%s".'), $path, $group)); - return false; + if (! file_exists($configDir) && ! @mkdir($configDir)) { + $e = error_get_last(); + $this->fail(sprintf( + $this->translate('Can\'t create configuration directory %s: %s'), + $configDir, + $e['message'] + )); } - printf($this->translate("Successfully created configuration directory at: %s\n"), $path); + if (! @chmod($configDir, octdec($mode))) { + $e = error_get_last(); + $this->fail(sprintf( + $this->translate('Can\'t change the mode of the configuration directory to %s: %s'), + $mode, + $e['message'] + )); + } + + if (! @chgrp($configDir, $group)) { + $e = error_get_last(); + $this->fail(sprintf( + $this->translate('Can\'t change the group of %s to %s: %s'), + $configDir, + $group, + $e['message'] + )); + } + + printf($this->translate('Successfully created configuration directory %s') . PHP_EOL, $configDir); } /** @@ -73,24 +95,23 @@ class ConfigCommand extends Command * * OPTIONS: * - * --path= The URL path to Icinga Web 2 [/icingaweb] + * --path= The URL path to Icinga Web 2 [/icingaweb2] * - * --root/--document-root= The directory from which the webserver will serve files [./public] + * --root/--document-root= The directory from which the webserver will serve files [/path/to/icingaweb2/public] * - * --config= Path to Icinga Web 2's configuration files [/etc/icingaweb] + * --config= Path to Icinga Web 2's configuration files [/etc/icingaweb2] * * --file= Write configuration to file [stdout] * - * * EXAMPLES: * - * icingacli setup config webserver apache + * icingacli setup config webserver apache * - * icingacli setup config webserver apache --path /icingaweb --document-root /usr/share/icingaweb/public --config=/etc/icingaweb + * icingacli setup config webserver apache --path /icingaweb2 --document-root /usr/share/icingaweb2/public --config=/etc/icingaweb2 * - * icingacli setup config webserver apache --file /etc/apache2/conf.d/icingaweb.conf + * icingacli setup config webserver apache --file /etc/apache2/conf.d/icingaweb2.conf * - * icingacli setup config webserver nginx + * icingacli setup config webserver nginx */ public function webserverAction() { @@ -102,18 +123,20 @@ class ConfigCommand extends Command } catch (ProgrammingError $e) { $this->fail($this->translate('Unknown type') . ': ' . $type); } - $urlPath = $this->params->get('path', $webserver->getUrlPath()); - if (! is_string($urlPath) || strlen(trim($urlPath)) === 0) { + $urlPath = trim($this->params->get('path', $webserver->getUrlPath())); + if (strlen($urlPath) === 0) { $this->fail($this->translate('The argument --path expects a URL path')); } - $documentRoot = $this->params->get('root', $this->params->get('document-root', $webserver->getDocumentRoot())); - if (! is_string($documentRoot) || strlen(trim($documentRoot)) === 0) { + $documentRoot = trim( + $this->params->get('root', $this->params->get('document-root', $webserver->getDocumentRoot())) + ); + if (strlen($documentRoot) === 0) { $this->fail($this->translate( 'The argument --root/--document-root expects a directory from which the webserver will serve files' )); } - $configDir = $this->params->get('config', $webserver->getConfigDir()); - if (! is_string($documentRoot) || strlen(trim($documentRoot)) === 0) { + $configDir = trim($this->params->get('config', $webserver->getConfigDir())); + if (strlen($configDir) === 0) { $this->fail($this->translate( 'The argument --config expects a path to Icinga Web 2\'s configuration files' )); diff --git a/modules/setup/application/clicommands/TokenCommand.php b/modules/setup/application/clicommands/TokenCommand.php index ff0229cfe..6f6e2b08e 100644 --- a/modules/setup/application/clicommands/TokenCommand.php +++ b/modules/setup/application/clicommands/TokenCommand.php @@ -22,11 +22,22 @@ class TokenCommand extends Command * * USAGE: * - * icingacli setup token show + * icingacli setup token show [options] + * + * OPTIONS: + * + * --config= Path to Icinga Web 2's configuration files [/etc/icingaweb2] */ public function showAction() { - $token = file_get_contents($this->app->getConfigDir() . '/setup.token'); + $configDir = $this->params->get('config', $this->app->getConfigDir()); + if (! is_string($configDir) || strlen(trim($configDir)) === 0) { + $this->fail($this->translate( + 'The argument --config expects a path to Icinga Web 2\'s configuration files' + )); + } + + $token = file_get_contents($configDir . '/setup.token'); if (! $token) { $this->fail( $this->translate('Nothing to show. Please create a new setup token using the generateToken action.') @@ -43,24 +54,35 @@ class TokenCommand extends Command * * USAGE: * - * icingacli setup token create + * icingacli setup token create [options] + * + * OPTIONS: + * + * --config= Path to Icinga Web 2's configuration files [/etc/icingaweb2] */ public function createAction() { + $configDir = $this->params->get('config', $this->app->getConfigDir()); + if (! is_string($configDir) || strlen(trim($configDir)) === 0) { + $this->fail($this->translate( + 'The argument --config expects a path to Icinga Web 2\'s configuration files' + )); + } + + $file = $configDir . '/setup.token'; + if (function_exists('openssl_random_pseudo_bytes')) { $token = bin2hex(openssl_random_pseudo_bytes(8)); } else { $token = substr(md5(mt_rand()), 16); } - $filepath = $this->app->getConfigDir() . '/setup.token'; - - if (false === file_put_contents($filepath, $token)) { - $this->fail(sprintf($this->translate('Cannot write setup token "%s" to disk.'), $filepath)); + if (false === file_put_contents($file, $token)) { + $this->fail(sprintf($this->translate('Cannot write setup token "%s" to disk.'), $file)); } - if (false === chmod($filepath, 0660)) { - $this->fail(sprintf($this->translate('Cannot change access mode of "%s" to %o.'), $filepath, 0660)); + if (! chmod($file, 0660)) { + $this->fail(sprintf($this->translate('Cannot change access mode of "%s" to %o.'), $file, 0660)); } printf($this->translate("The newly generated setup token is: %s\n"), $token); diff --git a/modules/setup/application/forms/AdminAccountPage.php b/modules/setup/application/forms/AdminAccountPage.php index 6ef791d4e..3b2e6ec9f 100644 --- a/modules/setup/application/forms/AdminAccountPage.php +++ b/modules/setup/application/forms/AdminAccountPage.php @@ -74,16 +74,15 @@ class AdminAccountPage extends Form $choices = array(); if ($this->backendConfig['backend'] !== 'db') { - $choices['by_name'] = mt('setup', 'By Name', 'setup.admin'); + $choices['by_name'] = $this->translate('By Name', 'setup.admin'); $this->addElement( 'text', 'by_name', array( 'required' => isset($formData['user_type']) && $formData['user_type'] === 'by_name', 'value' => $this->getUsername(), - 'label' => mt('setup', 'Username'), - 'description' => mt( - 'setup', + 'label' => $this->translate('Username'), + 'description' => $this->translate( 'Define the initial administrative account by providing a username that reflects' . ' a user created later or one that is authenticated using external mechanisms' ) @@ -94,21 +93,20 @@ class AdminAccountPage extends Form if ($this->backendConfig['backend'] === 'db' || $this->backendConfig['backend'] === 'ldap') { $users = $this->fetchUsers(); if (false === empty($users)) { - $choices['existing_user'] = mt('setup', 'Existing User'); + $choices['existing_user'] = $this->translate('Existing User'); $this->addElement( 'select', 'existing_user', array( 'required' => isset($formData['user_type']) && $formData['user_type'] === 'existing_user', - 'label' => mt('setup', 'Username'), + 'label' => $this->translate('Username'), 'description' => sprintf( - mt( - 'setup', + $this->translate( 'Choose a user reported by the %s backend as the initial administrative account', 'setup.admin' ), $this->backendConfig['backend'] === 'db' - ? mt('setup', 'database', 'setup.admin.authbackend') + ? $this->translate('database', 'setup.admin.authbackend') : 'LDAP' ), 'multiOptions' => array_combine($users, $users) @@ -118,16 +116,15 @@ class AdminAccountPage extends Form } if ($this->backendConfig['backend'] === 'db') { - $choices['new_user'] = mt('setup', 'New User'); + $choices['new_user'] = $this->translate('New User'); $required = isset($formData['user_type']) && $formData['user_type'] === 'new_user'; $this->addElement( 'text', 'new_user', array( 'required' => $required, - 'label' => mt('setup', 'Username'), - 'description' => mt( - 'setup', + 'label' => $this->translate('Username'), + 'description' => $this->translate( 'Enter the username to be used when creating an initial administrative account' ) ) @@ -137,8 +134,8 @@ class AdminAccountPage extends Form 'new_user_password', array( 'required' => $required, - 'label' => mt('setup', 'Password'), - 'description' => mt('setup', 'Enter the password to assign to the newly created account') + 'label' => $this->translate('Password'), + 'description' => $this->translate('Enter the password to assign to the newly created account') ) ); $this->addElement( @@ -146,8 +143,8 @@ class AdminAccountPage extends Form 'new_user_2ndpass', array( 'required' => $required, - 'label' => mt('setup', 'Repeat password'), - 'description' => mt('setup', 'Please repeat the password given above to avoid typing errors'), + 'label' => $this->translate('Repeat password'), + 'description' => $this->translate('Please repeat the password given above to avoid typing errors'), 'validators' => array( array('identical', false, array('new_user_password')) ) @@ -179,7 +176,7 @@ class AdminAccountPage extends Form 'note', 'title', array( - 'value' => mt('setup', 'Administration', 'setup.page.title'), + 'value' => $this->translate('Administration', 'setup.page.title'), 'decorators' => array( 'ViewHelper', array('HtmlTag', array('tag' => 'h2')) @@ -215,7 +212,7 @@ class AdminAccountPage extends Form } if ($data['user_type'] === 'new_user' && array_search($data['new_user'], $this->fetchUsers()) !== false) { - $this->getElement('new_user')->addError(mt('setup', 'Username already exists.')); + $this->getElement('new_user')->addError($this->translate('Username already exists.')); return false; } diff --git a/modules/setup/application/forms/AuthBackendPage.php b/modules/setup/application/forms/AuthBackendPage.php index fac2a7bbd..b123b5906 100644 --- a/modules/setup/application/forms/AuthBackendPage.php +++ b/modules/setup/application/forms/AuthBackendPage.php @@ -7,7 +7,7 @@ namespace Icinga\Module\Setup\Forms; use Icinga\Web\Form; use Icinga\Forms\Config\Authentication\DbBackendForm; use Icinga\Forms\Config\Authentication\LdapBackendForm; -use Icinga\Forms\Config\Authentication\AutologinBackendForm; +use Icinga\Forms\Config\Authentication\ExternalBackendForm; use Icinga\Data\ConfigObject; /** @@ -62,7 +62,7 @@ class AuthBackendPage extends Form 'note', 'title', array( - 'value' => mt('setup', 'Authentication Backend', 'setup.page.title'), + 'value' => $this->translate('Authentication Backend', 'setup.page.title'), 'decorators' => array( 'ViewHelper', array('HtmlTag', array('tag' => 'h2')) @@ -71,20 +71,17 @@ class AuthBackendPage extends Form ); if ($this->config['type'] === 'db') { - $note = mt( - 'setup', + $note = $this->translate( 'As you\'ve chosen to use a database for authentication all you need ' . 'to do now is defining a name for your first authentication backend.' ); } elseif ($this->config['type'] === 'ldap') { - $note = mt( - 'setup', + $note = $this->translate( 'Before you are able to authenticate using the LDAP connection defined earlier you need to' . ' provide some more information so that Icinga Web 2 is able to locate account details.' ); - } else { // if ($this->config['type'] === 'autologin' - $note = mt( - 'setup', + } else { // if ($this->config['type'] === 'external' + $note = $this->translate( 'You\'ve chosen to authenticate using a web server\'s mechanism so it may be necessary' . ' to adjust usernames before any permissions, restrictions, etc. are being applied.' ); @@ -106,13 +103,13 @@ class AuthBackendPage extends Form } elseif ($this->config['type'] === 'ldap') { $backendForm = new LdapBackendForm(); $backendForm->createElements($formData)->removeElement('resource'); - } else { // $this->config['type'] === 'autologin' - $backendForm = new AutologinBackendForm(); + } else { // $this->config['type'] === 'external' + $backendForm = new ExternalBackendForm(); $backendForm->createElements($formData); } $this->addElements($backendForm->getElements()); - $this->getElement('name')->setValue('icingaweb'); + $this->getElement('name')->setValue('icingaweb2'); } /** @@ -150,8 +147,8 @@ class AuthBackendPage extends Form 'order' => 2, 'ignore' => true, 'required' => true, - 'label' => mt('setup', 'Skip Validation'), - 'description' => mt('setup', 'Check this to not to validate authentication using this backend') + 'label' => $this->translate('Skip Validation'), + 'description' => $this->translate('Check this to not to validate authentication using this backend') ) ); } diff --git a/modules/setup/application/forms/AuthenticationPage.php b/modules/setup/application/forms/AuthenticationPage.php index 2a579e670..f51ef946a 100644 --- a/modules/setup/application/forms/AuthenticationPage.php +++ b/modules/setup/application/forms/AuthenticationPage.php @@ -29,19 +29,40 @@ class AuthenticationPage extends Form 'note', 'title', array( - 'value' => mt('setup', 'Authentication', 'setup.page.title'), + 'value' => $this->translate('Authentication', 'setup.page.title'), 'decorators' => array( 'ViewHelper', array('HtmlTag', array('tag' => 'h2')) ) ) ); + + if (isset($formData['type']) && $formData['type'] === 'external' && !isset($_SERVER['REMOTE_USER'])) { + $this->addElement( + 'note', + 'external_note', + array( + 'value' => $this->translate( + 'You\'re currently not authenticated using any of the web server\'s authentication ' + . 'mechanisms. Make sure you\'ll configure such, otherwise you\'ll not be able to ' + . 'log into Icinga Web 2.' + ), + 'decorators' => array( + 'ViewHelper', + array( + 'HtmlTag', + array('tag' => 'p', 'class' => 'icon-info info-box') + ) + ) + ) + ); + } + $this->addElement( 'note', 'description', array( - 'value' => mt( - 'setup', + 'value' => $this->translate( 'Please choose how you want to authenticate when accessing Icinga Web 2.' . ' Configuring backend specific details follows in a later step.' ) @@ -50,20 +71,21 @@ class AuthenticationPage extends Form $backendTypes = array(); if (Platform::hasMysqlSupport() || Platform::hasPostgresqlSupport()) { - $backendTypes['db'] = t('Database'); + $backendTypes['db'] = $this->translate('Database'); } if (Platform::extensionLoaded('ldap')) { $backendTypes['ldap'] = 'LDAP'; } - $backendTypes['autologin'] = t('Autologin'); + $backendTypes['external'] = $this->translate('External'); $this->addElement( 'select', 'type', array( 'required' => true, - 'label' => mt('setup', 'Authentication Type'), - 'description' => mt('setup', 'The type of authentication to use when accessing Icinga Web 2'), + 'autosubmit' => true, + 'label' => $this->translate('Authentication Type'), + 'description' => $this->translate('The type of authentication to use when accessing Icinga Web 2'), 'multiOptions' => $backendTypes ) ); diff --git a/modules/setup/application/forms/DatabaseCreationPage.php b/modules/setup/application/forms/DatabaseCreationPage.php index ec4a77ee1..be2974a52 100644 --- a/modules/setup/application/forms/DatabaseCreationPage.php +++ b/modules/setup/application/forms/DatabaseCreationPage.php @@ -90,7 +90,7 @@ class DatabaseCreationPage extends Form 'note', 'title', array( - 'value' => mt('setup', 'Database Setup', 'setup.page.title'), + 'value' => $this->translate('Database Setup', 'setup.page.title'), 'decorators' => array( 'ViewHelper', array('HtmlTag', array('tag' => 'h2')) @@ -101,8 +101,7 @@ class DatabaseCreationPage extends Form 'note', 'description', array( - 'value' => mt( - 'setup', + 'value' => $this->translate( 'It seems that either the database you defined earlier does not yet exist and cannot be created' . ' using the provided access credentials or the database does not have the required schema to ' . 'be operated by Icinga Web 2. Please provide appropriate access credentials to solve this.' @@ -116,16 +115,16 @@ class DatabaseCreationPage extends Form 'username', array( 'required' => false === $skipValidation, - 'label' => mt('setup', 'Username'), - 'description' => mt('setup', 'A user which is able to create databases and/or touch the database schema') + 'label' => $this->translate('Username'), + 'description' => $this->translate('A user which is able to create databases and/or touch the database schema') ) ); $this->addElement( 'password', 'password', array( - 'label' => mt('setup', 'Password'), - 'description' => mt('setup', 'The password for the database user defined above') + 'label' => $this->translate('Password'), + 'description' => $this->translate('The password for the database user defined above') ) ); @@ -182,7 +181,7 @@ class DatabaseCreationPage extends Form // form need to be granted to create databases, users... if (false === $db->checkPrivileges($this->databaseSetupPrivileges)) { $this->addError( - mt('setup', 'The provided credentials cannot be used to create the database and/or the user.') + $this->translate('The provided credentials cannot be used to create the database and/or the user.') ); $this->addSkipValidationCheckbox(); return false; @@ -191,8 +190,7 @@ class DatabaseCreationPage extends Form // ...and to grant all required usage privileges to others if (false === $db->isGrantable($this->databaseUsagePrivileges)) { $this->addError(sprintf( - mt( - 'setup', + $this->translate( 'The provided credentials cannot be used to grant all required privileges to the login "%s".' ), $this->config['username'] @@ -215,9 +213,8 @@ class DatabaseCreationPage extends Form array( 'order' => 2, 'required' => true, - 'label' => mt('setup', 'Skip Validation'), - 'description' => mt( - 'setup', + 'label' => $this->translate('Skip Validation'), + 'description' => $this->translate( 'Check this to not to validate the ability to login and required privileges' ) ) diff --git a/modules/setup/application/forms/DbResourcePage.php b/modules/setup/application/forms/DbResourcePage.php index 4a6535324..1901d8ca9 100644 --- a/modules/setup/application/forms/DbResourcePage.php +++ b/modules/setup/application/forms/DbResourcePage.php @@ -39,7 +39,7 @@ class DbResourcePage extends Form 'note', 'title', array( - 'value' => mt('setup', 'Database Resource', 'setup.page.title'), + 'value' => $this->translate('Database Resource', 'setup.page.title'), 'decorators' => array( 'ViewHelper', array('HtmlTag', array('tag' => 'h2')) @@ -50,8 +50,7 @@ class DbResourcePage extends Form 'note', 'description', array( - 'value' => mt( - 'setup', + 'value' => $this->translate( 'Now please configure your database resource. Note that the database itself does not need to' . ' exist at this time as it is going to be created once the wizard is about to be finished.' ) @@ -121,8 +120,10 @@ class DbResourcePage extends Form 'skip_validation', array( 'required' => true, - 'label' => mt('setup', 'Skip Validation'), - 'description' => mt('setup', 'Check this to not to validate connectivity with the given database server') + 'label' => $this->translate('Skip Validation'), + 'description' => $this->translate( + 'Check this to not to validate connectivity with the given database server' + ) ) ); } diff --git a/modules/setup/application/forms/GeneralConfigPage.php b/modules/setup/application/forms/GeneralConfigPage.php index 309c1784d..e0a9d0fab 100644 --- a/modules/setup/application/forms/GeneralConfigPage.php +++ b/modules/setup/application/forms/GeneralConfigPage.php @@ -29,7 +29,7 @@ class GeneralConfigPage extends Form 'note', 'title', array( - 'value' => mt('setup', 'Application Configuration', 'setup.page.title'), + 'value' => $this->translate('Application Configuration', 'setup.page.title'), 'decorators' => array( 'ViewHelper', array('HtmlTag', array('tag' => 'h2')) @@ -40,8 +40,7 @@ class GeneralConfigPage extends Form 'note', 'description', array( - 'value' => mt( - 'setup', + 'value' => $this->translate( 'Now please adjust all application and logging related configuration options to fit your needs.' ) ) diff --git a/modules/setup/application/forms/LdapDiscoveryConfirmPage.php b/modules/setup/application/forms/LdapDiscoveryConfirmPage.php index f76cbee07..66fd39001 100644 --- a/modules/setup/application/forms/LdapDiscoveryConfirmPage.php +++ b/modules/setup/application/forms/LdapDiscoveryConfirmPage.php @@ -82,7 +82,7 @@ EOT; 'note', 'title', array( - 'value' => mt('setup', 'LDAP Discovery Results', 'setup.page.title'), + 'value' => $this->translate('LDAP Discovery Results', 'setup.page.title'), 'decorators' => array( 'ViewHelper', array('HtmlTag', array('tag' => 'h2')) @@ -94,7 +94,7 @@ EOT; 'description', array( 'value' => sprintf( - mt('setup', 'The following directory service has been found on domain "%s":'), + $this->translate('The following directory service has been found on domain "%s":'), $this->config['domain'] ) ) @@ -119,7 +119,7 @@ EOT; 'confirm', array( 'value' => '1', - 'label' => mt('setup', 'Use this configuration?') + 'label' => $this->translate('Use this configuration?') ) ); } diff --git a/modules/setup/application/forms/LdapDiscoveryPage.php b/modules/setup/application/forms/LdapDiscoveryPage.php index 8c61eb379..26b43803b 100644 --- a/modules/setup/application/forms/LdapDiscoveryPage.php +++ b/modules/setup/application/forms/LdapDiscoveryPage.php @@ -36,7 +36,7 @@ class LdapDiscoveryPage extends Form 'note', 'title', array( - 'value' => mt('setup', 'LDAP Discovery', 'setup.page.title'), + 'value' => $this->translate('LDAP Discovery', 'setup.page.title'), 'decorators' => array( 'ViewHelper', array('HtmlTag', array('tag' => 'h2')) @@ -47,8 +47,7 @@ class LdapDiscoveryPage extends Form 'note', 'description', array( - 'value' => mt( - 'setup', + 'value' => $this->translate( 'You can use this page to discover LDAP or ActiveDirectory servers ' . ' for authentication. If you don\' want to execute a discovery, just skip this step.' ) @@ -66,8 +65,8 @@ class LdapDiscoveryPage extends Form 'skip_validation', array( 'required' => true, - 'label' => mt('setup', 'Skip'), - 'description' => mt('setup', 'Do not discover LDAP servers and enter all settings manually.') + 'label' => $this->translate('Skip'), + 'description' => $this->translate('Do not discover LDAP servers and enter all settings manually.') ) ); } @@ -94,7 +93,9 @@ class LdapDiscoveryPage extends Form return true; } } - $this->addError(sprintf(t('Could not find any LDAP servers on the domain "%s".'), $data['domain'])); + $this->addError( + sprintf($this->translate('Could not find any LDAP servers on the domain "%s".'), $data['domain']) + ); return false; } diff --git a/modules/setup/application/forms/LdapResourcePage.php b/modules/setup/application/forms/LdapResourcePage.php index 49bed69c3..f003a7370 100644 --- a/modules/setup/application/forms/LdapResourcePage.php +++ b/modules/setup/application/forms/LdapResourcePage.php @@ -37,7 +37,7 @@ class LdapResourcePage extends Form 'note', 'title', array( - 'value' => mt('setup', 'LDAP Resource', 'setup.page.title'), + 'value' => $this->translate('LDAP Resource', 'setup.page.title'), 'decorators' => array( 'ViewHelper', array('HtmlTag', array('tag' => 'h2')) @@ -48,8 +48,7 @@ class LdapResourcePage extends Form 'note', 'description', array( - 'value' => mt( - 'setup', + 'value' => $this->translate( 'Now please configure your AD/LDAP resource. This will later ' . 'be used to authenticate users logging in to Icinga Web 2.' ) @@ -107,9 +106,8 @@ class LdapResourcePage extends Form 'skip_validation', array( 'required' => true, - 'label' => mt('setup', 'Skip Validation'), - 'description' => mt( - 'setup', + 'label' => $this->translate('Skip Validation'), + 'description' => $this->translate( 'Check this to not to validate connectivity with the given directory service' ) ) diff --git a/modules/setup/application/forms/ModulePage.php b/modules/setup/application/forms/ModulePage.php index 5e8927dbc..ef765c0e7 100644 --- a/modules/setup/application/forms/ModulePage.php +++ b/modules/setup/application/forms/ModulePage.php @@ -4,22 +4,13 @@ namespace Icinga\Module\Setup\Forms; -use InvalidArgumentException; use Icinga\Application\Icinga; use Icinga\Web\Form; -use Icinga\Web\Session; -use Icinga\Web\Request; class ModulePage extends Form { - protected $session; - - protected $wizards; - protected $modules; - protected $pageData; - protected $modulePaths; /** @@ -29,7 +20,6 @@ class ModulePage extends Form { $this->setName('setup_modules'); $this->setViewScript('form/setup-modules.phtml'); - $this->session = Session::getSession()->getNamespace(get_class($this)); $this->modulePaths = array(); if (($appModulePath = realpath(Icinga::app()->getApplicationDir() . '/../modules')) !== false) { @@ -37,84 +27,24 @@ class ModulePage extends Form } } - public function setPageData(array $pageData) + public function createElements(array $formData) { - $this->pageData = $pageData; - return $this; - } - - public function handleRequest(Request $request = null) - { - $isPost = strtolower($request->getMethod()) === 'post'; - if ($isPost && $this->wasSent($request->getPost())) { - if (($newModule = $request->getPost('module')) !== null) { - $this->setCurrentModule($newModule); - $this->getResponse()->redirectAndExit($this->getRedirectUrl()); - } else { - // The user submitted this form but with the parent wizard's navigation - // buttons so it's now up to the parent wizard to handle the request.. - } - } else { - $wizard = $this->getCurrentWizard(); - $wizardPage = $wizard->getCurrentPage(); - - $wizard->handleRequest($request); - if ($isPost && $wizard->isFinished() && $wizardPage->wasSent($request->getPost())) { - $wizards = $this->getWizards(); - - $newModule = null; - foreach ($wizards as $moduleName => $moduleWizard) { - if (false === $moduleWizard->isFinished()) { - $newModule = $moduleName; - } - } - - if ($newModule === null) { - // In case all module wizards were completed just pick the first one again - reset($wizards); - $newModule = key($wizards); - } - - $this->setCurrentModule($newModule); - } + foreach ($this->getModules() as $module) { + $this->addElement( + 'checkbox', + $module->getName(), + array( + 'required' => true, + 'description' => $module->getDescription(), + 'label' => ucfirst($module->getName()), + 'value' => $module->getName() === 'monitoring' ? 1 : 0, + 'decorators' => array('ViewHelper') + ) + ); } } - public function clearSession() - { - $this->session->clear(); - foreach ($this->getWizards() as $wizard) { - $wizard->clearSession(); - } - } - - public function setCurrentModule($moduleName) - { - if (false === array_key_exists($moduleName, $this->getWizards())) { - throw new InvalidArgumentException(sprintf('Module "%s" does not provide a setup wizard', $moduleName)); - } - - $this->session->currentModule = $moduleName; - } - - public function getCurrentModule() - { - $moduleName = $this->session->get('currentModule'); - if ($moduleName === null) { - $moduleName = key($this->getWizards()); - $this->setCurrentModule($moduleName); - } - - return $moduleName; - } - - public function getCurrentWizard() - { - $wizards = $this->getWizards(); - return $wizards[$this->getCurrentModule()]; - } - - public function getModules() + protected function getModules() { if ($this->modules !== null) { return $this->modules; @@ -125,37 +55,39 @@ class ModulePage extends Form $moduleManager = Icinga::app()->getModuleManager(); $moduleManager->detectInstalledModules($this->modulePaths); foreach ($moduleManager->listInstalledModules() as $moduleName) { - $this->modules[] = $moduleManager->loadModule($moduleName)->getModule($moduleName); + if ($moduleName !== 'setup') { + $this->modules[$moduleName] = $moduleManager->loadModule($moduleName)->getModule($moduleName); + } } return $this->modules; } - public function getWizards() + public function getCheckedModules() { - if ($this->wizards !== null) { - return $this->wizards; - } else { - $this->wizards = array(); - } + $modules = $this->getModules(); - foreach ($this->getModules() as $module) { - if ($module->providesSetupWizard()) { - $this->wizards[$module->getName()] = $module->getSetupWizard(); + $checked = array(); + foreach ($this->getElements() as $name => $element) { + if (array_key_exists($name, $modules) && $element->isChecked()) { + $checked[$name] = $modules[$name]; } } - $this->mergePageData($this->wizards); - return $this->wizards; + return $checked; } - protected function mergePageData(array $wizards) + public function getModuleWizards() { - foreach ($wizards as $wizard) { - $wizardPageData = & $wizard->getPageData(); - foreach ($this->pageData as $pageName => $pageData) { - $wizardPageData[$pageName] = $pageData; + $checked = $this->getCheckedModules(); + + $wizards = array(); + foreach ($checked as $name => $module) { + if ($module->providesSetupWizard()) { + $wizards[$name] = $module->getSetupWizard(); } } + + return $wizards; } } diff --git a/modules/setup/application/forms/PreferencesPage.php b/modules/setup/application/forms/PreferencesPage.php index 26fd048e1..01b3296f4 100644 --- a/modules/setup/application/forms/PreferencesPage.php +++ b/modules/setup/application/forms/PreferencesPage.php @@ -27,11 +27,10 @@ class PreferencesPage extends Form */ public function showDatabaseNote() { - $this->getElement('type') + $this->getElement('store') ->setValue('db') ->setDescription( - mt( - 'setup', + $this->translate( 'Note that choosing "Database" causes Icinga Web 2 to use the same database as for authentication.' ) ); @@ -47,7 +46,7 @@ class PreferencesPage extends Form 'note', 'title', array( - 'value' => mt('setup', 'Preferences', 'setup.page.title'), + 'value' => $this->translate('Preferences', 'setup.page.title'), 'decorators' => array( 'ViewHelper', array('HtmlTag', array('tag' => 'h2')) @@ -58,23 +57,23 @@ class PreferencesPage extends Form 'note', 'description', array( - 'value' => mt('setup', 'Please choose how Icinga Web 2 should store user preferences.') + 'value' => $this->translate('Please choose how Icinga Web 2 should store user preferences.') ) ); $storageTypes = array(); - $storageTypes['ini'] = t('File System (INI Files)'); + $storageTypes['ini'] = $this->translate('File System (INI Files)'); if (Platform::hasMysqlSupport() || Platform::hasPostgresqlSupport()) { - $storageTypes['db'] = t('Database'); + $storageTypes['db'] = $this->translate('Database'); } - $storageTypes['null'] = t('Don\'t Store Preferences'); + $storageTypes['none'] = $this->translate('Don\'t Store Preferences'); $this->addElement( 'select', - 'type', + 'store', array( 'required' => true, - 'label' => t('User Preference Storage Type'), + 'label' => $this->translate('User Preference Storage Type'), 'multiOptions' => $storageTypes ) ); diff --git a/modules/setup/application/forms/SummaryPage.php b/modules/setup/application/forms/SummaryPage.php index 14ad93c56..9b42ec9d8 100644 --- a/modules/setup/application/forms/SummaryPage.php +++ b/modules/setup/application/forms/SummaryPage.php @@ -4,6 +4,7 @@ namespace Icinga\Module\Setup\Forms; +use LogicException; use Icinga\Web\Form; /** @@ -30,7 +31,12 @@ class SummaryPage extends Form */ public function init() { - $this->setName('setup_summary'); + if ($this->getName() === $this->filterName(get_class($this))) { + throw new LogicException( + 'When utilizing ' . get_class($this) . ' it is required to set a unique name by using the form options' + ); + } + $this->setViewScript('form/setup-summary.phtml'); } diff --git a/modules/setup/application/forms/WelcomePage.php b/modules/setup/application/forms/WelcomePage.php index 5da607683..66340ff25 100644 --- a/modules/setup/application/forms/WelcomePage.php +++ b/modules/setup/application/forms/WelcomePage.php @@ -32,9 +32,8 @@ class WelcomePage extends Form 'token', array( 'required' => true, - 'label' => mt('setup', 'Setup Token'), - 'description' => mt( - 'setup', + 'label' => $this->translate('Setup Token'), + 'description' => $this->translate( 'For security reasons we need to ensure that you are permitted to run this wizard.' . ' Please provide a token by following the instructions below.' ), diff --git a/modules/setup/application/views/scripts/form/setup-modules.phtml b/modules/setup/application/views/scripts/form/setup-modules.phtml index a352803d7..8d8e9ecf9 100644 --- a/modules/setup/application/views/scripts/form/setup-modules.phtml +++ b/modules/setup/application/views/scripts/form/setup-modules.phtml @@ -3,41 +3,18 @@ use Icinga\Web\Wizard; ?> -
-

-

-
- getElement($form->getTokenElementName()); ?> - getElement($form->getUidElementName()); ?> -
    - - getModules() as $module): ?> - providesSetupWizard()): ?> -
  • - getName() === $form->getCurrentModule(); ?> - - getSetupWizard()->isFinished()): ?> - icon('ok', mt('setup', 'Completed', 'setup.modules.wizard.state')); ?> - - - -
  • - - -
-
- -

- -

+
+

translate('Modules', 'setup.page.title'); ?>

+

translate('The following modules were found in your Icinga Web 2 installation. To enable and configure a module, just tick it and click "Next".'); ?>

+getElements() as $element): ?> + getName(), array(Wizard::BTN_PREV, Wizard::BTN_NEXT, $form->getTokenElementName(), $form->getUidElementName()))): ?> +
+

+ + +
-
-
- getCurrentWizard()->getForm()->render(); ?> -
- + getElement($form->getTokenElementName()); ?> getElement($form->getUidElementName()); ?>
diff --git a/modules/setup/application/views/scripts/form/setup-requirements.phtml b/modules/setup/application/views/scripts/form/setup-requirements.phtml index ca2556b95..47842efde 100644 --- a/modules/setup/application/views/scripts/form/setup-requirements.phtml +++ b/modules/setup/application/views/scripts/form/setup-requirements.phtml @@ -11,7 +11,17 @@ $requirements = $form->getRequirements();

title; ?>

- description; ?> + + description)): ?> +
    + description as $desc): ?> +
  • + +
+ + description; ?> + + message; ?> @@ -22,7 +32,7 @@ $requirements = $form->getRequirements(); diff --git a/modules/setup/application/views/scripts/form/setup-summary.phtml b/modules/setup/application/views/scripts/form/setup-summary.phtml index 714416833..e8053a897 100644 --- a/modules/setup/application/views/scripts/form/setup-summary.phtml +++ b/modules/setup/application/views/scripts/form/setup-summary.phtml @@ -4,9 +4,8 @@ use Icinga\Web\Wizard; ?>

translate( + 'You\'ve configured %1$s successfully. You can review the changes supposed to be made before setting it up.' . ' Make sure that everything is correct (Feel free to navigate back to make any corrections!) so' . ' that you can start using %1$s right after it has successfully been set up.' ), @@ -21,7 +20,7 @@ use Icinga\Web\Wizard;

- + getElement($form->getTokenElementName()); ?> getElement($form->getUidElementName()); ?>
diff --git a/modules/setup/application/views/scripts/form/setup-welcome.phtml b/modules/setup/application/views/scripts/form/setup-welcome.phtml index 6c8228541..d4bc1c3d7 100644 --- a/modules/setup/application/views/scripts/form/setup-welcome.phtml +++ b/modules/setup/application/views/scripts/form/setup-welcome.phtml @@ -11,16 +11,14 @@ $cliPath = realpath(Icinga::app()->getApplicationDir() . '/../bin/icingacli'); ?>
-

+

translate('Welcome to the configuration of Icinga Web 2!') ?>

-

translate( 'You\'ve already completed the configuration of Icinga Web 2. Note that most of your configuration' . ' files will be overwritten in case you\'ll re-configure Icinga Web 2 using this wizard!' ); ?>

-

translate( 'This wizard will guide you through the configuration of Icinga Web 2. Once completed and successfully' . ' finished you are able to log in and to explore all the new and stunning features!' ); ?>

@@ -39,25 +37,26 @@ $cliPath = realpath(Icinga::app()->getApplicationDir() . '/../bin/icingacli');

translate( 'To run this wizard a user needs to authenticate using a token which is usually' . ' provided to him by an administrator who\'d followed the instructions below.' ); ?>

-

+

translate('In any case, make sure that a group called "icingaweb2" exists:'); ?>

- setup config createDirectory ; + groupadd icingaweb2; +
+

translate('If you\'ve got the IcingaCLI installed you can do the following:'); ?>

+
+ setup config directory --group icingaweb2; setup token create;
-

+

translate('In case the IcingaCLI is missing you can create the token manually:'); ?>

- su && mkdir -m 2770 ; - head -c 12 /dev/urandom | base64 | tee ; - chmod 0660 ; + su -c "mkdir -m 2770 ; chgrp icingaweb2 ; head -c 12 /dev/urandom | base64 | tee ; chmod 0660 ;";

' . mt('setup', 'Icinga Web 2 documentation') . '' // TODO: Add link to iw2 docs which points to the installation topic + $this->translate('Please see the %s for an extensive description on how to access and use this wizard.'), + '' . $this->translate('Icinga Web 2 documentation') . '' // TODO: Add link to iw2 docs which points to the installation topic ); ?>

diff --git a/modules/setup/application/views/scripts/index/index.phtml b/modules/setup/application/views/scripts/index/index.phtml index 9af37be7c..a55cfa198 100644 --- a/modules/setup/application/views/scripts/index/index.phtml +++ b/modules/setup/application/views/scripts/index/index.phtml @@ -4,7 +4,7 @@ use Icinga\Web\Notification; $pages = $wizard->getPages(); $finished = isset($success); -$configPages = array_slice($pages, 2, count($pages) - 4, true); +$configPages = array_slice($pages, 3, count($pages) - 1, true); $currentPos = array_search($wizard->getCurrentPage(), $pages, true); list($configPagesLeft, $configPagesRight) = array_chunk($configPages, count($configPages) / 2, true); @@ -30,7 +30,7 @@ if ($notifications->hasMessages()) { img('img/logo_icinga_big.png'); ?>
-

+

translate('Welcome', 'setup.progress'); ?>

0 ? 'complete' : ( $maxProgress > 0 ? 'visited' : 'active' ); ?> @@ -41,30 +41,43 @@ if ($notifications->hasMessages()) {
-

+

translate('Modules', 'setup.progress'); ?>

1 ? ' complete' : ( $maxProgress > 1 ? ' visited' : ( $currentPos === 1 ? ' active' : '' ) ); ?> + + + + +
+
+
+

translate('Requirements', 'setup.progress'); ?>

+ 2 ? ' complete' : ( + $maxProgress > 2 ? ' visited' : ( + $currentPos === 2 ? ' active' : '' + ) + ); ?>
-
-

+
+

translate('Configuration', 'setup.progress'); ?>

$page): ?> 1 ? ' active' : '') + $pos < $maxProgress ? ' visited' : ($currentPos > 2 ? ' active' : '') ); ?>
@@ -78,7 +91,7 @@ if ($notifications->hasMessages()) {
@@ -87,11 +100,11 @@ if ($notifications->hasMessages()) { $page): ?> 1 ? ' active' : '') + $pos < $maxProgress ? ' visited' : ($currentPos > 2 ? ' active' : '') ); ?>
@@ -105,27 +118,7 @@ if ($notifications->hasMessages()) {
-

- count($pages) - 2 ? ' complete' : ( - $maxProgress > count($pages) - 2 ? ' visited' : ($currentPos === count($pages) - 2 ? ' active' : '') - ); ?> - - - - -
-
-
-

- - - - - -
-
-
-

+

translate('Finish', 'setup.progress'); ?>

diff --git a/modules/setup/application/views/scripts/index/parts/finish.phtml b/modules/setup/application/views/scripts/index/parts/finish.phtml index 94217017d..e695d72ce 100644 --- a/modules/setup/application/views/scripts/index/parts/finish.phtml +++ b/modules/setup/application/views/scripts/index/parts/finish.phtml @@ -11,16 +11,16 @@ -

+

translate('Congratulations! Icinga Web 2 has been successfully set up.'); ?>

-

+

translate('Sorry! Failed to set up Icinga Web 2 successfully.'); ?>

\ No newline at end of file diff --git a/modules/setup/library/Setup/Requirements.php b/modules/setup/library/Setup/Requirements.php index 4b3d411cb..ab9e693e5 100644 --- a/modules/setup/library/Setup/Requirements.php +++ b/modules/setup/library/Setup/Requirements.php @@ -9,6 +9,9 @@ use IteratorAggregate; /** * Container to store and handle requirements + * + * TODO: Requirements should be registered as objects with a specific purpose (PhpModRequirement, PhpIniRequirement, ..) + * so that it's not necessary to define unique identifiers which may differ between different modules. */ class Requirements implements IteratorAggregate { @@ -41,12 +44,40 @@ class Requirements implements IteratorAggregate * * @return self */ - public function add($requirement) + public function add($name, $requirement) { - $this->requirements[] = $requirement; + $this->requirements[$name] = array_key_exists($name, $this->requirements) + ? $this->combine($this->requirements[$name], $requirement) + : $requirement; return $this; } + /** + * Combine the two given requirements + * + * Returns the most important requirement with the description from the other one being added. + * + * @param object $oldRequirement + * @param object $newRequirement + * + * @return object + */ + protected function combine($oldRequirement, $newRequirement) + { + if ($newRequirement->state === static::STATE_MANDATORY && $oldRequirement->state === static::STATE_OPTIONAL) { + $tempRequirement = $oldRequirement; + $oldRequirement = $newRequirement; + $newRequirement = $tempRequirement; + } + + if (! is_array($oldRequirement->description)) { + $oldRequirement->description = array($oldRequirement->description); + } + + $oldRequirement->description[] = $newRequirement->description; + return $oldRequirement; + } + /** * Return all registered requirements * @@ -70,6 +101,7 @@ class Requirements implements IteratorAggregate /** * Register an optional requirement * + * @param string $name * @param string $title * @param string $description * @param bool $state @@ -77,20 +109,24 @@ class Requirements implements IteratorAggregate * * @return self */ - public function addOptional($title, $description, $state, $message) + public function addOptional($name, $title, $description, $state, $message) { - $this->add((object) array( - 'title' => $title, - 'message' => $message, - 'description' => $description, - 'state' => (bool) $state ? static::STATE_OK : static::STATE_OPTIONAL - )); + $this->add( + $name, + (object) array( + 'title' => $title, + 'message' => $message, + 'description' => $description, + 'state' => (bool) $state ? static::STATE_OK : static::STATE_OPTIONAL + ) + ); return $this; } /** * Register a mandatory requirement * + * @param string $name * @param string $title * @param string $description * @param bool $state @@ -98,14 +134,17 @@ class Requirements implements IteratorAggregate * * @return self */ - public function addMandatory($title, $description, $state, $message) + public function addMandatory($name, $title, $description, $state, $message) { - $this->add((object) array( - 'title' => $title, - 'message' => $message, - 'description' => $description, - 'state' => (bool) $state ? static::STATE_OK : static::STATE_MANDATORY - )); + $this->add( + $name, + (object) array( + 'title' => $title, + 'message' => $message, + 'description' => $description, + 'state' => (bool) $state ? static::STATE_OK : static::STATE_MANDATORY + ) + ); return $this; } @@ -118,8 +157,8 @@ class Requirements implements IteratorAggregate */ public function merge(Requirements $requirements) { - foreach ($requirements->getAll() as $requirement) { - $this->add($requirement); + foreach ($requirements->getAll() as $name => $requirement) { + $this->add($name, $requirement); } return $this; diff --git a/modules/setup/library/Setup/Steps/AuthenticationStep.php b/modules/setup/library/Setup/Steps/AuthenticationStep.php index a15198c57..ce0b49f58 100644 --- a/modules/setup/library/Setup/Steps/AuthenticationStep.php +++ b/modules/setup/library/Setup/Steps/AuthenticationStep.php @@ -139,7 +139,7 @@ class AuthenticationStep extends Step . '' . '' . '' - ) : ($authType === 'autologin' ? ( + ) : ($authType === 'external' ? ( '' . '' . '' diff --git a/modules/setup/library/Setup/Steps/DatabaseStep.php b/modules/setup/library/Setup/Steps/DatabaseStep.php index c6ec2ef2b..006b6c9ed 100644 --- a/modules/setup/library/Setup/Steps/DatabaseStep.php +++ b/modules/setup/library/Setup/Steps/DatabaseStep.php @@ -6,7 +6,6 @@ namespace Icinga\Module\Setup\Steps; use Exception; use PDOException; -use Icinga\Application\Icinga; use Icinga\Module\Setup\Step; use Icinga\Module\Setup\Utils\DbTool; use Icinga\Module\Setup\Exception\SetupException; @@ -71,7 +70,7 @@ class DatabaseStep extends Step $this->log(mt('setup', 'Database schema already exists...')); } else { $this->log(mt('setup', 'Creating database schema...')); - $db->import(Icinga::app()->getApplicationDir() . '/../etc/schema/mysql.schema.sql'); + $db->import($this->data['schemaPath'] . '/mysql.schema.sql'); } if ($db->hasLogin($this->data['resourceConfig']['username'])) { @@ -122,7 +121,7 @@ class DatabaseStep extends Step $this->log(mt('setup', 'Database schema already exists...')); } else { $this->log(mt('setup', 'Creating database schema...')); - $db->import(Icinga::app()->getApplicationDir() . '/../etc/schema/pgsql.schema.sql'); + $db->import($this->data['schemaPath'] . '/pgsql.schema.sql'); } if ($db->hasLogin($this->data['resourceConfig']['username'])) { diff --git a/modules/setup/library/Setup/Steps/GeneralConfigStep.php b/modules/setup/library/Setup/Steps/GeneralConfigStep.php index ee9e2c581..39c160628 100644 --- a/modules/setup/library/Setup/Steps/GeneralConfigStep.php +++ b/modules/setup/library/Setup/Steps/GeneralConfigStep.php @@ -29,7 +29,7 @@ class GeneralConfigStep extends Step $config[$section][$property] = $value; } - $config['preferences']['type'] = $this->data['preferencesType']; + $config['preferences']['store'] = $this->data['preferencesStore']; if (isset($this->data['preferencesResource'])) { $config['preferences']['resource'] = $this->data['preferencesResource']; } @@ -58,11 +58,11 @@ class GeneralConfigStep extends Step $generalHtml = '' . '
    ' . '
  • ' . sprintf( - $this->data['preferencesType'] === 'ini' ? sprintf( + $this->data['preferencesStore'] === 'ini' ? sprintf( t('Preferences will be stored per user account in INI files at: %s'), Config::resolvePath('preferences') ) : ( - $this->data['preferencesType'] === 'db' ? t('Preferences will be stored using a database.') : ( + $this->data['preferencesStore'] === 'db' ? t('Preferences will be stored using a database.') : ( t('Preferences will not be persisted across browser sessions.') ) ) diff --git a/modules/setup/library/Setup/Utils/DbTool.php b/modules/setup/library/Setup/Utils/DbTool.php index a368bfa1a..63184acd0 100644 --- a/modules/setup/library/Setup/Utils/DbTool.php +++ b/modules/setup/library/Setup/Utils/DbTool.php @@ -641,7 +641,8 @@ EOD; foreach ($mysqlPrivileges as $privilege) { if (false === empty($context) && $this->mysqlGrantContexts[$privilege] & static::TABLE_LEVEL) { $tablePrivileges[] = $privilege; - } elseif ($this->mysqlGrantContexts[$privilege] & static::DATABASE_LEVEL) { + } + if ($this->mysqlGrantContexts[$privilege] & static::DATABASE_LEVEL) { $dbPrivileges[] = $privilege; } } @@ -661,7 +662,11 @@ EOD; } $tablePrivilegesGranted = true; - if (false === empty($tablePrivileges)) { + if ( + false === empty($tablePrivileges) && ( + !$dbPrivilegesGranted || array_intersect($dbPrivileges, $tablePrivileges) != $tablePrivileges + ) + ) { $tableCondition = 'table_name IN (' . join(',', array_map(array($this, 'quote'), $context)) . ')'; $query = $this->query( 'SELECT COUNT(*) as matches' diff --git a/modules/setup/library/Setup/Utils/EnableModuleStep.php b/modules/setup/library/Setup/Utils/EnableModuleStep.php index 3ca3eebd1..a23e532f2 100644 --- a/modules/setup/library/Setup/Utils/EnableModuleStep.php +++ b/modules/setup/library/Setup/Utils/EnableModuleStep.php @@ -12,13 +12,13 @@ class EnableModuleStep extends Step { protected $modulePaths; - protected $moduleName; + protected $moduleNames; - protected $error; + protected $errors; - public function __construct($moduleName) + public function __construct(array $moduleNames) { - $this->moduleName = $moduleName; + $this->moduleNames = $moduleNames; $this->modulePaths = array(); if (($appModulePath = realpath(Icinga::app()->getApplicationDir() . '/../modules')) !== false) { @@ -28,17 +28,20 @@ class EnableModuleStep extends Step public function apply() { - try { - $moduleManager = Icinga::app()->getModuleManager(); - $moduleManager->detectInstalledModules($this->modulePaths); - $moduleManager->enableModule($this->moduleName); - } catch (Exception $e) { - $this->error = $e; - return false; + $moduleManager = Icinga::app()->getModuleManager(); + $moduleManager->detectInstalledModules($this->modulePaths); + + $success = true; + foreach ($this->moduleNames as $moduleName) { + try { + $moduleManager->enableModule($moduleName); + } catch (Exception $e) { + $this->errors[$moduleName] = $e; + $success = false; + } } - $this->error = false; - return true; + return $success; } public function getSummary() @@ -48,12 +51,19 @@ class EnableModuleStep extends Step public function getReport() { - if ($this->error === false) { - return '

    ' . sprintf(mt('setup', 'Module "%s" has been successfully enabled.'), $this->moduleName) . '

    '; - } elseif ($this->error !== null) { - $message = mt('setup', 'Module "%s" could not be enabled. An error occured:'); - return '

    ' . sprintf($message, $this->moduleName) . '

    ' - . '

    ' . $this->error->getMessage() . '

    '; + $okMessage = mt('setup', 'Module "%s" has been successfully enabled.'); + $failMessage = mt('setup', 'Module "%s" could not be enabled. An error occured:'); + + $report = ''; + foreach ($this->moduleNames as $moduleName) { + if (isset($this->errors[$moduleName])) { + $report .= '

    ' . sprintf($failMessage, $moduleName) . '

    ' + . '

    ' . $this->errors[$moduleName]->getMessage() . '

    '; + } else { + $report .= '

    ' . sprintf($okMessage, $moduleName) . '

    '; + } } + + return $report; } } diff --git a/modules/setup/library/Setup/Utils/MakeDirStep.php b/modules/setup/library/Setup/Utils/MakeDirStep.php index d15c7db6a..d7813541b 100644 --- a/modules/setup/library/Setup/Utils/MakeDirStep.php +++ b/modules/setup/library/Setup/Utils/MakeDirStep.php @@ -16,12 +16,12 @@ class MakeDirStep extends Step /** * @param array $paths - * @param int $dirmode + * @param int $dirmode Directory mode in octal notation */ public function __construct($paths, $dirmode) { $this->paths = $paths; - $this->dirmode = $dirmode; + $this->dirmode = octdec((string) $dirmode); $this->errors = array(); } @@ -35,9 +35,7 @@ class MakeDirStep extends Step $success = false; } else { $this->errors[$path] = null; - $old = umask(0); chmod($path, $this->dirmode); - umask($old); } } } diff --git a/modules/setup/library/Setup/Web/Form/Validator/TokenValidator.php b/modules/setup/library/Setup/Web/Form/Validator/TokenValidator.php index 7dc2ea2f9..fa858f531 100644 --- a/modules/setup/library/Setup/Web/Form/Validator/TokenValidator.php +++ b/modules/setup/library/Setup/Web/Form/Validator/TokenValidator.php @@ -38,10 +38,6 @@ class TokenValidator extends Zend_Validate_Abstract mt('setup', 'Cannot validate token, file "%s" is empty. Please define a token.'), $tokenPath ), - 'TOKEN_FILE_PUBLIC' => sprintf( - mt('setup', 'Cannot validate token, file "%s" must only be accessible by the webserver\'s user.'), - $tokenPath - ), 'TOKEN_INVALID' => mt('setup', 'Invalid token supplied.') ); } @@ -56,12 +52,6 @@ class TokenValidator extends Zend_Validate_Abstract */ public function isValid($value, $context = null) { - $tokenStats = @stat($this->tokenPath); - if (($tokenStats['mode'] & 4) === 4) { - $this->_error('TOKEN_FILE_PUBLIC'); - return false; - } - try { $file = new File($this->tokenPath); $expectedToken = trim($file->fgets()); diff --git a/modules/setup/library/Setup/WebWizard.php b/modules/setup/library/Setup/WebWizard.php index faa123fe8..8ae7344ea 100644 --- a/modules/setup/library/Setup/WebWizard.php +++ b/modules/setup/library/Setup/WebWizard.php @@ -9,6 +9,7 @@ use Icinga\Web\Form; use Icinga\Web\Wizard; use Icinga\Web\Request; use Icinga\Application\Config; +use Icinga\Application\Icinga; use Icinga\Application\Platform; use Icinga\Module\Setup\Forms\ModulePage; use Icinga\Module\Setup\Forms\WelcomePage; @@ -28,6 +29,7 @@ use Icinga\Module\Setup\Steps\DatabaseStep; use Icinga\Module\Setup\Steps\GeneralConfigStep; use Icinga\Module\Setup\Steps\ResourceStep; use Icinga\Module\Setup\Steps\AuthenticationStep; +use Icinga\Module\Setup\Utils\EnableModuleStep; use Icinga\Module\Setup\Utils\MakeDirStep; use Icinga\Module\Setup\Utils\DbTool; @@ -82,6 +84,7 @@ class WebWizard extends Wizard implements SetupWizard protected function init() { $this->addPage(new WelcomePage()); + $this->addPage(new ModulePage()); $this->addPage(new RequirementsPage()); $this->addPage(new AuthenticationPage()); $this->addPage(new PreferencesPage()); @@ -93,8 +96,14 @@ class WebWizard extends Wizard implements SetupWizard $this->addPage(new AdminAccountPage()); $this->addPage(new GeneralConfigPage()); $this->addPage(new DatabaseCreationPage()); - $this->addPage(new ModulePage()); - $this->addPage(new SummaryPage()); + $this->addPage(new SummaryPage(array('name' => 'setup_summary'))); + + if (($modulePageData = $this->getPageData('setup_modules')) !== null) { + $modulePage = $this->getPage('setup_modules')->populate($modulePageData); + foreach ($modulePage->getModuleWizards() as $moduleWizard) { + $this->addPage($moduleWizard); + } + } } /** @@ -166,9 +175,6 @@ class WebWizard extends Wizard implements SetupWizard unset($pageData['setup_admin_account']); unset($pageData['setup_authentication_backend']); } - } elseif ($page->getName() === 'setup_modules') { - $page->setPageData($this->getPageData()); - $page->handleRequest($request); } } @@ -182,7 +188,7 @@ class WebWizard extends Wizard implements SetupWizard if ($newPage->getName() === 'setup_db_resource') { $prefData = $this->getPageData('setup_preferences_type'); $authData = $this->getPageData('setup_authentication_type'); - $skip = $prefData['type'] !== 'db' && $authData['type'] !== 'db'; + $skip = $prefData['store'] !== 'db' && $authData['type'] !== 'db'; } elseif ($newPage->getname() === 'setup_ldap_discovery') { $authData = $this->getPageData('setup_authentication_type'); $skip = $authData['type'] !== 'ldap'; @@ -221,23 +227,7 @@ class WebWizard extends Wizard implements SetupWizard } } - if ($skip) { - if ($this->hasPageData($newPage->getName())) { - $pageData = & $this->getPageData(); - unset($pageData[$newPage->getName()]); - } - - $pages = $this->getPages(); - if ($this->getDirection() === static::FORWARD) { - $nextPage = $pages[array_search($newPage, $pages, true) + 1]; - $newPage = $this->getNewPage($nextPage->getName(), $newPage); - } else { // $this->getDirection() === static::BACKWARD - $previousPage = $pages[array_search($newPage, $pages, true) - 1]; - $newPage = $this->getNewPage($previousPage->getName(), $newPage); - } - } - - return $newPage; + return $skip ? $this->skipPage($newPage) : $newPage; } /** @@ -262,7 +252,6 @@ class WebWizard extends Wizard implements SetupWizard public function clearSession() { parent::clearSession(); - $this->getPage('setup_modules')->clearSession(); $tokenPath = Config::resolvePath('setup.token'); if (file_exists($tokenPath)) { @@ -294,7 +283,9 @@ class WebWizard extends Wizard implements SetupWizard : null, 'adminPassword' => isset($pageData['setup_database_creation']['password']) ? $pageData['setup_database_creation']['password'] - : null + : null, + 'schemaPath' => Config::module('setup') + ->get('schema', 'path', Icinga::app()->getBaseDir('etc' . DIRECTORY_SEPARATOR . 'schema')) )) ); } @@ -302,7 +293,7 @@ class WebWizard extends Wizard implements SetupWizard $setup->addStep( new GeneralConfigStep(array( 'generalConfig' => $pageData['setup_general_config'], - 'preferencesType' => $pageData['setup_preferences_type']['type'], + 'preferencesStore' => $pageData['setup_preferences_type']['store'], 'preferencesResource' => isset($pageData['setup_db_resource']['name']) ? $pageData['setup_db_resource']['name'] : null @@ -343,24 +334,26 @@ class WebWizard extends Wizard implements SetupWizard ); } - $configDir = $this->getConfigDir(); + $configDir = Icinga::app()->getConfigDir(); $setup->addStep( new MakeDirStep( array( - $configDir . '/modules', - $configDir . '/preferences', - $configDir . '/enabledModules' + $configDir . DIRECTORY_SEPARATOR . 'modules', + $configDir . DIRECTORY_SEPARATOR . 'preferences', + $configDir . DIRECTORY_SEPARATOR . 'enabledModules' ), - 0775 + 2770 ) ); - foreach ($this->getPage('setup_modules')->setPageData($this->getPageData())->getWizards() as $wizard) { - if ($wizard->isFinished()) { + foreach ($this->getWizards() as $wizard) { + if ($wizard->isComplete()) { $setup->addSteps($wizard->getSetup()->getSteps()); } } + $setup->addStep(new EnableModuleStep(array_keys($this->getPage('setup_modules')->getCheckedModules()))); + return $setup; } @@ -373,6 +366,7 @@ class WebWizard extends Wizard implements SetupWizard $phpVersion = Platform::getPhpVersion(); $requirements->addMandatory( + 'php_version_>=_5_3_2', mt('setup', 'PHP Version'), mt( 'setup', @@ -385,6 +379,7 @@ class WebWizard extends Wizard implements SetupWizard $defaultTimezone = Platform::getPhpConfig('date.timezone'); $requirements->addMandatory( + 'existing_default_timezone', mt('setup', 'Default Timezone'), sprintf( mt('setup', 'It is required that a default timezone has been set using date.timezone in %s.'), @@ -397,6 +392,7 @@ class WebWizard extends Wizard implements SetupWizard ); $requirements->addOptional( + 'platform=linux', mt('setup', 'Linux Platform'), mt( 'setup', @@ -408,6 +404,7 @@ class WebWizard extends Wizard implements SetupWizard ); $requirements->addMandatory( + 'existing_php_mod_openssl', mt('setup', 'PHP Module: OpenSSL'), mt('setup', 'The PHP module for OpenSSL is required to generate cryptographically safe password salts.'), Platform::extensionLoaded('openssl'), @@ -417,6 +414,7 @@ class WebWizard extends Wizard implements SetupWizard ); $requirements->addOptional( + 'existing_php_mod_json', mt('setup', 'PHP Module: JSON'), mt('setup', 'The JSON module for PHP is required for various export functionalities as well as APIs.'), Platform::extensionLoaded('json'), @@ -426,6 +424,7 @@ class WebWizard extends Wizard implements SetupWizard ); $requirements->addOptional( + 'existing_php_mod_ldap', mt('setup', 'PHP Module: LDAP'), mt('setup', 'If you\'d like to authenticate users using LDAP the corresponding PHP module is required'), Platform::extensionLoaded('ldap'), @@ -435,6 +434,7 @@ class WebWizard extends Wizard implements SetupWizard ); $requirements->addOptional( + 'existing_php_mod_intl', mt('setup', 'PHP Module: INTL'), mt( 'setup', @@ -449,6 +449,7 @@ class WebWizard extends Wizard implements SetupWizard // TODO(6172): Remove this requirement once we do not ship dompdf with Icinga Web 2 anymore $requirements->addOptional( + 'existing_php_mod_dom', mt('setup', 'PHP Module: DOM'), mt('setup', 'To be able to export views and reports to PDF, the DOM module for PHP is required.'), Platform::extensionLoaded('dom'), @@ -458,6 +459,7 @@ class WebWizard extends Wizard implements SetupWizard ); $requirements->addOptional( + 'existing_php_mod_gd', mt('setup', 'PHP Module: GD'), mt( 'setup', @@ -471,6 +473,7 @@ class WebWizard extends Wizard implements SetupWizard ); $requirements->addOptional( + 'existing_php_mod_imagick', mt('setup', 'PHP Module: Imagick'), mt( 'setup', @@ -484,6 +487,7 @@ class WebWizard extends Wizard implements SetupWizard ); $requirements->addOptional( + 'existing_php_mod_pdo_mysql', mt('setup', 'PHP Module: PDO-MySQL'), mt( 'setup', @@ -496,6 +500,7 @@ class WebWizard extends Wizard implements SetupWizard ); $requirements->addOptional( + 'existing_php_mod_pdo_pgsql', mt('setup', 'PHP Module: PDO-PostgreSQL'), mt( 'setup', @@ -510,6 +515,7 @@ class WebWizard extends Wizard implements SetupWizard $mysqlAdapterFound = Platform::zendClassExists('Zend_Db_Adapter_Pdo_Mysql'); $requirements->addOptional( + 'existing_class_Zend_Db_Adapter_Pdo_Mysql', mt('setup', 'Zend Database Adapter For MySQL'), mt('setup', 'The Zend database adapter for MySQL is required to access a MySQL database.'), $mysqlAdapterFound, @@ -520,6 +526,7 @@ class WebWizard extends Wizard implements SetupWizard $pgsqlAdapterFound = Platform::zendClassExists('Zend_Db_Adapter_Pdo_Pgsql'); $requirements->addOptional( + 'existing_class_Zend_Db_Adapter_Pdo_Pgsql', mt('setup', 'Zend Database Adapter For PostgreSQL'), mt('setup', 'The Zend database adapter for PostgreSQL is required to access a PostgreSQL database.'), $pgsqlAdapterFound, @@ -528,12 +535,13 @@ class WebWizard extends Wizard implements SetupWizard ) ); - $configDir = $this->getConfigDir(); + $configDir = Icinga::app()->getConfigDir(); $requirements->addMandatory( + 'writable_directory_' . $configDir, mt('setup', 'Writable Config Directory'), mt( 'setup', - 'The Icinga Web 2 configuration directory defaults to "/etc/icingaweb", if' . + 'The Icinga Web 2 configuration directory defaults to "/etc/icingaweb2", if' . ' not explicitly set in the environment variable "ICINGAWEB_CONFIGDIR".' ), is_writable($configDir), @@ -545,27 +553,10 @@ class WebWizard extends Wizard implements SetupWizard ) ); - foreach ($this->getPage('setup_modules')->setPageData($this->getPageData())->getWizards() as $wizard) { - $requirements->merge($wizard->getRequirements()->allOptional()); + foreach ($this->getWizards() as $wizard) { + $requirements->merge($wizard->getRequirements()); } return $requirements; } - - /** - * Return the configuration directory of Icinga Web 2 - * - * @return string - */ - protected function getConfigDir() - { - if (array_key_exists('ICINGAWEB_CONFIGDIR', $_SERVER)) { - $configDir = $_SERVER['ICINGAWEB_CONFIGDIR']; - } else { - $configDir = '/etc/icingaweb'; - } - - $canonical = realpath($configDir); - return $canonical ? $canonical : $configDir; - } } diff --git a/modules/setup/library/Setup/Webserver.php b/modules/setup/library/Setup/Webserver.php index 2449f9b9e..dbc55b6a2 100644 --- a/modules/setup/library/Setup/Webserver.php +++ b/modules/setup/library/Setup/Webserver.php @@ -24,7 +24,7 @@ abstract class Webserver * * @var string */ - protected $urlPath = '/icingaweb'; + protected $urlPath = '/icingaweb2'; /** * Path to Icinga Web 2's configuration files diff --git a/modules/translation/library/Translation/Util/GettextTranslationHelper.php b/modules/translation/library/Translation/Util/GettextTranslationHelper.php index 0d5a950e1..5702def85 100644 --- a/modules/translation/library/Translation/Util/GettextTranslationHelper.php +++ b/modules/translation/library/Translation/Util/GettextTranslationHelper.php @@ -101,7 +101,7 @@ class GettextTranslationHelper */ public function __construct(ApplicationBootstrap $bootstrap, $locale) { - $this->moduleMgr = $bootstrap->getModuleManager()->loadCoreModules()->loadEnabledModules(); + $this->moduleMgr = $bootstrap->getModuleManager()->loadEnabledModules(); $this->appDir = $bootstrap->getApplicationDir(); $this->locale = $locale; } diff --git a/packages/files/apache/icingaweb.conf b/packages/files/apache/icingaweb2.conf similarity index 91% rename from packages/files/apache/icingaweb.conf rename to packages/files/apache/icingaweb2.conf index 2c52b73e3..6bf0b7a66 100644 --- a/packages/files/apache/icingaweb.conf +++ b/packages/files/apache/icingaweb2.conf @@ -1,4 +1,4 @@ -Alias /icingaweb "/usr/share/icingaweb2/public" +Alias /icingaweb2 "/usr/share/icingaweb2/public" Options SymLinksIfOwnerMatch @@ -23,7 +23,7 @@ Alias /icingaweb "/usr/share/icingaweb2/public" RewriteEngine on - RewriteBase /icingaweb/ + RewriteBase /icingaweb2/ RewriteCond %{REQUEST_FILENAME} -s [OR] RewriteCond %{REQUEST_FILENAME} -l [OR] RewriteCond %{REQUEST_FILENAME} -d diff --git a/packages/files/bin/icingacli b/packages/files/bin/icingacli index 10b4857aa..5b41e4e8c 100755 --- a/packages/files/bin/icingacli +++ b/packages/files/bin/icingacli @@ -3,4 +3,4 @@ require_once '/usr/share/php/Icinga/Application/Cli.php'; -Icinga\Application\Cli::start('/usr/share/icingaweb')->dispatch(); +Icinga\Application\Cli::start('/usr/share/icingaweb2')->dispatch(); diff --git a/packages/files/config/modules/doc/config.ini b/packages/files/config/modules/doc/config.ini new file mode 100644 index 000000000..80df20784 --- /dev/null +++ b/packages/files/config/modules/doc/config.ini @@ -0,0 +1,3 @@ +[documentation] +icingaweb2 = /usr/share/doc/icingaweb2/markdown +modules = /usr/share/doc/icingaweb2/modules/{module}/markdown diff --git a/packages/files/config/modules/setup/config.ini b/packages/files/config/modules/setup/config.ini new file mode 100644 index 000000000..5158aae99 --- /dev/null +++ b/packages/files/config/modules/setup/config.ini @@ -0,0 +1,2 @@ +[schema] +path = /usr/share/doc/icingaweb2/schema diff --git a/public/css/icinga/login.less b/public/css/icinga/login.less index cfae3c478..6b03b476a 100644 --- a/public/css/icinga/login.less +++ b/public/css/icinga/login.less @@ -113,18 +113,33 @@ margin-left: 5em; } - div.config-note { + p.config-note { width: 50%; padding: 1em; - margin: 5em auto 0; + margin: 0 auto 2.5em; text-align: center; color: white; background-color: @colorCritical; + + a { + color: white; + font-weight: bold; + } } - div.config-note a { - color: white; - font-weight: bold; + p.info-box { + width: 50%; + height: 2.2em; + margin: 0 auto 2.5em; + + span.icon-info { + float: left; + height: 100%; + } + + em { + text-decoration: underline; + } } } diff --git a/public/css/icinga/main-content.less b/public/css/icinga/main-content.less index 6972e95dc..e3e31b397 100644 --- a/public/css/icinga/main-content.less +++ b/public/css/icinga/main-content.less @@ -154,6 +154,7 @@ table.perfdata th { table.perfdata td { white-space: nowrap; + padding-right: 0.5em; } table.objectlist { @@ -202,3 +203,9 @@ table.benchmark { [class^="icon-"]:before, [class*=" icon-"]:before { text-decoration: none; } + +.info-box { + padding: 0.5em; + border: 1px solid lightgrey; + background-color: infobackground; +} diff --git a/public/css/icinga/menu.less b/public/css/icinga/menu.less index c8ab698a5..0f3f2691e 100644 --- a/public/css/icinga/menu.less +++ b/public/css/icinga/menu.less @@ -62,15 +62,6 @@ color: @colorPetrol; } -#menu > ul > li.active li a:focus { - color: @colorTextDefault; -} - -#menu > ul > li > a:focus { - color: @colorTextDefault; - text-shadow: none; -} - #menu > ul > li.active li a:hover { text-decoration: underline; } @@ -264,3 +255,16 @@ html.ie8 #menu input.search { input:focus { outline: none; } +/* Make focus outline properly visible */ +a:focus { + outline: dotted black 1px; +} + +/* Displaying the outline in the navigation is not possible because of the messed up link borders, + color those links instead. */ +#menu a:focus, +#menu > ul > li > a:focus, +#menu .active ul li a:focus { + color: #21b5ad; + outline: none; +} diff --git a/public/css/icinga/monitoring-colors.less b/public/css/icinga/monitoring-colors.less index 86268d2ce..1e657101f 100644 --- a/public/css/icinga/monitoring-colors.less +++ b/public/css/icinga/monitoring-colors.less @@ -195,7 +195,7 @@ tr.state.handled td.state { } /* HOVER colors */ -tr.state:hover, tr[href]:hover { +tr[href]:hover { color: black; background-color: #eee; } diff --git a/public/css/icinga/setup.less b/public/css/icinga/setup.less index 166e47ff8..9dff6fecf 100644 --- a/public/css/icinga/setup.less +++ b/public/css/icinga/setup.less @@ -176,6 +176,12 @@ margin: 0 1em 0 0; } + ul { + margin: 0; + padding-left: 1em; + list-style-type: square; + } + &.state { color: white; padding: 0.4em; @@ -214,6 +220,10 @@ } } +#setup_authentication_type p.info-box em { + text-decoration: underline; +} + #setup_ldap_discovery_confirm table { margin: 1em 0; border-collapse: separate; @@ -270,7 +280,7 @@ } } - form#setup_summary { + form.summary { clear: left; } } @@ -395,71 +405,44 @@ } } -#setup { - div.module-wizard { - width: auto; - padding: 1em; - overflow: hidden; - border: solid 1px lightgrey; +#setup_modules { + div.module { + float: left; + width: 15em; + height: 15em; + margin: 1em; + padding: 0.3em; + border: 1px solid #ccc; + background-color: snow; - div.buttons { - margin: 1.5em 0 0; + h3 { + border: none; + margin: 0.5em 0; + text-align: center; + + label { + margin: 0; + width: 15em; + cursor: pointer; + } + } + + h3 + label { + width: 13.5em; + height: 13.9em; + overflow: auto; + cursor: pointer; + font-weight: normal; + } + + input[type=checkbox] { + height: 10em; float: right; - - button[type=submit] { - padding: 0.5em; - line-height: 0.5em; - background-color: @colorPetrol; - - &:hover, &:focus, &:active { - background-color: #666; - } - } } } - div.module-menu { - font-size: 0.9em; - width: 25%; - float: right; - margin-left: 1.5em; - - p { - margin-top: 0; - - &.all-completed { - .conspicuous-state-notification; - text-align: center; - font-size: 90%; - background-color: @colorOk; - } - } - - ul { - padding-left: 1.2em; - - button { - margin: 0 0 0.8em; - padding: 0; - color: black; - border: none; - outline: none; - font-size: 90%; - background-color: white; - - &:hover { - color: #666; - cursor: pointer; - } - - &:focus, &:active { - color: #666; - } - } - - img { - margin: 0 0.5em 0.2em; - } - } + div.buttons { + padding-top: 1em; + clear: both; } -} +} \ No newline at end of file diff --git a/public/css/icinga/widgets.less b/public/css/icinga/widgets.less index 93625b0dc..e2e37d7ab 100644 --- a/public/css/icinga/widgets.less +++ b/public/css/icinga/widgets.less @@ -285,3 +285,10 @@ li li .badge { .widgetFilter li.active { background-color: #eee; } + +.sparkline { + width: 12px; + height: 12px; + position: relative; + top: 4px; +} \ No newline at end of file diff --git a/application/fonts/fontello-ifont/font/ifont.eot b/public/font/ifont.eot similarity index 100% rename from application/fonts/fontello-ifont/font/ifont.eot rename to public/font/ifont.eot diff --git a/application/fonts/fontello-ifont/font/ifont.svg b/public/font/ifont.svg similarity index 100% rename from application/fonts/fontello-ifont/font/ifont.svg rename to public/font/ifont.svg diff --git a/application/fonts/fontello-ifont/font/ifont.ttf b/public/font/ifont.ttf similarity index 100% rename from application/fonts/fontello-ifont/font/ifont.ttf rename to public/font/ifont.ttf diff --git a/application/fonts/fontello-ifont/font/ifont.woff b/public/font/ifont.woff similarity index 100% rename from application/fonts/fontello-ifont/font/ifont.woff rename to public/font/ifont.woff diff --git a/public/js/icinga/behavior/navigation.js b/public/js/icinga/behavior/navigation.js index fde043c01..b8a12064d 100644 --- a/public/js/icinga/behavior/navigation.js +++ b/public/js/icinga/behavior/navigation.js @@ -32,6 +32,15 @@ if ($outerMenu.size()) { $outerMenu.addClass('active'); } + + /* + Recreate the html content of the menu item to force the browser to update the layout, or else + the link would only be visible as active after another click or page reload in Gecko and WebKit. + + fixes #7897 + */ + $selectedMenu.html($selectedMenu.html()); + } else { // store menu state var $menus = $('#menu li.active', el); @@ -121,23 +130,26 @@ } setTimeout(function () { - if (! $li.is('li:hover')) { - return; - } - if ($li.hasClass('active')) { - return; - } + try { + if (!$li.is('li:hover')) { + return; + } + if ($li.hasClass('active')) { + return; + } + } catch(e) { /* Bypass because if IE8 */ } $li.siblings().each(function () { var $sibling = $(this); - if ($sibling.is('li:hover')) { - return; - } + try { + if ($sibling.is('li:hover')) { + return; + } + } catch(e) { /* Bypass because if IE8 */ }; if ($sibling.hasClass('hover')) { $sibling.removeClass('hover'); } }); - self.hoverElement($li); }, delay); }; @@ -152,9 +164,11 @@ } setTimeout(function () { - if ($li.is('li:hover') || $sidebar.is('sidebar:hover') ) { - return; - } + try { + if ($li.is('li:hover') || $sidebar.is('sidebar:hover')) { + return; + } + } catch(e) { /* Bypass because if IE8 */ }; $li.removeClass('hover'); $('#layout').removeClass('hoveredmenu'); }, 500); @@ -174,9 +188,11 @@ self = event.data.self; setTimeout(function () { // TODO: make this behave well together with keyboard navigation - if (! $li.is('li:hover') /*&& ! $li.find('a:focus')*/) { - $li.removeClass('hover'); - } + try { + if (!$li.is('li:hover') /*&& ! $li.find('a:focus')*/) { + $li.removeClass('hover'); + } + } catch(e) { /* Bypass because if IE8 */ } }, 300); }; Icinga.Behaviors.Navigation = Navigation; diff --git a/public/js/icinga/behavior/sparkline.js b/public/js/icinga/behavior/sparkline.js index 33cc0d34b..e0d0fb0c7 100644 --- a/public/js/icinga/behavior/sparkline.js +++ b/public/js/icinga/behavior/sparkline.js @@ -18,34 +18,33 @@ $('span.sparkline', el).each(function(i, element) { // read custom options - var $spark = $(element); - var labels = $spark.attr('labels').split('|'); - var formatted = $spark.attr('formatted').split('|'); - var tooltipChartTitle = $spark.attr('sparkTooltipChartTitle') || ''; - var format = $spark.attr('tooltipformat'); - var hideEmpty = $spark.attr('hideEmptyLabel') === 'true'; - $spark.sparkline( - 'html', - { + var $spark = $(element); + var title = $spark.attr('title'); + + if ($spark.attr('labels')) { + $spark.removeAttr('original-title'); + } + + var options; + if ($spark.hasClass('sparkline-perfdata')) { + options = { enableTagOptions: true, - tooltipFormatter: function (sparkline, options, fields) { - var out = format; - if (hideEmpty && fields.offset === 3) { - return ''; - } - var replace = { - title: tooltipChartTitle, - label: labels[fields.offset] ? labels[fields.offset] : fields.offset, - formatted: formatted[fields.offset] ? formatted[fields.offset] : '', - value: fields.value, - percent: Math.round(fields.percent * 100) / 100 - }; - $.each(replace, function(key, value) { - out = out.replace('{{' + key + '}}', value); - }); - return out; - } - }); + width: 12, + height: 12, + title: title, + disableTooltips: true + }; + $spark.sparkline('html', options); + } else if ($spark.hasClass('sparkline-multi')) { + options = { + width: 100, + height: 100, + title: title, + enableTagOptions: true + }; + $spark.sparkline('html', options); + } + }); }; diff --git a/public/js/icinga/events.js b/public/js/icinga/events.js index e7ac3e3f1..b7f2f5cee 100644 --- a/public/js/icinga/events.js +++ b/public/js/icinga/events.js @@ -482,6 +482,16 @@ targetId = 'col1'; $target = $('#' + targetId); self.icinga.ui.layout1col(); + } else if (targetId === '_right') { + // Ensure that the content is displayed in the rightmost column + $target = $el.closest('.container'); + if ($target.attr('id') === 'col1') { + // As it's not possible to detect what's preceding the current state in the + // history stack this just simulates _main in case the respective element + // is not part of the rightmost column + $target = $('#col1'); + self.icinga.ui.layout1col(); + } } else { $target = $('#' + targetId); } diff --git a/var/log/.gitkeep b/var/log/.gitkeep deleted file mode 100644 index e69de29bb..000000000
' . t('User Name Attribute') . '' . $this->data['backendConfig']['user_name_attribute'] . '
' . t('Filter Pattern') . '' . $this->data['backendConfig']['strip_username_regexp'] . '