Merge branch 'master' into feature/deduplicate-puppet-code-6842

Conflicts:
	.vagrant-puppet/manifests/default.pp
This commit is contained in:
Alexander Klimov 2014-09-11 11:39:37 +02:00
commit b82ed3d2a4
275 changed files with 7526 additions and 3781 deletions

2
.gitignore vendored
View File

@ -11,6 +11,8 @@
build/ build/
development/
# ./configure output # ./configure output
config.log config.log
autom4te.cache autom4te.cache

View File

@ -5,7 +5,7 @@
namespace Icinga\Clicommands; namespace Icinga\Clicommands;
use Icinga\Cli\Command; use Icinga\Cli\Command;
use Exception; use Icinga\Exception\IcingaException;
class WebCommand extends Command class WebCommand extends Command
{ {
@ -13,11 +13,11 @@ class WebCommand extends Command
{ {
$minVersion = '5.4.0'; $minVersion = '5.4.0';
if (version_compare(PHP_VERSION, $minVersion) < 0) { if (version_compare(PHP_VERSION, $minVersion) < 0) {
throw new Exception(sprintf( throw new IcingaException(
'You are running PHP %s, internal webserver requires %s.', 'You are running PHP %s, internal webserver requires %s.',
PHP_VERSION, PHP_VERSION,
$minVersion $minVersion
)); );
} }
$fork = $this->params->get('daemonize'); $fork = $this->params->get('daemonize');
@ -27,12 +27,12 @@ class WebCommand extends Command
// TODO: Sanity check!! // TODO: Sanity check!!
if ($socket === null) { if ($socket === null) {
$socket = '0.0.0.0:80'; $socket = '0.0.0.0:80';
// throw new Exception('Socket is required'); // throw new IcingaException('Socket is required');
} }
if ($basedir === null) { if ($basedir === null) {
$basedir = dirname(ICINGAWEB_APPDIR) . '/public'; $basedir = dirname(ICINGAWEB_APPDIR) . '/public';
if (! file_exists($basedir) || ! is_dir($basedir)) { if (! file_exists($basedir) || ! is_dir($basedir)) {
throw new Exception('Basedir is required'); throw new IcingaException('Basedir is required');
} }
} }
$basedir = realpath($basedir); $basedir = realpath($basedir);
@ -68,7 +68,7 @@ class WebCommand extends Command
{ {
$pid = pcntl_fork(); $pid = pcntl_fork();
if ($pid == -1) { if ($pid == -1) {
throw new Exception('Could not fork'); throw new IcingaException('Could not fork');
} else if ($pid) { } else if ($pid) {
echo $this->screen->colorize('[OK]') echo $this->screen->colorize('[OK]')
. " Icinga Web server forked successfully\n"; . " Icinga Web server forked successfully\n";

View File

@ -2,7 +2,6 @@
// {{{ICINGA_LICENSE_HEADER}}} // {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}} // {{{ICINGA_LICENSE_HEADER}}}
use \Zend_Config;
use Icinga\Web\Url; use Icinga\Web\Url;
use Icinga\Logger\Logger; use Icinga\Logger\Logger;
use Icinga\Config\PreservingIniWriter; use Icinga\Config\PreservingIniWriter;
@ -12,6 +11,7 @@ use Icinga\Form\Dashboard\AddUrlForm;
use Icinga\Exception\NotReadableError; use Icinga\Exception\NotReadableError;
use Icinga\Exception\ConfigurationError; use Icinga\Exception\ConfigurationError;
use Icinga\Web\Controller\ActionController; use Icinga\Web\Controller\ActionController;
use Icinga\Exception\IcingaException;
/** /**
* Handle creation, removal and displaying of dashboards, panes and components * Handle creation, removal and displaying of dashboards, panes and components
@ -42,7 +42,7 @@ class DashboardController extends ActionController
} }
$dashboard->readConfig($dashboardConfig); $dashboard->readConfig($dashboardConfig);
} catch (NotReadableError $e) { } catch (NotReadableError $e) {
Logger::error(new Exception('Cannot load dashboard configuration. An exception was thrown:', 0, $e)); Logger::error(new IcingaException('Cannot load dashboard configuration. An exception was thrown:', $e));
return null; return null;
} }
return $dashboard; return $dashboard;
@ -111,19 +111,23 @@ class DashboardController extends ActionController
*/ */
public function indexAction() public function indexAction()
{ {
$dashboard = $this->getDashboard(); $dashboard = Dashboard::load();
if ($this->_getParam('pane')) {
$pane = $this->_getParam('pane');
$dashboard->activate($pane);
}
$this->view->configPath = IcingaConfig::resolvePath(self::DEFAULT_CONFIG); if (! $dashboard->hasPanes()) {
if ($dashboard === null) {
$this->view->title = 'Dashboard'; $this->view->title = 'Dashboard';
} else { } else {
$this->view->title = $dashboard->getActivePane()->getTitle() . ' :: Dashboard'; if ($this->_getParam('pane')) {
$this->view->tabs = $dashboard->getTabs(); $pane = $this->_getParam('pane');
$dashboard->activate($pane);
}
$this->view->configPath = IcingaConfig::resolvePath(self::DEFAULT_CONFIG);
if ($dashboard === null) {
$this->view->title = 'Dashboard';
} else {
$this->view->title = $dashboard->getActivePane()->getTitle() . ' :: Dashboard';
$this->view->tabs = $dashboard->getTabs();
/* Temporarily removed /* Temporarily removed
$this->view->tabs->add( $this->view->tabs->add(
@ -135,8 +139,8 @@ class DashboardController extends ActionController
); );
*/ */
$this->view->dashboard = $dashboard; $this->view->dashboard = $dashboard;
}
} }
} }

View File

@ -4,6 +4,7 @@
// namespace Icinga\Application\Controllers; // namespace Icinga\Application\Controllers;
use Icinga\Logger\Logger;
use Icinga\Web\Controller\ActionController; use Icinga\Web\Controller\ActionController;
use Icinga\Application\Icinga; use Icinga\Application\Icinga;
@ -21,6 +22,10 @@ class ErrorController extends ActionController
{ {
$error = $this->_getParam('error_handler'); $error = $this->_getParam('error_handler');
$exception = $error->exception; $exception = $error->exception;
Logger::error($exception);
Logger::error('Stacktrace: %s', $exception->getTraceAsString());
switch ($error->type) { switch ($error->type) {
case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ROUTE: case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ROUTE:
case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER: case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER:

View File

@ -18,9 +18,12 @@ class LayoutController extends ActionController
*/ */
public function menuAction() public function menuAction()
{ {
$this->view->menuRenderer = new MenuRenderer( $this->setAutorefreshInterval(15);
Menu::fromConfig()->order(), Url::fromRequest()->without('renderLayout')->getRelativeUrl() $this->_helper->layout()->disableLayout();
);
$url = Url::fromRequest();
$menu = new MenuRenderer(Menu::load(), $url->getRelativeUrl());
$this->view->menuRenderer = $menu->useCustomRenderer();
} }
/** /**
@ -30,11 +33,11 @@ class LayoutController extends ActionController
{ {
$topbarHtmlParts = array(); $topbarHtmlParts = array();
/** @var Hook\Layout\TopBar $hook */ /** @var Hook\TopBarHook $hook */
$hook = null; $hook = null;
foreach (Hook::all('TopBar') as $hook) { foreach (Hook::all('TopBar') as $hook) {
$topbarHtmlParts[] = $hook->getHtml($this->getRequest(), $this->view); $topbarHtmlParts[] = $hook->getHtml($this->getRequest());
} }
$this->view->topbarHtmlParts = $topbarHtmlParts; $this->view->topbarHtmlParts = $topbarHtmlParts;

View File

@ -4,9 +4,12 @@
use Icinga\Module\Monitoring\Controller; use Icinga\Module\Monitoring\Controller;
use Icinga\Web\Hook; use Icinga\Web\Hook;
use Icinga\Application\Config as IcingaConfig;
use Icinga\Web\Url; use Icinga\Web\Url;
use Icinga\Data\ResourceFactory; use Icinga\Data\ResourceFactory;
use Icinga\Logger\Logger;
use Icinga\Logger\Writer\FileWriter;
use Icinga\Protocol\File\FileReader;
use \Zend_Controller_Action_Exception as ActionError;
/** /**
* Class ListController * Class ListController
@ -36,20 +39,21 @@ class ListController extends Controller
*/ */
public function applicationlogAction() public function applicationlogAction()
{ {
$this->addTitleTab('application log'); if (! Logger::writesToFile()) {
$config_ini = IcingaConfig::app()->toArray(); throw new ActionError('Site not found', 404);
if (!in_array('logging', $config_ini) || (
in_array('type', $config_ini['logging']) &&
$config_ini['logging']['type'] === 'file' &&
in_array('target', $config_ini['logging']) &&
file_exists($config_ini['logging']['target'])
)
) {
$config = ResourceFactory::getResourceConfig('logfile');
$resource = ResourceFactory::createResource($config);
$this->view->logData = $resource->select()->order('DESC')->paginate();
} else {
$this->view->logData = null;
} }
$this->addTitleTab('application log');
$pattern = '/^(?<datetime>[0-9]{4}(-[0-9]{2}){2}' // date
. 'T[0-9]{2}(:[0-9]{2}){2}([\\+\\-][0-9]{2}:[0-9]{2})?)' // time
. ' - (?<loglevel>[A-Za-z]+)' // loglevel
. ' - (?<message>.*)$/'; // message
$loggerWriter = Logger::getInstance()->getWriter();
$resource = new FileReader(new Zend_Config(array(
'filename' => $loggerWriter->getPath(),
'fields' => $pattern
)));
$this->view->logData = $resource->select()->order('DESC')->paginate();
} }
} }

View File

@ -3,9 +3,8 @@
// {{{ICINGA_LICENSE_HEADER}}} // {{{ICINGA_LICENSE_HEADER}}}
use Icinga\Web\Controller\ActionController; use Icinga\Web\Controller\ActionController;
use Icinga\Application\Icinga;
use Icinga\Web\Widget; use Icinga\Web\Widget;
use Icinga\Web\Url; use Icinga\Web\Widget\SearchDashboard;
/** /**
* Search controller * Search controller
@ -14,47 +13,13 @@ class SearchController extends ActionController
{ {
public function indexAction() public function indexAction()
{ {
$search = $this->_request->getParam('q'); $this->view->dashboard = SearchDashboard::search($this->params->get('q'));
if (! $search) {
$this->view->tabs = Widget::create('tabs')->add( // NOTE: This renders the dashboard twice. Remove this once we can catch exceptions thrown in view scripts.
'search', $this->view->dashboard->render();
array( }
'title' => $this->translate('Search'),
'url' => '/search', public function hintAction()
) {
)->activate('search');
$this->render('hint');
return;
}
$dashboard = Widget::create('dashboard')->createPane($this->translate('Search'));
$pane = $dashboard->getPane($this->translate('Search'));
$suffix = strlen($search) ? ': ' . rtrim($search, '*') . '*' : '';
$pane->addComponent(
$this->translate('Hosts') . $suffix,
Url::fromPath('monitoring/list/hosts', array(
'host_name' => $search . '*',
'sort' => 'host_severity',
'limit' => 10,
)
));
$pane->addComponent(
$this->translate('Services') . $suffix,
Url::fromPath('monitoring/list/services', array(
'service_description' => $search . '*',
'sort' => 'service_severity',
'limit' => 10,
)
));
$pane->addComponent('Hostgroups' . $suffix, Url::fromPath('monitoring/list/hostgroups', array(
'hostgroup' => $search . '*',
'limit' => 10,
)));
$pane->addComponent('Servicegroups' . $suffix, Url::fromPath('monitoring/list/servicegroups', array(
'servicegroup' => $search . '*',
'limit' => 10,
)));
$dashboard->activate($this->translate('Search'));
$this->view->dashboard = $dashboard;
$this->view->tabs = $dashboard->getTabs();
} }
} }

View File

@ -2,10 +2,11 @@
// {{{ICINGA_LICENSE_HEADER}}} // {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}} // {{{ICINGA_LICENSE_HEADER}}}
use \Zend_Controller_Action_Exception as ActionException;
use Icinga\Web\Controller\ActionController; use Icinga\Web\Controller\ActionController;
use Icinga\Application\Icinga; use Icinga\Application\Icinga;
use Icinga\Logger\Logger; use Icinga\Logger\Logger;
use Icinga\Web\FileCache;
use Zend_Controller_Action_Exception as ActionException;
/** /**
* Delivery static content to clients * Delivery static content to clients
@ -30,8 +31,25 @@ class StaticController extends ActionController
public function gravatarAction() public function gravatarAction()
{ {
$cache = FileCache::instance();
$filename = md5(strtolower(trim($this->_request->getParam('email'))));
$cacheFile = 'gravatar-' . $filename;
header('Cache-Control: public');
header('Pragma: cache');
if ($etag = $cache->etagMatchesCachedFile($cacheFile)) {
header("HTTP/1.1 304 Not Modified");
return;
}
header('Content-Type: image/jpg'); header('Content-Type: image/jpg');
$img = file_get_contents('http://www.gravatar.com/avatar/' . md5(strtolower(trim($this->_request->getParam('email')))) . '?s=200&d=mm'); if ($cache->has($cacheFile)) {
header('ETag: "' . $cache->etagForCachedFile($cacheFile) . '"');
$cache->send($cacheFile);
return;
}
$img = file_get_contents('http://www.gravatar.com/avatar/' . $filename . '?s=120&d=mm');
$cache->store($cacheFile, $img);
header('ETag: "' . $cache->etagForCachedFile($cacheFile) . '"');
echo $img; echo $img;
} }
@ -41,13 +59,12 @@ class StaticController extends ActionController
public function imgAction() public function imgAction()
{ {
$module = $this->_getParam('module_name'); $module = $this->_getParam('module_name');
// TODO: This is more than dangerous, must be fixed!!
$file = $this->_getParam('file'); $file = $this->_getParam('file');
$basedir = Icinga::app()->getModuleManager()->getModule($module)->getBaseDir(); $basedir = Icinga::app()->getModuleManager()->getModule($module)->getBaseDir();
$filePath = $basedir . '/public/img/' . $file; $filePath = realpath($basedir . '/public/img/' . $file);
if (! file_exists($filePath)) {
if (! $filePath || strpos($filePath, $basedir) !== 0) {
throw new ActionException(sprintf( throw new ActionException(sprintf(
'%s does not exist', '%s does not exist',
$filePath $filePath

View File

@ -4,8 +4,8 @@
namespace Icinga\Form\Config\Authentication; namespace Icinga\Form\Config\Authentication;
use \Zend_Config; use Zend_Config;
use \Zend_Form_Element_Checkbox; use Zend_Form_Element_Checkbox;
use Icinga\Web\Form; use Icinga\Web\Form;
use Icinga\Data\ResourceFactory; use Icinga\Data\ResourceFactory;
use Icinga\Web\Form\Decorator\HelpText; use Icinga\Web\Form\Decorator\HelpText;

View File

@ -4,8 +4,8 @@
namespace Icinga\Form\Config\Authentication; namespace Icinga\Form\Config\Authentication;
use \Exception; use Exception;
use \Zend_Config; use Zend_Config;
use Icinga\Data\ResourceFactory; use Icinga\Data\ResourceFactory;
use Icinga\Authentication\DbConnection; use Icinga\Authentication\DbConnection;
use Icinga\Authentication\Backend\DbUserBackend; use Icinga\Authentication\Backend\DbUserBackend;
@ -111,10 +111,9 @@ class DbBackendForm extends BaseBackendForm
public function isValidAuthenticationBackend() public function isValidAuthenticationBackend()
{ {
try { try {
$testConnection = ResourceFactory::createResource(ResourceFactory::getResourceConfig( $dbUserBackend = new DbUserBackend(ResourceFactory::create(
$this->getValue('backend_' . $this->filterName($this->getBackendName()) . '_resource') $this->getValue('backend_' . $this->filterName($this->getBackendName()) . '_resource')
)); ));
$dbUserBackend = new DbUserBackend($testConnection);
if ($dbUserBackend->count() < 1) { if ($dbUserBackend->count() < 1) {
$this->addErrorMessage(t("No users found under the specified database backend")); $this->addErrorMessage(t("No users found under the specified database backend"));
return false; return false;

View File

@ -4,8 +4,9 @@
namespace Icinga\Form\Config\Authentication; namespace Icinga\Form\Config\Authentication;
use \Exception; use Exception;
use \Zend_Config; use Icinga\Application\Platform;
use Zend_Config;
use Icinga\Web\Form; use Icinga\Web\Form;
use Icinga\Data\ResourceFactory; use Icinga\Data\ResourceFactory;
use Icinga\Authentication\Backend\LdapUserBackend; use Icinga\Authentication\Backend\LdapUserBackend;
@ -135,7 +136,7 @@ class LdapBackendForm extends BaseBackendForm
*/ */
public function isValidAuthenticationBackend() public function isValidAuthenticationBackend()
{ {
if (! ResourceFactory::ldapAvailable()) { if (! Platform::extensionLoaded('ldap')) {
/* /*
* It should be possible to run icingaweb without the php ldap extension, when * It should be possible to run icingaweb without the php ldap extension, when
* no ldap backends are needed. When the user tries to create an ldap backend * no ldap backends are needed. When the user tries to create an ldap backend
@ -148,7 +149,7 @@ class LdapBackendForm extends BaseBackendForm
$cfg = $this->getConfig(); $cfg = $this->getConfig();
$backendName = 'backend_' . $this->filterName($this->getBackendName()) . '_name'; $backendName = 'backend_' . $this->filterName($this->getBackendName()) . '_name';
$backendConfig = new Zend_Config($cfg[$this->getValue($backendName)]); $backendConfig = new Zend_Config($cfg[$this->getValue($backendName)]);
$backend = ResourceFactory::createResource(ResourceFactory::getResourceConfig($backendConfig->resource)); $backend = ResourceFactory::create($backendConfig->resource);
$testConn = new LdapUserBackend( $testConn = new LdapUserBackend(
$backend, $backend,
$backendConfig->user_class, $backendConfig->user_class,
@ -157,7 +158,7 @@ class LdapBackendForm extends BaseBackendForm
$testConn->assertAuthenticationPossible(); $testConn->assertAuthenticationPossible();
/* /*
if ($testConn->count() === 0) { if ($testConn->count() === 0) {
throw new Exception('No Users Found On Directory Server'); throw new IcingaException('No Users Found On Directory Server');
} }
*/ */
} catch (Exception $exc) { } catch (Exception $exc) {

View File

@ -4,7 +4,7 @@
namespace Icinga\Form\Config\Authentication; namespace Icinga\Form\Config\Authentication;
use \Zend_Config; use Zend_Config;
use Icinga\Web\Form; use Icinga\Web\Form;
/** /**

View File

@ -4,7 +4,7 @@
namespace Icinga\Form\Config; namespace Icinga\Form\Config;
use \Zend_Config; use Zend_Config;
use Icinga\Web\Form; use Icinga\Web\Form;
use Icinga\Application\Icinga; use Icinga\Application\Icinga;
use Icinga\Web\Form\Validator\WritablePathValidator; use Icinga\Web\Form\Validator\WritablePathValidator;

View File

@ -5,6 +5,7 @@
namespace Icinga\Form\Config; namespace Icinga\Form\Config;
use Exception; use Exception;
use Icinga\Application\Platform;
use Zend_Config; use Zend_Config;
use Zend_Form_Element_Checkbox; use Zend_Form_Element_Checkbox;
use Icinga\Web\Form; use Icinga\Web\Form;
@ -405,14 +406,14 @@ class ResourceForm extends Form
* in case they aren't actually used. When the user tries to create a resource that depends on an * in case they aren't actually used. When the user tries to create a resource that depends on an
* uninstalled extension, an error should be displayed. * uninstalled extension, an error should be displayed.
*/ */
if ($config->db === 'mysql' && !ResourceFactory::mysqlAvailable()) { if ($config->db === 'mysql' && ! Platform::extensionLoaded('mysql')) {
$this->addErrorMessage( $this->addErrorMessage(
t('You need to install the php extension "mysql" and the ' . t('You need to install the php extension "mysql" and the ' .
'Zend_Pdo_Mysql classes to use MySQL database resources.') 'Zend_Pdo_Mysql classes to use MySQL database resources.')
); );
return false; return false;
} }
if ($config->db === 'pgsql' && !ResourceFactory::pgsqlAvailable()) { if ($config->db === 'pgsql' && ! Platform::extensionLoaded('pgsql')) {
$this->addErrorMessage( $this->addErrorMessage(
t('You need to install the php extension "pgsql" and the ' . t('You need to install the php extension "pgsql" and the ' .
'Zend_Pdo_Pgsql classes to use PostgreSQL database resources.') 'Zend_Pdo_Pgsql classes to use PostgreSQL database resources.')

View File

@ -4,15 +4,16 @@
namespace Icinga\Form\Preference; namespace Icinga\Form\Preference;
use \DateTimeZone; use DateTimeZone;
use \Zend_Config; use Icinga\Util\TimezoneDetect;
use \Zend_Form_Element_Text; use Zend_Config;
use \Zend_Form_Element_Select; use Zend_Form_Element_Text;
use \Zend_View_Helper_DateFormat; use Zend_Form_Element_Select;
use \Icinga\Web\Form; use Zend_View_Helper_DateFormat;
use \Icinga\Web\Form\Validator\TimeFormatValidator; use Icinga\Web\Form;
use \Icinga\Web\Form\Validator\DateFormatValidator; use Icinga\Web\Form\Validator\TimeFormatValidator;
use \Icinga\Util\Translator; use Icinga\Web\Form\Validator\DateFormatValidator;
use Icinga\Util\Translator;
/** /**
* General user preferences * General user preferences
@ -69,13 +70,22 @@ class GeneralForm extends Form
*/ */
private function addTimezoneSelection(Zend_Config $cfg) private function addTimezoneSelection(Zend_Config $cfg)
{ {
$prefs = $this->getUserPreferences();
$useGlobalTimezone = $this->getRequest()->getParam('default_timezone', !$prefs->has('app.timezone'));
$detect = new TimezoneDetect();
$tzList = array(); $tzList = array();
foreach (DateTimeZone::listIdentifiers() as $tz) { foreach (DateTimeZone::listIdentifiers() as $tz) {
$tzList[$tz] = $tz; $tzList[$tz] = $tz;
} }
$helptext = 'Use the following timezone for dates and times'; $helptext = 'Use the following timezone for dates and times';
$prefs = $this->getUserPreferences();
$useGlobalTimezone = $this->getRequest()->getParam('default_timezone', !$prefs->has('app.timezone')); if ($useGlobalTimezone && $detect->success() === true) {
$helptext .= '<br />' . t('Currently your time was detected to be')
. ': '
. '<strong>' . $detect->getTimezoneName() . '</strong>';
}
$selectTimezone = new Zend_Form_Element_Select( $selectTimezone = new Zend_Form_Element_Select(
array( array(
@ -87,6 +97,7 @@ class GeneralForm extends Form
'value' => $prefs->get('app.timezone', $cfg->get('timezone', date_default_timezone_get())) 'value' => $prefs->get('app.timezone', $cfg->get('timezone', date_default_timezone_get()))
) )
); );
$this->addElement( $this->addElement(
'checkbox', 'checkbox',
'default_timezone', 'default_timezone',
@ -99,7 +110,9 @@ class GeneralForm extends Form
if ($useGlobalTimezone) { if ($useGlobalTimezone) {
$selectTimezone->setAttrib('disabled', 1); $selectTimezone->setAttrib('disabled', 1);
} }
$this->addElement($selectTimezone); $this->addElement($selectTimezone);
$this->enableAutoSubmit(array('default_timezone')); $this->enableAutoSubmit(array('default_timezone'));
} }

View File

@ -29,17 +29,17 @@ $iframeClass = $isIframe ? ' iframe' : '';
<title><?= $this->title ? $this->escape($this->title) : 'Icinga Web' ?></title> <title><?= $this->title ? $this->escape($this->title) : 'Icinga Web' ?></title>
<!-- TODO: viewport and scale settings make no sense for us, fix this --> <!-- TODO: viewport and scale settings make no sense for us, fix this -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link rel="stylesheet" href="<?= $this->href($cssfile) ?>" media="screen" type="text/css" /> <? if ($isIframe): ?>
<? if ($isIframe): ?>
<base target="_parent"/> <base target="_parent"/>
<?php else: ?> <?php else: ?>
<script type="text/javascript"> <script type="text/javascript">
(function() { (function() {
var html = document.getElementsByTagName('html')[0]; var html = document.getElementsByTagName('html')[0];
html.className = html.className.replace(/no-js/, 'js'); html.className = html.className.replace(/no-js/, 'js');
}()); }());
</script> </script>
<?php endif ?> <?php endif ?>
<link rel="stylesheet" href="<?= $this->href($cssfile) ?>" media="screen" type="text/css" />
<!-- Respond.js IE8 support of media queries --> <!-- Respond.js IE8 support of media queries -->
<!--[if lt IE 9]> <!--[if lt IE 9]>
<script src="<?= $this->baseUrl('js/vendor/respond.min.js');?>"></script> <script src="<?= $this->baseUrl('js/vendor/respond.min.js');?>"></script>

View File

@ -3,6 +3,7 @@
use Icinga\Web\Url; use Icinga\Web\Url;
use Icinga\Web\Menu; use Icinga\Web\Menu;
use Icinga\Web\MenuRenderer; use Icinga\Web\MenuRenderer;
use Icinga\Web\Widget\SearchDashboard;
// Don't render a menu for unauthenticated users unless menu is auth aware // Don't render a menu for unauthenticated users unless menu is auth aware
if (! $this->auth()->isAuthenticated()) { if (! $this->auth()->isAuthenticated()) {
@ -10,9 +11,15 @@ if (! $this->auth()->isAuthenticated()) {
} }
?> ?>
<div id="menu" data-base-target="_main"> <div
<form action="<?= $this->href('search') ?>" method="get" role="search"> id="menu" data-last-update="<?= (time() - 14) ?>000" data-base-target="_main" class="container" data-icinga-url="<?=$this->href('layout/menu');?>"
<input type="text" name="q" class="search autofocus" placeholder="<?= $this->translate('Search...') ?>" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" /> data-icinga-refresh="15"
</form> >
<?= new MenuRenderer(Menu::fromConfig()->order(), Url::fromRequest()->without('renderLayout')->getRelativeUrl()); ?> <? if (SearchDashboard::search('dummy')->getPane('search')->hasComponents()): ?>
<form action="<?= $this->href('search') ?>" method="get" role="search">
<input type="text" name="q" class="search autofocus" placeholder="<?= $this->translate('Search...') ?>"
autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" />
</form>
<? endif; ?>
<?= new MenuRenderer(Menu::load(), Url::fromRequest()->without('renderLayout')->getRelativeUrl()); ?>
</div> </div>

View File

@ -5,121 +5,191 @@
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Icinga Web 2 (0.1)\n" "Project-Id-Version: Icinga Web 2 (None)\n"
"Report-Msgid-Bugs-To: dev@icinga.org\n" "Report-Msgid-Bugs-To: dev@icinga.org\n"
"POT-Creation-Date: 2014-05-29 11:12+0000\n" "POT-Creation-Date: 2014-08-22 17:30+0200\n"
"PO-Revision-Date: 2014-05-29 13:19+0100\n" "PO-Revision-Date: 2014-08-22 17:52+0100\n"
"Last-Translator: Thomas Gelf <thomas@gelf.net>\n" "Last-Translator: Thomas Gelf <thomas@gelf.net>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
#: /usr/local/src/bugfix.master/application/views/scripts/mixedPagination.phtml:15
#, php-format
msgid "%d to %d of %d"
msgstr "%d bis %d von %d"
#: /usr/local/src/bugfix.master/application/views/scripts/pivottablePagination.phtml:9 #: /usr/local/src/bugfix.master/application/views/scripts/pivottablePagination.phtml:9
#, php-format #, php-format
msgid "%s: %d to %d of %d" msgid "%s: %d to %d of %d"
msgstr "%s: %d bis %d von %d" msgstr "%s: %d bis %d von %d"
#: /usr/local/src/bugfix.master/application/forms/Config/LoggingForm.php:117 #: /usr/local/src/bugfix.master/application/forms/Authentication/LoginForm.php:36
msgid "...and your password"
msgstr "...und dein Kennwort ein"
#: /usr/local/src/bugfix.master/library/Icinga/Web/Widget/FilterEditor.php:132
msgid "Add"
msgstr "Hinzufügen"
#: /usr/local/src/bugfix.master/library/Icinga/Web/Widget/FilterWidget.php:81
msgid "Add filter..."
msgstr "Filter hinzufügen..."
#: /usr/local/src/bugfix.master/application/controllers/AuthenticationController.php:118
msgid "All configured authentication methods failed. Please check the system log or Icinga Web 2 log for more information."
msgstr "Alle konfigurierten Authentifizierungsmethoden sind fehlgeschlagen. Bitte überprüfe das Systemlog oder jenes von Icinga Web 2 für weitere Details."
#: /usr/local/src/bugfix.master/application/forms/Config/LoggingForm.php:91
msgid "Application Prefix" msgid "Application Prefix"
msgstr "Anwendungspräfix" msgstr "Anwendungspräfix"
#: /usr/local/src/bugfix.master/application/forms/Config/Authentication/DbBackendForm.php:78 #: /usr/local/src/bugfix.master/library/Icinga/Web/Menu.php:197
#: /usr/local/src/bugfix.master/application/forms/Config/Authentication/LdapBackendForm.php:80 msgid "ApplicationLog"
msgstr "Anwendungslog"
#: /usr/local/src/bugfix.master/library/Icinga/Web/Form/notyet_FormWizard.php:31
msgid "Back"
msgstr "Zurück"
#: /usr/local/src/bugfix.master/application/forms/Config/Authentication/DbBackendForm.php:53
#: /usr/local/src/bugfix.master/application/forms/Config/Authentication/LdapBackendForm.php:55
msgid "Backend Name" msgid "Backend Name"
msgstr "Backend-Name" msgstr "Backend-Name"
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:282 #: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:257
msgid "Bind DN" msgid "Bind DN"
msgstr "Bind DN" msgstr "Bind DN"
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:294 #: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:269
msgid "Bind Password" msgid "Bind Password"
msgstr "Bind Kennwort" msgstr "Bind Kennwort"
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:358 #: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:333
#: /usr/local/src/bugfix.master/application/forms/Config/Authentication/BaseBackendForm.php:139 #: /usr/local/src/bugfix.master/application/forms/Config/Authentication/BaseBackendForm.php:114
msgid "Check this box to enforce changes without connectivity validation" msgid "Check this box to enforce changes without connectivity validation"
msgstr "Aktiviere dieses Häkchen um die Änderungen ohne Validierung der Verbindung zu speichern" msgstr "Aktiviere dieses Häkchen um die Änderungen ohne Validierung der Verbindung zu speichern"
#: /usr/local/src/bugfix.master/application/forms/Config/LoggingForm.php:73 #: /usr/local/src/bugfix.master/application/forms/Config/LoggingForm.php:47
msgid "Check this to enable logging." msgid "Check this to enable logging."
msgstr "Aktiviere dieses Häkchen um das Logging zu aktivieren." msgstr "Aktiviere dieses Häkchen um das Logging zu aktivieren."
#: /usr/local/src/bugfix.master/application/forms/Config/Authentication/LdapBackendForm.php:187 #: /usr/local/src/bugfix.master/library/Icinga/Web/Widget/FilterEditor.php:108
msgid "Click to add a filter expression to this operator"
msgstr "Hier klicken, um einen Filter-Ausdruck zu diesem Operator hinzuzufügen"
#: /usr/local/src/bugfix.master/library/Icinga/Web/Widget/FilterEditor.php:105
msgid "Click to add another operator below this one"
msgstr "Hier klicken, um unterhalb dieses Operators einen weiteren hinzuzufügen"
#: /usr/local/src/bugfix.master/library/Icinga/Web/Widget/FilterEditor.php:97
#: /usr/local/src/bugfix.master/library/Icinga/Web/Widget/FilterWidget.php:69
msgid "Click to remove this part of your filter"
msgstr "Klicken, um diesen Teil des Filters zu löschen"
#: /usr/local/src/bugfix.master/library/Icinga/Web/Menu.php:189
msgid "Configuration"
msgstr "Konfiguration"
#: /usr/local/src/bugfix.master/application/forms/Config/Authentication/LdapBackendForm.php:165
msgid "Connection Validation Failed: " msgid "Connection Validation Failed: "
msgstr "Überprüfung der Verbindung fehlgeschlagen: " msgstr "Überprüfung der Verbindung fehlgeschlagen: "
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:477 #: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:452
msgid "Connectivity validation failed, connection to the given resource not possible." msgid "Connectivity validation failed, connection to the given resource not possible."
msgstr "Überprüfung fehlgeschlagen, konnte keine Verbindung zu der angegebenen Ressource herstellen." msgstr "Überprüfung fehlgeschlagen, konnte keine Verbindung zu der angegebenen Ressource herstellen."
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:454 #: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:429
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:470 #: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:445
msgid "Connectivity validation failed, the provided file does not exist." msgid "Connectivity validation failed, the provided file does not exist."
msgstr "Überprüfung fehlgeschlagen, die angegebene Datei existiert nicht." msgstr "Überprüfung fehlgeschlagen, die angegebene Datei existiert nicht."
#: /usr/local/src/bugfix.master/application/forms/Config/Authentication/DbBackendForm.php:90 #: /usr/local/src/bugfix.master/application/controllers/AuthenticationController.php:59
msgid "Could not read your authentiction.ini, no authentication methods are available."
msgstr "Deine authentication.ini konnte nicht gelesen werden, darum sind keine Authentifizierungsmethoden verfügbar."
#: /usr/local/src/bugfix.master/application/layouts/scripts/body.phtml:31
#: /usr/local/src/bugfix.master/library/Icinga/Web/Menu.php:175
msgid "Dashboard"
msgstr "Dashboard"
#: /usr/local/src/bugfix.master/application/forms/Config/Authentication/DbBackendForm.php:65
msgid "Database Connection" msgid "Database Connection"
msgstr "Datenbankverbindung" msgstr "Datenbankverbindung"
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:183 #: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:158
msgid "Database Name" msgid "Database Name"
msgstr "Datenbankname" msgstr "Datenbankname"
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:144 #: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:119
msgid "Database Type" msgid "Database Type"
msgstr "Datenbanktyp" msgstr "Datenbanktyp"
#: /usr/local/src/bugfix.master/application/forms/Config/LoggingForm.php:89 #: /usr/local/src/bugfix.master/application/forms/Config/LoggingForm.php:63
msgid "Debug" msgid "Debug"
msgstr "Debug" msgstr "Debug"
#: /usr/local/src/bugfix.master/application/forms/Config/GeneralForm.php:185 #: /usr/local/src/bugfix.master/application/forms/Config/GeneralForm.php:101
msgid "Default Language" msgid "Default Language"
msgstr "Standardsprache" msgstr "Standardsprache"
#: /usr/local/src/bugfix.master/application/controllers/ErrorController.php:62 #: /usr/local/src/bugfix.master/application/controllers/ErrorController.php:36
#, php-format #, php-format
msgid "Enabling the \"%s\" module might help!" msgid "Enabling the \"%s\" module might help!"
msgstr "Das Modul \"%s\" zu aktivieren könnte helfen!" msgstr "Das Modul \"%s\" zu aktivieren könnte helfen!"
#: /usr/local/src/bugfix.master/application/forms/Config/LoggingForm.php:86 #: /usr/local/src/bugfix.master/application/forms/Config/LoggingForm.php:60
msgid "Error" msgid "Error"
msgstr "Fehler" msgstr "Fehler"
#: /usr/local/src/bugfix.master/application/forms/Config/LoggingForm.php:139 #: /usr/local/src/bugfix.master/library/Icinga/Web/Widget/FilterEditor.php:109
msgid "Expression"
msgstr "Ausdruck"
#: /usr/local/src/bugfix.master/application/forms/Config/LoggingForm.php:113
msgid "Facility" msgid "Facility"
msgstr "Facility" msgstr "Facility"
#: /usr/local/src/bugfix.master/application/forms/Config/LoggingForm.php:102 #: /usr/local/src/bugfix.master/application/controllers/PreferenceController.php:55
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:383 #, php-format
msgid "Failed to persist preferences. (%s)"
msgstr "Persistierung der Einstellungen fehlgeschlagen. (%s)"
#: /usr/local/src/bugfix.master/application/forms/Config/LoggingForm.php:76
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:358
msgid "File" msgid "File"
msgstr "Datei" msgstr "Datei"
#: /usr/local/src/bugfix.master/application/forms/Config/LoggingForm.php:155 #: /usr/local/src/bugfix.master/application/forms/Config/LoggingForm.php:129
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:220 #: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:195
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:231 #: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:206
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:308 #: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:283
msgid "Filepath" msgid "Filepath"
msgstr "Dateipfad" msgstr "Dateipfad"
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:357 #: /usr/local/src/bugfix.master/library/Icinga/Web/Widget/FilterWidget.php:90
#: /usr/local/src/bugfix.master/application/forms/Config/Authentication/BaseBackendForm.php:138 msgid "Filter this list"
msgstr "Diese Liste filtern"
#: /usr/local/src/bugfix.master/library/Icinga/Web/Widget/FilterWidget.php:94
msgid "Filtered"
msgstr "Gefiltert"
#: /usr/local/src/bugfix.master/library/Icinga/Web/Form/notyet_FormWizard.php:32
msgid "Finish"
msgstr "Fertigstellen"
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:332
#: /usr/local/src/bugfix.master/application/forms/Config/Authentication/BaseBackendForm.php:113
msgid "Force Changes" msgid "Force Changes"
msgstr "Änderungen erzwingen" msgstr "Änderungen erzwingen"
#: /usr/local/src/bugfix.master/library/Icinga/Web/Form/notyet_QuickForm.php:147
msgid "Form has successfully been sent"
msgstr "Das Formular wurde erfolgreich versendet"
#: /usr/local/src/bugfix.master/application/views/scripts/search/hint.phtml:7 #: /usr/local/src/bugfix.master/application/views/scripts/search/hint.phtml:7
msgid "Hint" msgid "Hint"
msgstr "Hinweis" msgstr "Hinweis"
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:160 #: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:135
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:260 #: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:235
msgid "Host" msgid "Host"
msgstr "Host" msgstr "Host"
@ -132,165 +202,183 @@ msgstr "Hosts"
msgid "I'm ready to search, waiting for your input" msgid "I'm ready to search, waiting for your input"
msgstr "Ich bin bereit zur Suche, warte auf deine Eingabe" msgstr "Ich bin bereit zur Suche, warte auf deine Eingabe"
#: /usr/local/src/bugfix.master/application/controllers/AuthenticationController.php:63 #: /usr/local/src/bugfix.master/application/controllers/AuthenticationController.php:40
#: /usr/local/src/bugfix.master/application/views/scripts/authentication/login.phtml:8 #: /usr/local/src/bugfix.master/application/views/scripts/authentication/login.phtml:8
msgid "Icingaweb Login" msgid "Icingaweb Login"
msgstr "Icingaweb Anmeldung" msgstr "Icingaweb Anmeldung"
#: /usr/local/src/bugfix.master/application/views/scripts/authentication/logout.phtml:17 #: /usr/local/src/bugfix.master/application/views/scripts/authentication/logout.phtml:14
msgid "If this message does not disappear, it might be necessary to quit the current session manually by clearing the cache, or by closing the current browser session." msgid "If this message does not disappear, it might be necessary to quit the current session manually by clearing the cache, or by closing the current browser session."
msgstr "Wenn diese Nachricht nicht verschwindet könnte es nötig sein die aktuelle Sitzung manuell zu beenden indem der Cache gelöscht order die Browsersitzung geschlossen wird." msgstr "Wenn diese Nachricht nicht verschwindet könnte es nötig sein die aktuelle Sitzung manuell zu beenden indem der Cache gelöscht order die Browsersitzung geschlossen wird."
#: /usr/local/src/bugfix.master/application/controllers/AuthenticationController.php:118 #: /usr/local/src/bugfix.master/application/controllers/AuthenticationController.php:131
msgid "Incorrect username or password" msgid "Incorrect username or password"
msgstr "Benutzername oder Kennwort ungültig" msgstr "Benutzername oder Kennwort ungültig"
#: /usr/local/src/bugfix.master/application/forms/Config/LoggingForm.php:88 #: /usr/local/src/bugfix.master/application/forms/Config/LoggingForm.php:62
msgid "Information" msgid "Information"
msgstr "Information" msgstr "Information"
#: /usr/local/src/bugfix.master/library/Icinga/Web/Wizard/Wizard.php:337 #: /usr/local/src/bugfix.master/application/forms/Config/Authentication/LdapBackendForm.php:67
#: /usr/local/src/bugfix.master/library/Icinga/Web/Wizard/Wizard.php:380
msgid "Install"
msgstr "Installieren"
#: /usr/local/src/bugfix.master/application/views/scripts/install/index.phtml:29
msgid "Installation"
msgstr "Installation"
#: /usr/local/src/bugfix.master/application/forms/Config/Authentication/LdapBackendForm.php:92
msgid "LDAP Resource" msgid "LDAP Resource"
msgstr "LDAP Ressource" msgstr "LDAP Ressource"
#: /usr/local/src/bugfix.master/application/forms/Config/Authentication/LdapBackendForm.php:115 #: /usr/local/src/bugfix.master/application/forms/Config/Authentication/LdapBackendForm.php:90
msgid "LDAP User Name Attribute" msgid "LDAP User Name Attribute"
msgstr "LDAP-Attribut für Benutzername" msgstr "LDAP-Attribut für Benutzername"
#: /usr/local/src/bugfix.master/application/forms/Config/Authentication/LdapBackendForm.php:104 #: /usr/local/src/bugfix.master/application/forms/Config/Authentication/LdapBackendForm.php:79
msgid "LDAP User Object Class" msgid "LDAP User Object Class"
msgstr "LDAP Objektklasse für Benutzer" msgstr "LDAP Objektklasse für Benutzer"
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:232 #: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:207
msgid "Location of your icinga objects.cache file" msgid "Location of your icinga objects.cache file"
msgstr "Pfad zur Datei objects.cache von Icinga" msgstr "Pfad zur Datei objects.cache von Icinga"
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:221 #: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:196
msgid "Location of your icinga status.dat file" msgid "Location of your icinga status.dat file"
msgstr "Pfad zur Datei status.dat von Icinga" msgstr "Pfad zur Datei status.dat von Icinga"
#: /usr/local/src/bugfix.master/application/controllers/InstallController.php:69 #: /usr/local/src/bugfix.master/application/forms/Config/LoggingForm.php:46
msgid "Logging"
msgstr "Logging"
#: /usr/local/src/bugfix.master/application/forms/Config/LoggingForm.php:72
msgid "Logging Enabled" msgid "Logging Enabled"
msgstr "Logging aktiv" msgstr "Logging aktiv"
#: /usr/local/src/bugfix.master/application/forms/Config/LoggingForm.php:82 #: /usr/local/src/bugfix.master/application/forms/Config/LoggingForm.php:56
msgid "Logging Level" msgid "Logging Level"
msgstr "Log-Level" msgstr "Log-Level"
#: /usr/local/src/bugfix.master/application/forms/Config/LoggingForm.php:98 #: /usr/local/src/bugfix.master/application/forms/Config/LoggingForm.php:72
msgid "Logging Type" msgid "Logging Type"
msgstr "Logging-Typ" msgstr "Logging-Typ"
#: /usr/local/src/bugfix.master/application/views/scripts/authentication/logout.phtml:15 #: /usr/local/src/bugfix.master/application/views/scripts/authentication/logout.phtml:12
msgid "Logging out..." msgid "Logging out..."
msgstr "Abmelden..." msgstr "Abmelden..."
#: /usr/local/src/bugfix.master/application/views/scripts/authentication/logout.phtml:28 #: /usr/local/src/bugfix.master/application/views/scripts/authentication/logout.phtml:21
msgid "Login" msgid "Login"
msgstr "Anmelden" msgstr "Anmelden"
#: /usr/local/src/bugfix.master/application/layouts/scripts/body.phtml:39
#: /usr/local/src/bugfix.master/application/layouts/scripts/parts/topbar.phtml:35 #: /usr/local/src/bugfix.master/application/layouts/scripts/parts/topbar.phtml:35
#: /usr/local/src/bugfix.master/library/Icinga/Web/Menu.php:202
msgid "Logout" msgid "Logout"
msgstr "Abmelden" msgstr "Abmelden"
#: /usr/local/src/bugfix.master/application/views/scripts/authentication/logout.phtml:64 #: /usr/local/src/bugfix.master/application/views/scripts/authentication/logout.phtml:43
msgid "Logout not possible, it may be necessary to quit the session manually by clearing the cache, or closing the current browser session. Error: "
msgstr ""
#: /usr/local/src/bugfix.master/application/views/scripts/authentication/logout.phtml:69
msgid "Logout successful!" msgid "Logout successful!"
msgstr "Abmelden erfolgreich!" msgstr "Abmelden erfolgreich!"
#: /usr/local/src/bugfix.master/application/forms/Config/Authentication/ReorderForm.php:137 #: /usr/local/src/bugfix.master/library/Icinga/Web/Widget/FilterEditor.php:235
msgid "Move down in authentication order" #: /usr/local/src/bugfix.master/library/Icinga/Web/Widget/FilterWidget.php:95
msgstr "" msgid "Modify this filter"
msgstr "Diesen Filter bearbeiten"
#: /usr/local/src/bugfix.master/application/forms/Config/Authentication/ReorderForm.php:111 #: /usr/local/src/bugfix.master/library/Icinga/Web/Menu.php:193
msgid "Modules"
msgstr "Module"
#: /usr/local/src/bugfix.master/application/forms/Config/Authentication/ReorderForm.php:112
msgid "Move down in authentication order"
msgstr "In der Authentifizierungsreihenfolge nach unten schieben"
#: /usr/local/src/bugfix.master/application/forms/Config/Authentication/ReorderForm.php:86
msgid "Move up in authentication order" msgid "Move up in authentication order"
msgstr "" msgstr "In der Authentifizierungsreihenfolge nach oben schieben"
#: /usr/local/src/bugfix.master/application/views/scripts/pivottablePagination.phtml:16 #: /usr/local/src/bugfix.master/application/views/scripts/pivottablePagination.phtml:16
msgid "Navigation" msgid "Navigation"
msgstr "Navigation" msgstr "Navigation"
#: /usr/local/src/bugfix.master/application/views/scripts/mixedPagination.phtml:83
#: /usr/local/src/bugfix.master/application/views/scripts/mixedPagination.phtml:86 #: /usr/local/src/bugfix.master/application/views/scripts/mixedPagination.phtml:86
#: /usr/local/src/bugfix.master/library/Icinga/Web/Wizard/Wizard.php:337 #: /usr/local/src/bugfix.master/application/views/scripts/mixedPagination.phtml:89
#: /usr/local/src/bugfix.master/library/Icinga/Web/Wizard/Wizard.php:380 #: /usr/local/src/bugfix.master/library/Icinga/Web/Form/notyet_FormWizard.php:30
msgid "Next" msgid "Next"
msgstr "Weiter" msgstr "Weiter"
#: /usr/local/src/bugfix.master/application/forms/Config/Authentication/DbBackendForm.php:144 #: /usr/local/src/bugfix.master/application/controllers/AuthenticationController.php:110
msgid "No users found under the specified database backend" msgid "No authentication methods available. Did you create authentication.ini when installing Icinga Web 2?"
msgstr "" msgstr "Keine Authentifizierungsmethode verfügbar. Hast du beim Installieren von Icinga Web 2 eine authentication.ini erstellt?"
#: /usr/local/src/bugfix.master/application/controllers/ErrorController.php:59 #: /usr/local/src/bugfix.master/application/forms/Config/Authentication/DbBackendForm.php:119
msgid "No users found under the specified database backend"
msgstr "Im konfigurierten Datenbankbackend wurden keine Benutzer gefunden"
#: /usr/local/src/bugfix.master/library/Icinga/Web/Widget/FilterEditor.php:106
msgid "Operator"
msgstr "Operator"
#: /usr/local/src/bugfix.master/application/views/scripts/mixedPagination.phtml:33
msgid "Page"
msgstr "Seite"
#: /usr/local/src/bugfix.master/application/controllers/ErrorController.php:33
msgid "Page not found." msgid "Page not found."
msgstr "Seite nicht gefunden." msgstr "Seite nicht gefunden."
#: /usr/local/src/bugfix.master/application/forms/Authentication/LoginForm.php:65 #: /usr/local/src/bugfix.master/application/views/scripts/mixedPagination.phtml:12
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:206 msgid "Pagination"
msgstr "Seitennavigation"
#: /usr/local/src/bugfix.master/application/forms/Authentication/LoginForm.php:35
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:181
msgid "Password" msgid "Password"
msgstr "Kennwort" msgstr "Kennwort"
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:319 #: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:294
msgid "Pattern" msgid "Pattern"
msgstr "Muster" msgstr "Muster"
#: /usr/local/src/bugfix.master/library/Icinga/Web/Form/Element/Number.php:61 #: /usr/local/src/bugfix.master/library/Icinga/Web/Form/Element/Number.php:36
msgid "Please enter a number." msgid "Please enter a number."
msgstr "Bitte eine Nummer eingeben." msgstr "Bitte eine Nummer eingeben."
#: /usr/local/src/bugfix.master/application/forms/Authentication/LoginForm.php:25
msgid "Please enter your username..."
msgstr "Bitte gib deinen Benutzernamen..."
#: /usr/local/src/bugfix.master/application/controllers/AuthenticationController.php:126
msgid "Please note that not all authentication methods where available. Check the system log or Icinga Web 2 log for more information."
msgstr "Beachte bitte dass nicht alle Authentifizierungsmethoden verfügbar waren. Überprüfe das Systemlog oder jenes von Icinga Web 2 für weitere Informationen."
#: /usr/local/src/bugfix.master/application/views/scripts/search/hint.phtml:8 #: /usr/local/src/bugfix.master/application/views/scripts/search/hint.phtml:8
msgid "Please use the asterisk (*) as a placeholder for wildcard searches. For convenience I'll always add a wildcard after the last character you typed." msgid "Please use the asterisk (*) as a placeholder for wildcard searches. For convenience I'll always add a wildcard after the last character you typed."
msgstr "Bitte benutze das Sternchen (*) als Jokerzeichen für eine Suche mit Platzhaltern. Der Einfachheit halber hänge ich immer einen Platzhalter hinter das letzte von dir getippte Zeichen." msgstr "Bitte benutze das Sternchen (*) als Jokerzeichen für eine Suche mit Platzhaltern. Der Einfachheit halber hänge ich immer einen Platzhalter hinter das letzte von dir getippte Zeichen."
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:171 #: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:146
msgid "Port" msgid "Port"
msgstr "Port" msgstr "Port"
#: /usr/local/src/bugfix.master/application/layouts/scripts/body.phtml:38
#: /usr/local/src/bugfix.master/application/layouts/scripts/parts/topbar.phtml:32 #: /usr/local/src/bugfix.master/application/layouts/scripts/parts/topbar.phtml:32
#: /usr/local/src/bugfix.master/library/Icinga/Web/Menu.php:185
msgid "Preferences" msgid "Preferences"
msgstr "Einstellungen" msgstr "Einstellungen"
#: /usr/local/src/bugfix.master/application/views/scripts/mixedPagination.phtml:45 #: /usr/local/src/bugfix.master/application/controllers/PreferenceController.php:48
msgid "Preferences updated successfully"
msgstr "Einstellungen erfolgreich aktualisiert"
#: /usr/local/src/bugfix.master/application/views/scripts/mixedPagination.phtml:48 #: /usr/local/src/bugfix.master/application/views/scripts/mixedPagination.phtml:48
#: /usr/local/src/bugfix.master/application/views/scripts/mixedPagination.phtml:51
msgid "Prev" msgid "Prev"
msgstr "Zurück" msgstr "Zurück"
#: /usr/local/src/bugfix.master/library/Icinga/Web/Wizard/Wizard.php:326 #: /usr/local/src/bugfix.master/library/Icinga/Web/Widget/FilterWidget.php:99
#: /usr/local/src/bugfix.master/library/Icinga/Web/Wizard/Wizard.php:367 msgid "Remove this filter"
msgid "Previous" msgstr "Diesen Filter entfernen"
msgstr "Vorheriges"
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:333 #: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:308
msgid "Resource Name" msgid "Resource Name"
msgstr "" msgstr "Ressourcename"
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:375 #: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:350
msgid "Resource Type" msgid "Resource Type"
msgstr "" msgstr "Ressourcetyp"
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:271 #: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:246
msgid "Root DN" msgid "Root DN"
msgstr "Wurzel-DN" msgstr "Wurzel-DN"
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:379 #: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:354
msgid "SQL Database" msgid "SQL Database"
msgstr "SQL Datenbank" msgstr "SQL Datenbank"
@ -301,187 +389,241 @@ msgstr "SQL Datenbank"
msgid "Search" msgid "Search"
msgstr "Suche" msgstr "Suche"
#: /usr/local/src/bugfix.master/application/layouts/scripts/parts/navigation.phtml:17 #: /usr/local/src/bugfix.master/application/layouts/scripts/parts/navigation.phtml:15
msgid "Search..." msgid "Search..."
msgstr "Suche..." msgstr "Suche..."
#: /usr/local/src/bugfix.master/application/forms/Config/GeneralForm.php:189 #: /usr/local/src/bugfix.master/library/Icinga/Web/Form/Validator/notyet_CsrfTokenValidator.php:20
msgid "Security check failed, please submit your form again"
msgstr "Sicherheitscheck fehlgeschlagen, bitte sende das Formular erneut ab"
#: /usr/local/src/bugfix.master/application/forms/Config/GeneralForm.php:105
msgid "Select the language to use by default. Can be overwritten by a user in his preferences." msgid "Select the language to use by default. Can be overwritten by a user in his preferences."
msgstr "" msgstr "Die zu benutzende Standard-Sprache. Kann von Benutzern in deren Einstellungen überschrieben werden."
#: /usr/local/src/bugfix.master/application/controllers/SearchController.php:41 #: /usr/local/src/bugfix.master/application/controllers/SearchController.php:41
#: /usr/local/src/bugfix.master/application/views/scripts/pivottablePagination.phtml:34 #: /usr/local/src/bugfix.master/application/views/scripts/pivottablePagination.phtml:34
msgid "Services" msgid "Services"
msgstr "Services" msgstr "Services"
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:245 #: /usr/local/src/bugfix.master/library/Icinga/Web/Widget/Limiter.php:84
#, php-format
msgid "Show %s rows on one page"
msgstr "Zeige %s Zeilen pro Seite"
#: /usr/local/src/bugfix.master/application/views/scripts/mixedPagination.phtml:16
#, php-format
msgid "Show rows %d to %d of %d"
msgstr "Zeige die Zeilen %d bis %d von %d"
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:220
msgid "Socket" msgid "Socket"
msgstr "" msgstr "Socket"
#: /usr/local/src/bugfix.master/application/forms/Config/LoggingForm.php:140 #: /usr/local/src/bugfix.master/application/views/scripts/config/module.phtml:22
msgid "State"
msgstr "Status"
#: /usr/local/src/bugfix.master/library/Icinga/Web/Menu.php:181
msgid "System"
msgstr "System"
#: /usr/local/src/bugfix.master/application/views/scripts/authentication/login.phtml:4
msgid "The Icinga logo"
msgstr "Das Icinga Logo"
#: /usr/local/src/bugfix.master/application/forms/Config/LoggingForm.php:114
msgid "The Syslog facility to utilize." msgid "The Syslog facility to utilize."
msgstr "" msgstr "Die zu benutzende Syslog-Facility"
#: /usr/local/src/bugfix.master/application/forms/Config/Authentication/LdapBackendForm.php:116 #: /usr/local/src/bugfix.master/application/forms/Config/Authentication/LdapBackendForm.php:91
msgid "The attribute name used for storing the user name on the ldap server" msgid "The attribute name used for storing the user name on the ldap server"
msgstr "" msgstr "Der Attributname welcher benutzt wird, um Benutzernamen auf dem LDAP-Server abzulegen"
#: /usr/local/src/bugfix.master/application/forms/Config/Authentication/DbBackendForm.php:91 #: /usr/local/src/bugfix.master/application/forms/Config/Authentication/DbBackendForm.php:66
msgid "The database connection to use for authenticating with this provider" msgid "The database connection to use for authenticating with this provider"
msgstr "" msgstr "Die Datenbankverbindung, welche zur Authentifizierung mit diesem Provider genutzt werden soll"
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:309 #: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:284
msgid "The filename to fetch information from" msgid "The filename to fetch information from"
msgstr "" msgstr "Die Datei aus welcher Informationen gelesen werden sollen"
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:161 #: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:136
msgid "The hostname of the database." msgid "The hostname of the database."
msgstr "" msgstr "Der Hostname der Datenbank."
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:261 #: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:236
msgid "The hostname or address of the LDAP server to use for authentication" msgid "The hostname or address of the LDAP server to use for authentication"
msgstr "" msgstr "Der Hostname oder die IP-Adresse des LDAP-Servers der zur Authentifizierung genutzt werden soll"
#: /usr/local/src/bugfix.master/application/forms/Config/LoggingForm.php:156 #: /usr/local/src/bugfix.master/application/forms/Config/LoggingForm.php:130
msgid "The logfile to write messages to." msgid "The logfile to write messages to."
msgstr "" msgstr "Das Logfile in welches Nachrichten geschrieben werden sollen."
#: /usr/local/src/bugfix.master/application/forms/Config/LoggingForm.php:83 #: /usr/local/src/bugfix.master/application/forms/Config/LoggingForm.php:57
msgid "The maximum loglevel to emit." msgid "The maximum loglevel to emit."
msgstr "" msgstr "Loglevel bis zu welchem Nachrichten ausgegeben werden sollen."
#: /usr/local/src/bugfix.master/application/forms/Config/LoggingForm.php:118 #: /usr/local/src/bugfix.master/application/forms/Config/LoggingForm.php:92
msgid "The name of the application by which to prefix syslog messages." msgid "The name of the application by which to prefix syslog messages."
msgstr "" msgstr "Der Anwendungsname welcher Syslog-Nachrichten vorangestellt werden soll."
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:184 #: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:159
msgid "The name of the database to use" msgid "The name of the database to use"
msgstr "" msgstr "Der Name der zu benutzenden Datenbank"
#: /usr/local/src/bugfix.master/application/forms/Config/Authentication/LdapBackendForm.php:81 #: /usr/local/src/bugfix.master/application/forms/Config/Authentication/LdapBackendForm.php:56
msgid "The name of this authentication backend" msgid "The name of this authentication backend"
msgstr "" msgstr "Der Name dieses Authentifizierungsbackends"
#: /usr/local/src/bugfix.master/application/forms/Config/Authentication/DbBackendForm.php:79 #: /usr/local/src/bugfix.master/application/forms/Config/Authentication/DbBackendForm.php:54
msgid "The name of this authentication provider" msgid "The name of this authentication provider"
msgstr "" msgstr "Der Name dieses Authentifizierungsproviders"
#: /usr/local/src/bugfix.master/application/forms/Config/Authentication/LdapBackendForm.php:105 #: /usr/local/src/bugfix.master/application/forms/Config/Authentication/LdapBackendForm.php:80
msgid "The object class used for storing users on the ldap server" msgid "The object class used for storing users on the ldap server"
msgstr "" msgstr "Die Objekt-Klasse welche benutzt wird, um Benutzer auf diesem LDAP-Server abzulegen"
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:207 #: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:182
msgid "The password to use for authentication" msgid "The password to use for authentication"
msgstr "" msgstr "Das Kennwort welche zur Authentifizierung benutzt werden soll"
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:270
msgid "The password to use for querying the ldap server"
msgstr "Das Kennwort welches zum Abfragen des LDAP-Servers benutzt werden soll"
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:221
msgid "The path to your livestatus socket used for querying monitoring data"
msgstr "Der Pfad zu deinem Live-Status Socket, über welchen Monitoring-Daten abgefragt werden sollen"
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:247
msgid "The path where users can be found on the ldap server"
msgstr "Der Pfad unter welchem Benutzer auf diesem LDAP-Server gefunden werden können."
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:147
msgid "The port to use."
msgstr "Der zu benutzende Port."
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:295 #: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:295
msgid "The password to use for querying the ldap server"
msgstr ""
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:246
msgid "The path to your livestatus socket used for querying monitoring data"
msgstr ""
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:272
msgid "The path where users can be found on the ldap server"
msgstr ""
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:172
msgid "The port to use."
msgstr ""
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:320
msgid "The regular expression by which to identify columns" msgid "The regular expression by which to identify columns"
msgstr "" msgstr "Der zu benutzende reguläre Ausdruck, mit welchem Spalten identifiziert werden können"
#: /usr/local/src/bugfix.master/application/forms/Config/Authentication/LdapBackendForm.php:93 #: /usr/local/src/bugfix.master/application/forms/Config/Authentication/LdapBackendForm.php:68
msgid "The resource to use for authenticating with this provider" msgid "The resource to use for authenticating with this provider"
msgstr "" msgstr "Die Resource die zum Authentifizieren mit diesem Provider genutzt werden soll"
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:145 #: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:120
msgid "The type of SQL database you want to create." msgid "The type of SQL database you want to create."
msgstr "" msgstr "Der Typ der zu benutzenden SQL Datenbank."
#: /usr/local/src/bugfix.master/application/forms/Config/LoggingForm.php:99 #: /usr/local/src/bugfix.master/application/forms/Config/LoggingForm.php:73
msgid "The type of logging to utilize." msgid "The type of logging to utilize."
msgstr "" msgstr "Der Typ des zu benutzenden Loggings."
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:376 #: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:351
msgid "The type of resource" msgid "The type of resource"
msgstr "" msgstr "Der Typ der Ressource"
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:334 #: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:309
msgid "The unique name of this resource" msgid "The unique name of this resource"
msgstr "" msgstr "Der eindeutige Name dieser Resource"
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:283 #: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:258
msgid "The user dn to use for querying the ldap server" msgid "The user dn to use for querying the ldap server"
msgstr "" msgstr "Die DN des Benutzers mit welchem dieser LDAP-Server befragt werden soll"
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:195 #: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:170
msgid "The user name to use for authentication." msgid "The user name to use for authentication."
msgstr "" msgstr "Der zur Authentifizierung zu benutzende Benutzername."
#: /usr/local/src/bugfix.master/application/views/scripts/config/module.phtml:6 #: /usr/local/src/bugfix.master/application/views/scripts/config/module.phtml:6
msgid "There is no such module installed." msgid "There is no such module installed."
msgstr "Gegenwärtig ist kein solches Modul installiert." msgstr "Gegenwärtig ist kein solches Modul installiert."
#: /usr/local/src/bugfix.master/application/views/scripts/config/module.phtml:32 #: /usr/local/src/bugfix.master/application/views/scripts/config/module.phtml:46
msgid "This module has no dependencies" msgid "This module has no dependencies"
msgstr "Dieses Modul hat keine Abhängigkeiten" msgstr "Dieses Modul hat keine Abhängigkeiten"
#: /usr/local/src/bugfix.master/library/Icinga/Application/Modules/Module.php:383 #: /usr/local/src/bugfix.master/library/Icinga/Application/Modules/Module.php:435
msgid "This module has no description" msgid "This module has no description"
msgstr "Dieses Modul hat keine Beschreibung" msgstr "Dieses Modul hat keine Beschreibung"
#: /usr/local/src/bugfix.master/application/forms/Preference/GeneralForm.php:100 #: /usr/local/src/bugfix.master/application/views/scripts/config/devtools.phtml:5
msgid "UI Debug"
msgstr "UI Debug"
#: /usr/local/src/bugfix.master/application/forms/Preference/GeneralForm.php:43
msgid "Use Default Language" msgid "Use Default Language"
msgstr "Standardsprache verwenden" msgstr "Standardsprache verwenden"
#: /usr/local/src/bugfix.master/application/forms/Preference/GeneralForm.php:109 #: /usr/local/src/bugfix.master/application/forms/Preference/GeneralForm.php:52
msgid "Use the following language to display texts and messages" msgid "Use the following language to display texts and messages"
msgstr "" msgstr "Die folgende Sprache benutzen, um Texte und Nachrichten anzuzeigen"
#: /usr/local/src/bugfix.master/application/forms/Authentication/LoginForm.php:57 #: /usr/local/src/bugfix.master/application/forms/Authentication/LoginForm.php:24
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:194 #: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:169
msgid "Username" msgid "Username"
msgstr "Benutzername" msgstr "Benutzername"
#: /usr/local/src/bugfix.master/application/forms/Config/Authentication/LdapBackendForm.php:169 #: /usr/local/src/bugfix.master/application/forms/Config/Authentication/LdapBackendForm.php:144
msgid "Using ldap is not possible, the php extension \"ldap\" is not installed." msgid "Using ldap is not possible, the php extension \"ldap\" is not installed."
msgstr "" msgstr "Es ist nicht möglich, LDAP zu benutzen, da die PHP-Erweiterung \"LDAP\" nicht installiert ist."
#: /usr/local/src/bugfix.master/application/forms/Config/Authentication/DbBackendForm.php:148 #: /usr/local/src/bugfix.master/application/forms/Config/Authentication/DbBackendForm.php:123
#, php-format #, php-format
msgid "Using the specified backend failed: %s" msgid "Using the specified backend failed: %s"
msgstr "" msgstr "Die angegebene Datenbank zu benutzen war nicht möglich: %s"
#: /usr/local/src/bugfix.master/application/forms/Config/LoggingForm.php:87 #: /usr/local/src/bugfix.master/application/forms/Config/LoggingForm.php:61
msgid "Warning" msgid "Warning"
msgstr "Warnung" msgstr "Warnung"
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:435 #: /usr/local/src/bugfix.master/application/views/scripts/dashboard/index.phtml:13
msgid "We tried to load a dashboard configuration with no success. Please have look that the configuration does exist:"
msgstr "Der Versuch die Dashboard-Konfiguration zu laden war nicht erfolgreich. Bitte stelle sicher, dass die folgende Konfigurationsdatei existiert:"
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:410
msgid "You need to install the php extension \"mysql\" and the Zend_Pdo_Mysql classes to use MySQL database resources." msgid "You need to install the php extension \"mysql\" and the Zend_Pdo_Mysql classes to use MySQL database resources."
msgstr "" msgstr "Um MySQL Datenbank-Ressourcen nutzen zu können müssen die PHP-Erweiterung \"mysql\" sowie die Zend_Pdo_Mysql Klassen installiert sein."
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:442 #: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:417
msgid "You need to install the php extension \"pgsql\" and the Zend_Pdo_Pgsql classes to use PostgreSQL database resources." msgid "You need to install the php extension \"pgsql\" and the Zend_Pdo_Pgsql classes to use PostgreSQL database resources."
msgstr "" msgstr "Um PostgreSQL Datenbank-Ressourcen nutzen zu können müssen die PHP-Erweiterung \"pqsql\" sowie die Zend_Pdo_Pgsql Klassen installiert sein."
#: /usr/local/src/bugfix.master/application/forms/Preference/GeneralForm.php:106 #: /usr/local/src/bugfix.master/application/forms/Preference/GeneralForm.php:49
msgid "Your Current Language" msgid "Your Current Language"
msgstr "Deine aktuelle Sprache" msgstr "Deine aktuelle Sprache"
#: /usr/local/src/bugfix.master/library/Icinga/Util/Format.php:108 #: /usr/local/src/bugfix.master/library/Icinga/Web/Widget/Limiter.php:58
#: /usr/local/src/bugfix.master/library/Icinga/Util/Format.php:114 msgid "all"
msgstr "alle"
#: /usr/local/src/bugfix.master/library/Icinga/Util/Format.php:83
#: /usr/local/src/bugfix.master/library/Icinga/Util/Format.php:89
msgid "for" msgid "for"
msgstr "für" msgstr "für"
#: /usr/local/src/bugfix.master/library/Icinga/Util/Format.php:112 #: /usr/local/src/bugfix.master/library/Icinga/Util/Format.php:87
#: /usr/local/src/bugfix.master/library/Icinga/Util/Format.php:131 #: /usr/local/src/bugfix.master/library/Icinga/Util/Format.php:106
#: /usr/local/src/bugfix.master/library/Icinga/Util/Format.php:133 #: /usr/local/src/bugfix.master/library/Icinga/Util/Format.php:108
msgid "since" msgid "since"
msgstr "seit" msgstr "seit"
#: /usr/local/src/bugfix.master/application/views/scripts/config/devtools.phtml:5
msgid "toggle"
msgstr "umschalten"
#~ msgid "%d to %d of %d"
#~ msgstr "%d bis %d von %d"
#~ msgid "Installation"
#~ msgstr "Installation"
#~ msgid "Logging"
#~ msgstr "Logging"
#~ msgid "Previous"
#~ msgstr "Vorheriges"
#~ msgid "Icinga Users Login" #~ msgid "Icinga Users Login"
#~ msgstr "Icinga Benutzeranmeldung" #~ msgstr "Icinga Benutzeranmeldung"

View File

@ -3,7 +3,6 @@
// {{{ICINGA_LICENSE_HEADER}}} // {{{ICINGA_LICENSE_HEADER}}}
use Icinga\Application\Icinga; use Icinga\Application\Icinga;
use Icinga\Application\Config;
use Icinga\Util\DateTimeFactory; use Icinga\Util\DateTimeFactory;
use Icinga\Web\Form\Validator\DateTimeValidator; use Icinga\Web\Form\Validator\DateTimeValidator;
@ -109,10 +108,8 @@ class Zend_View_Helper_DateFormat extends Zend_View_Helper_Abstract
*/ */
public function getDateFormat() public function getDateFormat()
{ {
return $this->request->getUser()->getPreferences()->get( // TODO(mh): Missing localized format (#6077)
'app.dateFormat', return 'd/m/Y';
Config::app()->global !== null ? Config::app()->global->get('dateFormat', 'd/m/Y') : 'd/m/Y'
);
} }
/** /**
@ -122,10 +119,8 @@ class Zend_View_Helper_DateFormat extends Zend_View_Helper_Abstract
*/ */
public function getTimeFormat() public function getTimeFormat()
{ {
return $this->request->getUser()->getPreferences()->get( // TODO(mh): Missing localized format (#6077)
'app.timeFormat', return 'g:i A';
Config::app()->global !== null ? Config::app()->global->get('timeFormat', 'g:i A') : 'g:i A'
);
} }
/** /**

View File

@ -2,6 +2,11 @@
<?= $this->tabs ?> <?= $this->tabs ?>
</div> </div>
<div class="content" > <div class="content">
<?= $this->form ?> <h1><?= $this->escape($this->translate('This feature is deactivated at the moment.')); ?></h1>
</div> <p>
<?=
$this->escape($this->translate('Please have a little patience, we are hard working on it, take a look at icingaweb2 issues.'));
?>
</p>
</div>

View File

@ -7,16 +7,10 @@
</div> </div>
<?php else: ?> <?php else: ?>
<div class="content"> <div class="content">
<h1>No dashboard configuration found!</h1> <h1><?= $this->escape($this->translate('Welcome to Icinga Web!')) ?></h1>
<p> <p><?= sprintf(
<?= $this->escape($this->translate('Currently there is no dashlet available. This might change once you enabled some of the available %s.')),
$this->translate('We tried to load a dashboard configuration with no success.' $this->qlink($this->translate('modules'), 'config/modules')
. ' Please have look that the configuration does exist:'); ) ?></p>
?>
<code>
<?= $this->escape($this->configPath) ?>.ini
</code>
</p>
</div> </div>
<?php endif; ?> <?php endif ?>

View File

@ -1 +1,13 @@
<?= $menuRenderer; ?> <?php
use Icinga\Web\Widget\SearchDashboard;
?>
<? if (SearchDashboard::search('dummy')->getPane('search')->hasComponents()): ?>
<form action="<?= $this->href('search') ?>" method="get" role="search">
<input
type="text" name="q" class="search autofocus" placeholder="<?= $this->translate('Search...') ?>"
autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
/>
</form>
<? endif; ?>
<?= $menuRenderer; ?>

View File

@ -5,6 +5,7 @@
</div> </div>
<div class="content"> <div class="content">
<?php if ($this->logData !== null): ?>
<table class="action"> <table class="action">
<tbody> <tbody>
<?php foreach ($this->logData as $value): ?> <?php foreach ($this->logData as $value): ?>
@ -21,4 +22,5 @@
<?php endforeach; ?> <?php endforeach; ?>
</tbody> </tbody>
</table> </table>
</div> <?php endif; ?>
</div>

View File

@ -1,12 +1,8 @@
<div class="controls">
<?= $this->tabs ?>
</div>
<div class="content"> <div class="content">
<h1><?= $this->translate("I'm ready to search, waiting for your input") ?></h1> <h1><?= $this->translate("I'm ready to search, waiting for your input") ?></h1>
<p><strong><?= $this->translate('Hint') ?>: </strong><?= $this->translate( <p><strong><?= $this->translate('Hint') ?>: </strong><?= $this->translate(
'Please use the asterisk (*) as a placeholder for wildcard searches.' 'Please use the asterisk (*) as a placeholder for wildcard searches.'
. " For convenience I'll always add a wildcard after the last character" . " For convenience I'll always add a wildcard in front and after your"
. ' you typed.' . ' search string.'
) ?></p> ) ?></p>
</div> </div>

View File

@ -1,5 +1,5 @@
<div class="controls"> <div class="controls">
<?= $this->tabs ?> <?= $this->dashboard->getTabs() ?>
</div> </div>
<div class="content dashboard"> <div class="content dashboard">

View File

@ -1,7 +1,5 @@
[global] [global]
timezone = "Europe/Berlin" timezone = "Europe/Berlin"
dateFormat = "d/m/Y"
timeFormat = "g:i A"
; Contains the directories that will be searched for available modules. Modules that ; Contains the directories that will be searched for available modules. Modules that
; don't exist in these directories can still be symlinked in the module folder, but ; don't exist in these directories can still be symlinked in the module folder, but

View File

@ -1,39 +0,0 @@
[Incidents]
title = "Current incidents"
[Incidents.Service Problems]
url = "monitoring/list/services"
service_problem = 1
limit = 10
sort = service_severity
[Incidents.Recently Recovered Services]
url = "monitoring/list/services"
sort = "service_last_state_change"
service_state = 0
limit = 10
dir = "desc"
[Incidents.Host Problems]
url = "monitoring/list/hosts"
host_problem = 1
sort = host_severity
[Landing]
title = "Landing page"
[Landing.Hostgroups]
url = "monitoring/chart/hostgroup"
[Landing.Servicegroups]
url = "monitoring/chart/servicegroup"
[Landing.Unhandled Problem Services]
url = "monitoring/list/services"
service_handled = 0
service_problem = 1
[Landing.Unhandled Problem Hosts]
url = "monitoring/list/hosts"
host_handled = 0
host_problem = 1

View File

@ -1,34 +0,0 @@
[Dashboard]
title = "Dashboard"
url = "dashboard"
icon = "img/icons/dashboard.png"
priority = 10
[System]
icon = img/icons/configuration.png
priority = 200
[System.Preferences]
title = "Preferences"
url = "preference"
priority = 200
[System.Configuration]
title = "Configuration"
url = "config"
priority = 300
[System.Modules]
title = "Modules"
url = "config/modules"
priority = 400
[System.ApplicationLog]
title = "Application log"
url = "list/applicationlog"
priority = 500
[Logout]
url = "authentication/logout"
icon = img/icons/logout.png
priority = 300

View File

@ -1,5 +0,0 @@
[Documentation]
title = "Documentation"
icon = "img/icons/comment.png"
url = "doc"
priority = 80

View File

@ -1,109 +0,0 @@
[Problems]
priority = 20
icon = "img/icons/error.png"
[Problems.Unhandled Hosts]
priority = 40
url = "monitoring/list/hosts?host_problem=1&host_handled=0"
[Problems.Unhandled Services]
priority = 40
url = "monitoring/list/services?service_problem=1&service_handled=0&sort=service_severity"
[Problems.Host Problems]
priority = 50
url = "monitoring/list/hosts?host_problem=1&sort=host_severity"
[Problems.Service Problems]
priority = 50
url = "monitoring/list/services?service_problem=1&sort=service_severity&dir=desc"
[Problems.Current Downtimes]
url = "monitoring/list/downtimes?downtime_is_in_effect=1"
[Overview]
priority = 30
icon = "img/icons/hostgroup.png"
[Overview.Tactical Overview]
title = "Tactical Overview"
url = "monitoring/tactical"
priority = 40
[Overview.Hosts]
title = "Hosts"
url = "monitoring/list/hosts"
priority = 50
[Overview.Services]
title = "Services"
url = "monitoring/list/services"
priority = 50
[Overview.Servicematrix]
title = "Servicematrix"
url = "monitoring/list/servicematrix?service_problem=1"
priority = 51
[Overview.Servicegroups]
title = "Servicegroups"
url = "monitoring/list/servicegroups"
priority = 60
[Overview.Hostgroups]
title = "Hostgroups"
url = "monitoring/list/hostgroups"
priority = 60
[Overview.Contactgroups]
title = "Contactgroups"
url = "monitoring/list/contactgroups"
priority = 61
[Overview.Downtimes]
title = "Downtimes"
url = "monitoring/list/downtimes"
priority = 70
[Overview.Comments]
title = "Comments"
url = "monitoring/list/comments?comment_type=(comment|ack)"
priority = 70
[Overview.Contacts]
title = "Contacts"
url = "monitoring/list/contacts"
priority = 70
[History]
icon = "img/icons/history.png"
[History.Critical Events]
title = "Critical Events"
url = "monitoring/list/statehistorysummary"
priority = 50
[History.Notifications]
title = "Notifications"
url = "monitoring/list/notifications"
[History.Events]
title = "All Events"
url = "monitoring/list/eventhistory?timestamp>=-7%20days"
[History.Timeline]
title = "Timeline"
url = "monitoring/timeline"
[System.Process Info]
title = "Process Info"
url = "monitoring/process/info"
priority = 120
[System.Performance Info]
title = "Performance Info"
url = "monitoring/process/performance"
priority = 130

0
doc/api/.gitkeep Normal file
View File

View File

@ -1,130 +0,0 @@
# Frontend components
Frontend components are JavaScript modules that can be required directly through the HTML markup of
your view, to provide additional functionality for the user. Although its best practice to
make all features available without JavaScript, these components can be used to provide a richer
and more comfortable user experience in case JavaScript is available.
There is a certain set of frontend components which come directly with the Icinga2-Web core application,
but it is also possible to define new components directly in Icinga2-Web modules.
## How do components work?
Components are defined in JavaScript files that provide a set of functionality that will be added to the
targeted HTML node. Icinga2-Web uses [RequireJS](http://requirejs.org) to load
all frontend components, so each frontend component is in fact
[defined exactly like a RequireJS-Module](http://requirejs.org/docs/api.html#define) .
The important difference to plain RequireJS is, that the loading and execution of these components is
done automatically through the HTML markup. The attribute *data-icinga-component* in a DIV
element will indicate that this element is a container for a frontend component and will trigger
the component loader to create a component instance for this HTML node. The component loader
keeps track of all available components and makes it possible to retrieve this instance when needed.
### Component names
A component name consists of two parts: the namespace and the name of the component itself. The component
is named exactly like its JavaScript file, while the namespace is the name of the Icinga2-Web module that contains
the component. Each Icinga2-Web module can contain its own components in the folder *public/js*.
<module>/<component>
NOTE: The namespace used for modules defined in the Icinga2-Web core application is "app". In opposition to
the modules the core application keeps its modules located in *public/js/icinga/components*
instead of *public/js*.
#### Example Names
The full name for the component *modules/monitoring/public/js/someComponent.js* in the module "monitoring" would be:
"monitoring/someComponent"
The full component name for the component *public/js/icinga/components/datetime.js* in the Icinga2-Web core application
would:
"app/datetime"
## Creating a component
As described in the chapters above, components are defined exactly like RequireJS modules, but
with the additional requirement that they must always return a class constructor. The component below will
search all date pickers, set the time format and create a JavaScript date picker when there is no native one
available.
/**
* Ensures that our date/time controls will work on every browser (natively or javascript based)
*/
define(['jquery', 'datetimepicker'], function($) {
"use strict";
var DateTimePicker = function(target) {
$(target).find('.datetime input')
.attr('data-format', 'yyyy-MM-dd hh:mm:ss');
$(target).find('.datetime')
.addClass('input-append')
.append('<span class="add-on">' +
'<i data-time-icon="icon-time" data-date-icon="icon-calendar"></i></span>')
.datetimepicker();
};
return DateTimePicker;
});
## Loading a component
The following code will load the module *datetime*, which will ensure that there is always a datetime-picker
with right time-format available.
<div id="date-time-picker" data-icinga-component="app/datetime">
<div class="datetime">
<input data-format="dd/MM/yyyy hh:mm:ss" type="text"/>
</div>
</div>
### Component ids
When an ID is assigned to the HTML element, it will be used by the component loader to reference this
component. Otherwise an ID in the form "icinga-component-&lt;ID&gt;" will be created and the ID attribute in the
HTML Element will be updated accordingly.
### Component "target"
The div-element with the *data-icinga-component* will be used as the "target" for the loaded component,
which means that the component will perform its actions on this HTML node.
# Retrieving a component
Sometimes it can be necessary to retrieve the instances of the components itself, for example when they implement
additional functions that can be called. The component loader is available in the Icinga object and can be used
to retrieve component instances using their ID or their full component name.
## By component id
var component = Icinga.components.getById("component-id");
component.doSomething();
## By full component name
var components = Icinga.components.getByType("app/datetime");
// ... do something with every component of the type app/datetime
## All components
var components = Icinga.components.getComponents();
// ... do something with every component

View File

@ -14,30 +14,4 @@ the objects you're interested in and can add and remove elements.
* The dashboard itself is just the view containing the panes * The dashboard itself is just the view containing the panes
## Configuration files
By default, the config/dashboard/dashboard.ini is used for storing dashboards in the following format:
[PaneName] ; Define a new Pane
title = "PaneTitle" ; The title of the pane as displayed in the tabls
[PaneName.Component1] ; Define a new component 'Component 1' underneat the pane
url = "/url/for/component1" ; the url that will be displayed, with view=compact as URL parameter appended
height = "500px" ; optional height setting
width = "400px" ; optional width setting
[test.My hosts] ; Another component, here with host
url = "monitoring/list/hosts" ; the url of the component
; Notice the missing height/width definition
[test.My services] ; And another pane
url = "monitoring/list/services" ; With service url
[test2] ; Define a second pane
title = "test2" ; with the title
[test2.test] ; Add a component to the second pane
url = "/monitoring/show/host/host1" ; ...and define it's url
[dashboards1]: res/Dashboard.png [dashboards1]: res/Dashboard.png

View File

@ -238,6 +238,77 @@ the labels to show you can use the 'disableLegend()' call on the GridChart objec
![Various Line Graph Options][graph7] ![Various Line Graph Options][graph7]
### Tooltips
It is possible to specify custom tooltip format strings when creating bar charts.
Tooltips provide information about the points of each bar chart column, by aggregating
the values of all data sets with the same x-coordinate.
When no custom format string is given, a sane default format string is used, but its usually
clearer for the user to describe the data of each chart more accurately with a custom one.
**Example #9.1: Bar Charts with custom tooltips**
$this->chart->drawBars(
array(
'label' => 'Hosts critical',
'palette' => Palette::PROBLEM,
'stack' => 'stack1',
'data' => $data2,
'tooltip' => '{title}<br/> {value} of {sum} hosts are ok.'
),
array(
'label' => 'Hosts warning',
'stack' => 'stack1',
'palette' => Palette::WARNING,
'data' => $data,
'tooltip' => '{title}<br/> Oh no, {value} of {sum} hosts are down!'
)
);
As you can see, you can specify a format string for each data set, which allows you to
pass a custom message for all "down" hosts, one custom message for all "Ok" hosts and so on.
In contrast to that, the aggregation of values works on a column basis and will give you the
sum of all y-values with the same x-coordinate and not the aggregation of all values of the data set.
#### Rich Tooltips
It is also possible to use HTML in the tooltip strings to create rich tooltip markups, which can
be useful to provide extended output that spans over multiple lines. Please keep in mind that
users without JavaScript will see the tooltip with all of its html-tags stripped.
![Various Line Graph Options][graph7.1]
#### Available replacements
The available replacements depend on the used chart type, since the tooltip data is
instantiated and populated by the chart. All bar graphs have the following replacements available:
Aggregated values, are calculated from the data points of each column:
- sum: The amount of all Y-values of the current column
- max: The biggest occurring Y-value of the current column
- min: The smallest occurring Y-value of the current column
Column values are also defined by the current column, but are not
the product of any aggregation
- title: The x-value of the current column
Row values are defined by the properties the current data set, and are only useful for rendering the
generic tooltip correctly, since you could also just directly write
those values into your custom tooltip.
- label: The name of the current data set
- color: The color of this data set
## Pie Charts ## Pie Charts
### The PieChart Object ### The PieChart Object
@ -317,5 +388,6 @@ Rendering is straightforward, assuming $svg is the PieChart/GridChart object, yo
[graph5]: res/GraphExample#5.png [graph5]: res/GraphExample#5.png
[graph6]: res/GraphExample#6.png [graph6]: res/GraphExample#6.png
[graph7]: res/GraphExample#7.png [graph7]: res/GraphExample#7.png
[graph7.1]: res/GraphExample#7.1.png
[graph8]: res/GraphExample#8.png [graph8]: res/GraphExample#8.png
[graph9]: res/GraphExample#9.png [graph9]: res/GraphExample#9.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

@ -83,7 +83,7 @@ BuildArch: noarch
AutoReqProv: Off AutoReqProv: Off
%endif %endif
Source0: icingaweb2-%{version}.tar.gz Source: icingaweb2-%{version}.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
@ -181,15 +181,10 @@ install -D -m0644 packages/rpm/etc/httpd/conf.d/icingaweb.conf %{buildroot}/%{ap
%{__cp} -r application library modules public %{buildroot}/%{sharedir}/ %{__cp} -r application library modules public %{buildroot}/%{sharedir}/
## config ## config
# use the default menu.ini for application and monitoring mobule
install -D -m0644 config/menu.ini %{buildroot}/%{_sysconfdir}/icingaweb/menu.ini
install -D -m0644 config/modules/monitoring/menu.ini %{buildroot}/%{_sysconfdir}/icingaweb/modules/monitoring/menu.ini
# authentication is db only # authentication is db only
install -D -m0644 packages/rpm/etc/icingaweb/authentication.ini %{buildroot}/%{_sysconfdir}/icingaweb/authentication.ini install -D -m0644 packages/rpm/etc/icingaweb/authentication.ini %{buildroot}/%{_sysconfdir}/icingaweb/authentication.ini
# custom resource paths # custom resource paths
install -D -m0644 packages/rpm/etc/icingaweb/resources.ini %{buildroot}/%{_sysconfdir}/icingaweb/resources.ini install -D -m0644 packages/rpm/etc/icingaweb/resources.ini %{buildroot}/%{_sysconfdir}/icingaweb/resources.ini
# dashboard
install -D -m0644 config/dashboard/dashboard.ini %{buildroot}/%{_sysconfdir}/icingaweb/dashboard/dashboard.ini
# monitoring module (icinga2) # monitoring module (icinga2)
install -D -m0644 packages/rpm/etc/icingaweb/modules/monitoring/backends.ini %{buildroot}/%{_sysconfdir}/icingaweb/modules/monitoring/backends.ini install -D -m0644 packages/rpm/etc/icingaweb/modules/monitoring/backends.ini %{buildroot}/%{_sysconfdir}/icingaweb/modules/monitoring/backends.ini
install -D -m0644 packages/rpm/etc/icingaweb/modules/monitoring/instances.ini %{buildroot}/%{_sysconfdir}/icingaweb/modules/monitoring/instances.ini install -D -m0644 packages/rpm/etc/icingaweb/modules/monitoring/instances.ini %{buildroot}/%{_sysconfdir}/icingaweb/modules/monitoring/instances.ini

View File

@ -14,6 +14,7 @@ use Icinga\Exception\NotReadableError;
use Icinga\Logger\Logger; use Icinga\Logger\Logger;
use Icinga\Util\DateTimeFactory; use Icinga\Util\DateTimeFactory;
use Icinga\Util\Translator; use Icinga\Util\Translator;
use Icinga\Exception\IcingaException;
/** /**
* This class bootstraps a thin Icinga application layer * This class bootstraps a thin Icinga application layer
@ -332,7 +333,7 @@ abstract class ApplicationBootstrap
try { try {
$this->moduleManager->loadEnabledModules(); $this->moduleManager->loadEnabledModules();
} catch (NotReadableError $e) { } catch (NotReadableError $e) {
Logger::error(new Exception('Cannot load enabled modules. An exception was thrown:', 0, $e)); Logger::error(new IcingaException('Cannot load enabled modules. An exception was thrown:', $e));
} }
return $this; return $this;
} }
@ -369,7 +370,7 @@ abstract class ApplicationBootstrap
try { try {
$this->config = Config::app(); $this->config = Config::app();
} catch (NotReadableError $e) { } catch (NotReadableError $e) {
Logger::error(new Exception('Cannot load application configuration. An exception was thrown:', 0, $e)); Logger::error(new IcingaException('Cannot load application configuration. An exception was thrown:', $e));
$this->config = new Zend_Config(array()); $this->config = new Zend_Config(array());
} }
return $this; return $this;
@ -417,7 +418,7 @@ abstract class ApplicationBootstrap
ResourceFactory::setConfig($config); ResourceFactory::setConfig($config);
} catch (NotReadableError $e) { } catch (NotReadableError $e) {
Logger::error( Logger::error(
new Exception('Cannot load resource configuration. An exception was thrown:', 0, $e) new IcingaException('Cannot load resource configuration. An exception was thrown:', $e)
); );
} }
@ -451,9 +452,8 @@ abstract class ApplicationBootstrap
*/ */
protected function setupInternationalization() protected function setupInternationalization()
{ {
$localeDir = $this->getApplicationDir('locale'); if ($this->hasLocales()) {
if (file_exists($localeDir) && is_dir($localeDir)) { Translator::registerDomain(Translator::DEFAULT_DOMAIN, $this->getLocaleDir());
Translator::registerDomain(Translator::DEFAULT_DOMAIN, $localeDir);
} }
try { try {
@ -468,4 +468,48 @@ abstract class ApplicationBootstrap
return $this; return $this;
} }
/**
* @return string Our locale directory
*/
public function getLocaleDir()
{
return $this->getApplicationDir('locale');
}
/**
* return bool Whether Icinga Web has translations
*/
public function hasLocales()
{
$localedir = $this->getLocaleDir();
return file_exists($localedir) && is_dir($localedir);
}
/**
* List all available locales
*
* NOTE: Might be a candidate for a static function in Translator
*
* return array Locale list
*/
public function listLocales()
{
$locales = array();
if (! $this->hasLocales()) {
return $locales;
}
$localedir = $this->getLocaleDir();
$dh = opendir($localedir);
while (false !== ($file = readdir($dh))) {
$filename = $localedir . DIRECTORY_SEPARATOR . $file;
if (preg_match('/^[a-z]{2}_[A-Z]{2}$/', $file) && is_dir($filename)) {
$locales[] = $file;
}
}
closedir($dh);
sort($locales);
return $locales;
}
} }

View File

@ -61,7 +61,10 @@ class Config extends Zend_Config
$this->configFile = $filepath; $this->configFile = $filepath;
$this->merge(new Zend_Config_Ini($filepath)); $this->merge(new Zend_Config_Ini($filepath));
} else { } else {
throw new NotReadableError('Cannot read config file "' . $filename . '". Permission denied'); throw new NotReadableError(
'Cannot read config file "%s". Permission denied',
$filename
);
} }
} }
@ -82,6 +85,18 @@ class Config extends Zend_Config
return self::$app[$configname]; return self::$app[$configname];
} }
/**
* Set module config
*
* @param string $moduleName
* @param string $configName
* @param Zend_Config $config
*/
public static function setModuleConfig($moduleName, $configName, Zend_Config $config)
{
self::$modules[$moduleName][$configName] = $config;
}
/** /**
* Retrieve a module config instance * Retrieve a module config instance
* *

View File

@ -39,11 +39,11 @@ class Loader
public function registerNamespace($namespace, $directory) public function registerNamespace($namespace, $directory)
{ {
if (!is_dir($directory)) { if (!is_dir($directory)) {
throw new ProgrammingError(sprintf( throw new ProgrammingError(
'Directory "%s" for namespace "%s" does not exist', 'Directory "%s" for namespace "%s" does not exist',
$directory, $directory,
$namespace $namespace
)); );
} }
$this->namespaces[$namespace] = $directory; $this->namespaces[$namespace] = $directory;

View File

@ -110,12 +110,14 @@ class Manager
} }
if (!is_dir($this->enableDir)) { if (!is_dir($this->enableDir)) {
throw new NotReadableError( throw new NotReadableError(
'Cannot read enabled modules. Module directory "' . $this->enableDir . '" is not a directory' 'Cannot read enabled modules. Module directory "%s" is not a directory',
$this->enableDir
); );
} }
if (!is_readable($this->enableDir)) { if (!is_readable($this->enableDir)) {
throw new NotReadableError( throw new NotReadableError(
'Cannot read enabled modules. Module directory "' . $this->enableDir . '" is not readable' 'Cannot read enabled modules. Module directory "%s" is not readable',
$this->enableDir
); );
} }
if (($dh = opendir($canonical)) !== false) { if (($dh = opendir($canonical)) !== false) {
@ -206,10 +208,8 @@ class Manager
{ {
if (!$this->hasInstalled($name)) { if (!$this->hasInstalled($name)) {
throw new ConfigurationError( throw new ConfigurationError(
sprintf( 'Cannot enable module "%s". Module is not installed.',
'Cannot enable module "%s". Module is not installed.', $name
$name
)
); );
} }
@ -219,8 +219,8 @@ class Manager
if (!is_writable($this->enableDir)) { if (!is_writable($this->enableDir)) {
throw new SystemPermissionException( throw new SystemPermissionException(
'Can not enable module "' . $name . '". ' 'Can not enable module "%s". Insufficient system permissions for enabling modules.',
. 'Insufficient system permissions for enabling modules.' $name
); );
} }
@ -232,9 +232,11 @@ class Manager
$error = error_get_last(); $error = error_get_last();
if (strstr($error["message"], "File exists") === false) { if (strstr($error["message"], "File exists") === false) {
throw new SystemPermissionException( throw new SystemPermissionException(
'Could not enable module "' . $name . '" due to file system errors. ' 'Could not enable module "%s" due to file system errors. '
. 'Please check path and mounting points because this is not a permission error. ' . 'Please check path and mounting points because this is not a permission error. '
. 'Primary error was: ' . $error['message'] . 'Primary error was: %s',
$name,
$error['message']
); );
} }
} }
@ -268,14 +270,18 @@ class Manager
} }
$link = $this->enableDir . '/' . $name; $link = $this->enableDir . '/' . $name;
if (!file_exists($link)) { if (!file_exists($link)) {
throw new ConfigurationError('Could not disable module. The module ' . $name . ' was not found.'); throw new ConfigurationError(
'Could not disable module. The module %s was not found.',
$name
);
} }
if (!is_link($link)) { if (!is_link($link)) {
throw new ConfigurationError( throw new ConfigurationError(
'Could not disable module. The module "' . $name . '" is not a symlink. ' 'Could not disable module. The module "%s" is not a symlink. '
. 'It looks like you have installed this module manually and moved it to your module folder. ' . 'It looks like you have installed this module manually and moved it to your module folder. '
. 'In order to dynamically enable and disable modules, you have to create a symlink to ' . 'In order to dynamically enable and disable modules, you have to create a symlink to '
. 'the enabled_modules folder.' . 'the enabled_modules folder.',
$name
); );
} }
@ -283,9 +289,11 @@ class Manager
if (!@unlink($link)) { if (!@unlink($link)) {
$error = error_get_last(); $error = error_get_last();
throw new SystemPermissionException( throw new SystemPermissionException(
'Could not disable module "' . $name . '" due to file system errors. ' 'Could not disable module "%s" due to file system errors. '
. 'Please check path and mounting points because this is not a permission error. ' . 'Please check path and mounting points because this is not a permission error. '
. 'Primary error was: ' . $error['message'] . 'Primary error was: %s',
$name,
$error['message']
); );
} }
} }
@ -319,10 +327,8 @@ class Manager
} }
throw new ProgrammingError( throw new ProgrammingError(
sprintf( 'Trying to access uninstalled module dir: %s',
'Trying to access uninstalled module dir: %s', $name
$name
)
); );
} }
@ -388,10 +394,8 @@ class Manager
{ {
if (!$this->hasLoaded($name)) { if (!$this->hasLoaded($name)) {
throw new ProgrammingError( throw new ProgrammingError(
sprintf( 'Cannot access module %s as it hasn\'t been loaded',
'Cannot access module %s as it hasn\'t been loaded', $name
$name
)
); );
} }
return $this->loadedModules[$name]; return $this->loadedModules[$name];

View File

@ -5,17 +5,22 @@
namespace Icinga\Application\Modules; namespace Icinga\Application\Modules;
use Exception; use Exception;
use Zend_Config;
use Zend_Controller_Router_Route_Abstract; use Zend_Controller_Router_Route_Abstract;
use Zend_Controller_Router_Route as Route; use Zend_Controller_Router_Route as Route;
use Zend_Controller_Router_Route_Regex as RegexRoute;
use Icinga\Application\ApplicationBootstrap; use Icinga\Application\ApplicationBootstrap;
use Icinga\Application\Config; use Icinga\Application\Config;
use Icinga\Application\Icinga; use Icinga\Application\Icinga;
use Icinga\Logger\Logger; use Icinga\Logger\Logger;
use Icinga\Util\Translator; use Icinga\Util\Translator;
use Icinga\Web\Hook; use Icinga\Web\Hook;
use Icinga\Web\Menu;
use Icinga\Web\Widget; use Icinga\Web\Widget;
use Icinga\Web\Widget\Dashboard\Pane;
use Icinga\Util\File; use Icinga\Util\File;
use Icinga\Exception\ProgrammingError; use Icinga\Exception\ProgrammingError;
use Icinga\Exception\IcingaException;
/** /**
* Module handling * Module handling
@ -136,7 +141,6 @@ class Module
*/ */
private $app; private $app;
/** /**
* Routes to add to the route chain * Routes to add to the route chain
* *
@ -146,6 +150,97 @@ class Module
*/ */
protected $routes = array(); protected $routes = array();
/**
* A set of menu elements
*
* @var array
*/
protected $menuItems = array();
/**
* A set of Pane elements
*
* @var array
*/
protected $paneItems = array();
/**
* @var array
*/
protected $searchUrls = array();
/**
* @param string $title
* @param string $url
*/
public function provideSearchUrl($title, $url)
{
$searchUrl = (object) array(
'title' => $title,
'url' => $url
);
$this->searchUrls[] = $searchUrl;
}
public function getSearchUrls()
{
$this->launchConfigScript();
return $this->searchUrls;
}
/**
* Get all Menu Items
*
* @return array
*/
public function getPaneItems()
{
$this->launchConfigScript();
return $this->paneItems;
}
/**
* Add a pane to dashboard
*
* @param $name
* @return Pane
*/
protected function dashboard($name)
{
$this->paneItems[$name] = new Pane($name);
return $this->paneItems[$name];
}
/**
* Get all Menu Items
*
* @return array
*/
public function getMenuItems()
{
$this->launchConfigScript();
return $this->menuItems;
}
/**
* Add a menu Section to the Sidebar menu
*
* @param $name
* @param array $properties
* @return mixed
*/
protected function menuSection($name, array $properties = array())
{
if (array_key_exists($name, $this->menuItems)) {
$this->menuItems[$name]->setProperties($properties);
} else {
$this->menuItems[$name] = new Menu($name, new Zend_Config($properties));
}
return $this->menuItems[$name];
}
/** /**
* Create a new module object * Create a new module object
* *
@ -559,8 +654,9 @@ class Module
protected function providePermission($name, $description) protected function providePermission($name, $description)
{ {
if ($this->providesPermission($name)) { if ($this->providesPermission($name)) {
throw new Exception( throw new IcingaException(
sprintf('Cannot provide permission "%s" twice', $name) 'Cannot provide permission "%s" twice',
$name
); );
} }
$this->permissionList[$name] = (object) array( $this->permissionList[$name] = (object) array(
@ -580,8 +676,9 @@ class Module
protected function provideRestriction($name, $description) protected function provideRestriction($name, $description)
{ {
if ($this->providesRestriction($name)) { if ($this->providesRestriction($name)) {
throw new Exception( throw new IcingaException(
sprintf('Cannot provide restriction "%s" twice', $name) 'Cannot provide restriction "%s" twice',
$name
); );
} }
$this->restrictionList[$name] = (object) array( $this->restrictionList[$name] = (object) array(
@ -637,12 +734,44 @@ class Module
*/ */
protected function registerLocales() protected function registerLocales()
{ {
if (file_exists($this->localedir) && is_dir($this->localedir)) { if ($this->hasLocales()) {
Translator::registerDomain($this->name, $this->localedir); Translator::registerDomain($this->name, $this->localedir);
} }
return $this; return $this;
} }
/**
* return bool Whether this module has translations
*/
public function hasLocales()
{
return file_exists($this->localedir) && is_dir($this->localedir);
}
/**
* List all available locales
*
* return array Locale list
*/
public function listLocales()
{
$locales = array();
if (! $this->hasLocales()) {
return $locales;
}
$dh = opendir($this->localedir);
while (false !== ($file = readdir($dh))) {
$filename = $this->localedir . DIRECTORY_SEPARATOR . $file;
if (preg_match('/^[a-z]{2}_[A-Z]{2}$/', $file) && is_dir($filename)) {
$locales[] = $file;
}
}
closedir($dh);
sort($locales);
return $locales;
}
/** /**
* Register web integration * Register web integration
* *
@ -693,12 +822,15 @@ class Module
); );
$router->addRoute( $router->addRoute(
$this->name . '_img', $this->name . '_img',
new Route( new RegexRoute(
'img/' . $this->name . '/:file', 'img/' . $this->name . '/(.+)',
array( array(
'controller' => 'static', 'controller' => 'static',
'action' => 'img', 'action' => 'img',
'module_name' => $this->name 'module_name' => $this->name
),
array(
1 => 'file'
) )
) )
); );
@ -781,4 +913,15 @@ class Module
$this->routes[$name] = $route; $this->routes[$name] = $route;
return $this; return $this;
} }
/**
* Translate a string with the global mt()
*
* @param $string
* @return mixed|string
*/
protected function translate($string)
{
return mt($this->name, $string);
}
} }

View File

@ -4,22 +4,57 @@
namespace Icinga\Application; namespace Icinga\Application;
/**
* Platform tests for icingaweb
*/
class Platform class Platform
{ {
/**
* Domain name
*
* @var string
*/
protected static $domain; protected static $domain;
/**
* Host name
*
* @var string
*/
protected static $hostname; protected static $hostname;
/**
* Fully qualified domain name
*
* @var string
*/
protected static $fqdn; protected static $fqdn;
/**
* Test of windows
*
* @return bool
*/
public static function isWindows() public static function isWindows()
{ {
return strtoupper(substr(PHP_OS, 0, 3)) === 'WIN'; return strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
} }
/**
* Test of linux
*
* @return bool
*/
public static function isLinux() public static function isLinux()
{ {
return strtoupper(substr(PHP_OS, 0, 5)) === 'LINUX'; return strtoupper(substr(PHP_OS, 0, 5)) === 'LINUX';
} }
/**
* Test of CLI environment
*
* @return bool
*/
public static function isCli() public static function isCli()
{ {
if (PHP_SAPI == 'cli') { if (PHP_SAPI == 'cli') {
@ -31,6 +66,11 @@ class Platform
return false; return false;
} }
/**
* Get the hostname
*
* @return string
*/
public static function getHostname() public static function getHostname()
{ {
if (self::$hostname === null) { if (self::$hostname === null) {
@ -39,6 +79,11 @@ class Platform
return self::$hostname; return self::$hostname;
} }
/**
* Get the domain name
*
* @return string
*/
public static function getDomain() public static function getDomain()
{ {
if (self::$domain === null) { if (self::$domain === null) {
@ -47,6 +92,11 @@ class Platform
return self::$domain; return self::$domain;
} }
/**
* Get the fully qualified domain name
*
* @return string
*/
public static function getFqdn() public static function getFqdn()
{ {
if (self::$fqdn === null) { if (self::$fqdn === null) {
@ -55,6 +105,9 @@ class Platform
return self::$fqdn; return self::$fqdn;
} }
/**
* Initialize domain and host strings
*/
protected static function discoverHostname() protected static function discoverHostname()
{ {
self::$hostname = gethostname(); self::$hostname = gethostname();
@ -66,4 +119,16 @@ class Platform
self::$domain = array_shift(preg_split('~\.~', self::$hostname, 2)); self::$domain = array_shift(preg_split('~\.~', self::$hostname, 2));
} }
} }
/**
* Test for php extension
*
* @param string $extensionName E.g. mysql, ldap
*
* @return bool
*/
public static function extensionLoaded($extensionName)
{
return extension_loaded($extensionName);
}
} }

View File

@ -10,11 +10,10 @@ use Icinga\Authentication\Manager as AuthenticationManager;
use Icinga\Exception\ConfigurationError; use Icinga\Exception\ConfigurationError;
use Icinga\Exception\NotReadableError; use Icinga\Exception\NotReadableError;
use Icinga\Logger\Logger; use Icinga\Logger\Logger;
use Icinga\Util\TimezoneDetect;
use Icinga\Web\Request; use Icinga\Web\Request;
use Icinga\Web\Response; use Icinga\Web\Response;
use Icinga\Web\View; use Icinga\Web\View;
use Icinga\Web\Session\Session as BaseSession;
use Icinga\Web\Session;
use Icinga\User; use Icinga\User;
use Icinga\Util\Translator; use Icinga\Util\Translator;
use Icinga\Util\DateTimeFactory; use Icinga\Util\DateTimeFactory;
@ -59,13 +58,6 @@ class Web extends ApplicationBootstrap
*/ */
private $request; private $request;
/**
* Session object
*
* @var BaseSession
*/
private $session;
/** /**
* User object * User object
* *
@ -92,7 +84,6 @@ class Web extends ApplicationBootstrap
->setupErrorHandling() ->setupErrorHandling()
->loadConfig() ->loadConfig()
->setupResourceFactory() ->setupResourceFactory()
->setupSession()
->setupUser() ->setupUser()
->setupTimezone() ->setupTimezone()
->setupLogger() ->setupLogger()
@ -172,7 +163,6 @@ class Web extends ApplicationBootstrap
$this->setupFrontController(); $this->setupFrontController();
$this->setupViewRenderer(); $this->setupViewRenderer();
return $this; return $this;
} }
@ -192,17 +182,6 @@ class Web extends ApplicationBootstrap
return $this; return $this;
} }
/**
* Initialize a session provider
*
* @return self
*/
private function setupSession()
{
$this->session = Session::create();
return $this;
}
/** /**
* Inject dependencies into request * Inject dependencies into request
* *
@ -295,10 +274,11 @@ class Web extends ApplicationBootstrap
*/ */
protected function setupTimezone() protected function setupTimezone()
{ {
$userTimezone = null;
if ($this->user !== null && $this->user->getPreferences() !== null) { if ($this->user !== null && $this->user->getPreferences() !== null) {
$userTimezone = $this->user->getPreferences()->get('app.timezone'); $detect = new TimezoneDetect();
} else { $userTimezone = $this->user->getPreferences()->get('app.timezone', $detect->getTimezoneName());
$userTimezone = null;
} }
try { try {

View File

@ -2,7 +2,7 @@
// {{{ICINGA_LICENSE_HEADER}}} // {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}} // {{{ICINGA_LICENSE_HEADER}}}
use \Icinga\Util\Translator; use Icinga\Util\Translator;
if (extension_loaded('gettext')) { if (extension_loaded('gettext')) {
function t($messageId) function t($messageId)

View File

@ -97,7 +97,9 @@ class AuthChain implements Iterator
} catch (ConfigurationError $e) { } catch (ConfigurationError $e) {
Logger::error( Logger::error(
new ConfigurationError( new ConfigurationError(
'Cannot create authentication backend "' . $name . '". An exception was thrown:', 0, $e 'Cannot create authentication backend "%s". An exception was thrown:',
$name,
$e
) )
); );
$this->next(); $this->next();

View File

@ -11,6 +11,7 @@ use Icinga\Exception\AuthenticationException;
use Exception; use Exception;
use Zend_Db_Expr; use Zend_Db_Expr;
use Zend_Db_Select; use Zend_Db_Select;
use Icinga\Exception\IcingaException;
class DbUserBackend extends UserBackend class DbUserBackend extends UserBackend
{ {
@ -60,7 +61,10 @@ class DbUserBackend extends UserBackend
return false; return false;
} }
if ($salt === '') { if ($salt === '') {
throw new Exception('Cannot find salt for user ' . $user->getUsername()); throw new IcingaException(
'Cannot find salt for user %s',
$user->getUsername()
);
} }
$select = new Zend_Db_Select($this->conn->getConnection()); $select = new Zend_Db_Select($this->conn->getConnection());
@ -73,12 +77,9 @@ class DbUserBackend extends UserBackend
return ($row !== false) ? true : false; return ($row !== false) ? true : false;
} catch (Exception $e) { } catch (Exception $e) {
throw new AuthenticationException( throw new AuthenticationException(
sprintf( 'Failed to authenticate user "%s" against backend "%s". An exception was thrown:',
'Failed to authenticate user "%s" against backend "%s". An exception was thrown:', $user->getUsername(),
$user->getUsername(), $this->getName(),
$this->getName()
),
0,
$e $e
); );
} }
@ -125,4 +126,4 @@ class DbUserBackend extends UserBackend
return ($row !== false) ? $row->count : 0; return ($row !== false) ? $row->count : 0;
} }
} }

View File

@ -68,21 +68,17 @@ class LdapUserBackend extends UserBackend
$result = $q->fetchRow(); $result = $q->fetchRow();
if (! isset($result)) { if (! isset($result)) {
throw new AuthenticationException( throw new AuthenticationException(
sprintf( 'No objects with objectClass="%s" in DN="%s" found.',
'No objects with objectClass="%s" in DN="%s" found.', $this->userClass,
$this->userClass, $this->conn->getDN()
$this->conn->getDN()
)
); );
} }
if (! isset($result->{$this->userNameAttribute})) { if (! isset($result->{$this->userNameAttribute})) {
throw new AuthenticationException( throw new AuthenticationException(
sprintf( 'UserNameAttribute "%s" not existing in objectClass="%s"',
'UserNameAttribute "%s" not existing in objectClass="%s"', $this->userNameAttribute,
$this->userNameAttribute, $this->userClass
$this->userClass
)
); );
} }
} }
@ -121,11 +117,8 @@ class LdapUserBackend extends UserBackend
} catch (AuthenticationException $e) { } catch (AuthenticationException $e) {
// Authentication not possible // Authentication not possible
throw new AuthenticationException( throw new AuthenticationException(
sprintf( 'Authentication against backend "%s" not possible: ',
'Authentication against backend "%s" not possible: ', $this->getName(),
$this->getName()
),
0,
$e $e
); );
} }
@ -141,12 +134,9 @@ class LdapUserBackend extends UserBackend
} catch (LdapException $e) { } catch (LdapException $e) {
// Error during authentication of this specific user // Error during authentication of this specific user
throw new AuthenticationException( throw new AuthenticationException(
sprintf( 'Failed to authenticate user "%s" against backend "%s". An exception was thrown:',
'Failed to authenticate user "%s" against backend "%s". An exception was thrown:', $user->getUsername(),
$user->getUsername(), $this->getName(),
$this->getName()
),
0,
$e $e
); );
} }

View File

@ -13,6 +13,7 @@ use Icinga\Exception\NotReadableError;
use Icinga\Application\Config as IcingaConfig; use Icinga\Application\Config as IcingaConfig;
use Icinga\User\Preferences; use Icinga\User\Preferences;
use Icinga\User\Preferences\PreferencesStore; use Icinga\User\Preferences\PreferencesStore;
use Icinga\Exception\IcingaException;
class Manager class Manager
{ {
@ -55,7 +56,11 @@ class Manager
$config = IcingaConfig::app(); $config = IcingaConfig::app();
} catch (NotReadableError $e) { } catch (NotReadableError $e) {
Logger::error( Logger::error(
new Exception('Cannot load preferences for user "' . $username . '". An exception was thrown', 0, $e) new IcingaException(
'Cannot load preferences for user "%s". An exception was thrown',
$username,
$e
)
); );
$config = new Zend_Config(array()); $config = new Zend_Config(array());
} }
@ -68,8 +73,10 @@ class Manager
$preferences = new Preferences($preferencesStore->load()); $preferences = new Preferences($preferencesStore->load());
} catch (NotReadableError $e) { } catch (NotReadableError $e) {
Logger::error( Logger::error(
new Exception( new IcingaException(
'Cannot load preferences for user "' . $username . '". An exception was thrown', 0, $e 'Cannot load preferences for user "%s". An exception was thrown',
$username,
$e
) )
); );
$preferences = new Preferences(); $preferences = new Preferences();

View File

@ -54,16 +54,18 @@ abstract class UserBackend implements Countable
// Use a custom backend class, this is only useful for testing // Use a custom backend class, this is only useful for testing
if (!class_exists($backendConfig->class)) { if (!class_exists($backendConfig->class)) {
throw new ConfigurationError( throw new ConfigurationError(
'Authentication configuration for backend "' . $name . '" defines an invalid backend' 'Authentication configuration for backend "%s" defines an invalid backend class.'
. ' class. Backend class "' . $backendConfig->class. '" not found' . ' Backend class "%s" not found',
$name,
$backendConfig->class
); );
} }
return new $backendConfig->class($backendConfig); return new $backendConfig->class($backendConfig);
} }
if (($backendType = $backendConfig->backend) === null) { if (($backendType = $backendConfig->backend) === null) {
throw new ConfigurationError( throw new ConfigurationError(
'Authentication configuration for backend "' . $name 'Authentication configuration for backend "%s" is missing the backend directive',
. '" is missing the backend directive' $name
); );
} }
$backendType = strtolower($backendType); $backendType = strtolower($backendType);
@ -74,8 +76,8 @@ abstract class UserBackend implements Countable
} }
if ($backendConfig->resource === null) { if ($backendConfig->resource === null) {
throw new ConfigurationError( throw new ConfigurationError(
'Authentication configuration for backend "' . $name 'Authentication configuration for backend "%s" is missing the resource directive',
. '" is missing the resource directive' $name
); );
} }
try { try {
@ -100,22 +102,24 @@ abstract class UserBackend implements Countable
case 'ldap': case 'ldap':
if (($userClass = $backendConfig->user_class) === null) { if (($userClass = $backendConfig->user_class) === null) {
throw new ConfigurationError( throw new ConfigurationError(
'Authentication configuration for backend "' . $name 'Authentication configuration for backend "%s" is missing the user_class directive',
. '" is missing the user_class directive' $name
); );
} }
if (($userNameAttribute = $backendConfig->user_name_attribute) === null) { if (($userNameAttribute = $backendConfig->user_name_attribute) === null) {
throw new ConfigurationError( throw new ConfigurationError(
'Authentication configuration for backend "' . $name 'Authentication configuration for backend "%s" is missing the user_name_attribute directive',
. '" is missing the user_name_attribute directive' $name
); );
} }
$backend = new LdapUserBackend($resource, $userClass, $userNameAttribute); $backend = new LdapUserBackend($resource, $userClass, $userNameAttribute);
break; break;
default: default:
throw new ConfigurationError( throw new ConfigurationError(
'Authentication configuration for backend "' . $name. '" defines an invalid backend' 'Authentication configuration for backend "%s" defines an invalid backend type.'
. ' type. Backend type "' . $backendType . '" is not supported' . ' Backend type "%s" is not supported',
$name,
$backendType
); );
} }
$backend->setName($name); $backend->setName($name);

View File

@ -9,12 +9,15 @@ use Icinga\Chart\Legend;
use Icinga\Chart\Palette; use Icinga\Chart\Palette;
use Icinga\Chart\Primitive\Drawable; use Icinga\Chart\Primitive\Drawable;
use Icinga\Chart\SVGRenderer; use Icinga\Chart\SVGRenderer;
use Icinga\Exception\IcingaException;
/** /**
* Base class for charts, extended by all other Chart classes. * Base class for charts, extended by all other Chart classes.
*/ */
abstract class Chart implements Drawable abstract class Chart implements Drawable
{ {
protected $align = false;
/** /**
* SVG renderer that handles * SVG renderer that handles
* *
@ -87,19 +90,33 @@ abstract class Chart implements Drawable
* *
* Render this graph and return the created SVG * Render this graph and return the created SVG
* *
* @return string The SVG created by the SvgRenderer * @return string The SVG created by the SvgRenderer
* *
* @throws Exception Thrown wen the dataset is not valid for this graph * @throws IcingaException Thrown wen the dataset is not valid for this graph
* @see SVGRenderer::render * @see SVGRenderer::render
*/ */
public function render() public function render()
{ {
if (!$this->isValidDataFormat()) { if (!$this->isValidDataFormat()) {
throw new Exception('Dataset for graph doesn\'t have the proper structure'); throw new IcingaException('Dataset for graph doesn\'t have the proper structure');
} }
$this->build(); $this->build();
if ($this->align) {
$this->renderer->preserveAspectRatio();
$this->renderer->setXAspectRatioAlignment(SVGRenderer::X_ASPECT_RATIO_MIN);
$this->renderer->setYAspectRatioAlignment(SVGRenderer::Y_ASPECT_RATIO_MIN);
}
$this->renderer->getCanvas()->addElement($this); $this->renderer->getCanvas()->addElement($this);
return $this->renderer->render(); return $this->renderer->render();
} }
/**
* Align the chart to the top left corner instead of centering it
*
* @param bool $align
*/
public function alignTopLeft ($align = true)
{
$this->align = $align;
}
} }

View File

@ -16,6 +16,13 @@ use Icinga\Chart\Render\RenderContext;
*/ */
class BarGraph extends Styleable implements Drawable class BarGraph extends Styleable implements Drawable
{ {
/**
* The dataset order
*
* @var int
*/
private $order = 0;
/** /**
* The width of the bars. * The width of the bars.
* *
@ -30,14 +37,37 @@ class BarGraph extends Styleable implements Drawable
*/ */
private $dataSet; private $dataSet;
/**
* The tooltips
*
* @var
*/
private $tooltips;
/**
* All graphs
*
* @var
*/
private $graphs;
/** /**
* Create a new BarGraph with the given dataset * Create a new BarGraph with the given dataset
* *
* @param array $dataSet An array of datapoints * @param array $dataSet An array of data points
* @param int $order The graph number displayed by this BarGraph
* @param array $tooltips The tooltips to display for each value
*/ */
public function __construct(array $dataSet) public function __construct(
{ array $dataSet,
array &$graphs,
$order,
array $tooltips = null
) {
$this->order = $order;
$this->dataSet = $dataSet; $this->dataSet = $dataSet;
$this->tooltips = $tooltips;
$this->graphs = $graphs;
} }
/** /**
@ -56,6 +86,30 @@ class BarGraph extends Styleable implements Drawable
} }
} }
/**
* Draw a single rectangle
*
* @param array $point The
* @param null $index
* @param string $fill The fill color to use
* @param $strokeWidth
*
* @return Rect
*/
private function drawSingleBar($point, $index = null, $fill, $strokeWidth)
{
$rect = new Rect($point[0] - ($this->barWidth / 2), $point[1], $this->barWidth, 100 - $point[1]);
$rect->setFill($fill);
$rect->setStrokeWidth($strokeWidth);
$rect->setStrokeColor('black');
if (isset($index)) {
$rect->setAttribute('data-icinga-graph-index', $index);
}
$rect->setAttribute('data-icinga-graph-type', 'bar');
$rect->setAdditionalStyle('clip-path: url(#clip);');
return $rect;
}
/** /**
* Render this BarChart * Render this BarChart
* *
@ -68,23 +122,33 @@ class BarGraph extends Styleable implements Drawable
$doc = $ctx->getDocument(); $doc = $ctx->getDocument();
$group = $doc->createElement('g'); $group = $doc->createElement('g');
$idx = 0; $idx = 0;
foreach ($this->dataSet as $point) { foreach ($this->dataSet as $x => $point) {
$rect = new Rect($point[0] - 2, $point[1], 4, 100 - $point[1]); // add white background bar, to prevent other bars from altering transparency effects
$rect->setFill($this->fill); $bar = $this->drawSingleBar($point, $idx++, 'white', $this->strokeWidth, $idx)->toSvg($ctx);
$rect->setStrokeWidth($this->strokeWidth); $group->appendChild($bar);
$rect->setStrokeColor('black');
$rect->setAttribute('data-icinga-graph-index', $idx++); // draw actual bar
$rect->setAttribute('data-icinga-graph-type', 'bar'); $bar = $this->drawSingleBar($point, null, $this->fill, $this->strokeWidth, $idx)->toSvg($ctx);
$rect->setAdditionalStyle('clip-path: url(#clip);'); $bar->setAttribute('class', 'chart-data');
/*$rect->setAnimation( if (isset($this->tooltips[$x])) {
new Animation( $data = array(
'y', 'label' => isset($this->graphs[$this->order]['label']) ?
$ctx->yToAbsolute(100), strtolower($this->graphs[$this->order]['label']) : '',
$ctx->yToAbsolute($point[1]), 'color' => isset($this->graphs[$this->order]['color']) ?
rand(1, 1.5)/2 strtolower($this->graphs[$this->order]['color']) : '#fff'
) );
);*/ $format = isset($this->graphs[$this->order]['tooltip'])
$group->appendChild($rect->toSvg($ctx)); ? $this->graphs[$this->order]['tooltip'] : null;
$bar->setAttribute(
'title',
$this->tooltips[$x]->renderNoHtml($this->order, $data, $format)
);
$bar->setAttribute(
'data-title-rich',
$this->tooltips[$x]->render($this->order, $data, $format)
);
}
$group->appendChild($bar);
} }
return $group; return $group;
} }

View File

@ -41,6 +41,10 @@ class StackedGraph implements Drawable
if (!isset($this->points[$x])) { if (!isset($this->points[$x])) {
$this->points[$x] = 0; $this->points[$x] = 0;
} }
// store old y-value for displaying the actual (non-aggregated)
// value in the tooltip
$point[2] = $point[1];
$this->points[$x] += $point[1]; $this->points[$x] += $point[1];
$point[1] = $this->points[$x]; $point[1] = $this->points[$x];
} }

View File

@ -0,0 +1,144 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Chart\Graph;
/**
* A tooltip that stores and aggregates information about displayed data
* points of a graph and replaces them in a format string to render the description
* for specific data points of the graph.
*
* When render() is called, placeholders for the keys for each data entry will be replaced by
* the current value of this data set and the formatted string will be returned.
* The content of the replaced keys can change for each data set and depends on how the data
* is passed to this class. There are several types of properties:
*
* <ul>
* <li>Global properties</li>: Key-value pairs that stay the same every time render is called, and are
* passed to an instance in the constructor.
* <li>Aggregated properties</li>: Global properties that are created automatically from
* all attached data points.
* <li>Local properties</li>: Key-value pairs that only apply to a single data point and
* are passed to the render-function.
* </ul>
*/
class Tooltip
{
/**
* The default format string used
* when no other format is specified
*
* @var string
*/
private $defaultFormat;
/**
* All aggregated points
*
* @var array
*/
private $points = array();
/**
* Contains all static replacements
*
* @var array
*/
private $data = array(
'sum' => 0
);
/**
* Used to format the displayed tooltip.
*
* @var string
*/
protected $tooltipFormat;
/**
* Create a new tooltip with the specified default format string
*
* Allows you to set the global data for this tooltip, that is displayed every
* time render is called.
*
* @param array $data Map of global properties
* @param string $format The default format string
*/
public function __construct (
$data = array(),
$format = '<b>{title}</b></b><br/> {value} of {sum} {label}'
) {
$this->data = array_merge($this->data, $data);
$this->defaultFormat = $format;
}
/**
* Add a single data point to update the aggregated properties for this tooltip
*
* @param $point array Contains the (x,y) values of the data set
*/
public function addDataPoint($point)
{
// set x-value
if (!isset($this->data['title'])) {
$this->data['title'] = $point[0];
}
// aggregate y-values
$y = (int)$point[1];
if (isset($point[2])) {
// load original value in case value already aggregated
$y = (int)$point[2];
}
if (!isset($this->data['min']) || $this->data['min'] > $y) {
$this->data['min'] = $y;
}
if (!isset($this->data['max']) || $this->data['max'] < $y) {
$this->data['max'] = $y;
}
$this->data['sum'] += $y;
$this->points[] = $y;
}
/**
* Format the tooltip for a certain data point
*
* @param array $order Which data set to render
* @param array $data The local data for this tooltip
* @param string $format Use a custom format string for this data set
*
* @return mixed|string The tooltip value
*/
public function render($order, $data = array(), $format = null)
{
if (isset($format)) {
$str = $format;
} else {
$str = $this->defaultFormat;
}
$data['value'] = $this->points[$order];
foreach (array_merge($this->data, $data) as $key => $value) {
$str = str_replace('{' . $key . '}', $value, $str);
}
return $str;
}
/**
* Format the tooltip for a certain data point but remove all
* occurring html tags
*
* This is useful for rendering clean tooltips on client without JavaScript
*
* @param array $order Which data set to render
* @param array $data The local data for this tooltip
* @param string $format Use a custom format string for this data set
*
* @return mixed|string The tooltip value, without any HTML tags
*/
public function renderNoHtml($order, $data, $format)
{
return strip_tags($this->render($order, $data, $format));
}
}

View File

@ -10,6 +10,7 @@ use Icinga\Chart\Axis;
use Icinga\Chart\Graph\BarGraph; use Icinga\Chart\Graph\BarGraph;
use Icinga\Chart\Graph\LineGraph; use Icinga\Chart\Graph\LineGraph;
use Icinga\Chart\Graph\StackedGraph; use Icinga\Chart\Graph\StackedGraph;
use Icinga\Chart\Graph\Tooltip;
use Icinga\Chart\Primitive\Canvas; use Icinga\Chart\Primitive\Canvas;
use Icinga\Chart\Primitive\Rect; use Icinga\Chart\Primitive\Rect;
use Icinga\Chart\Primitive\Path; use Icinga\Chart\Primitive\Path;
@ -74,6 +75,16 @@ class GridChart extends Chart
*/ */
private $stacks = array(); private $stacks = array();
/**
* An associative array containing all Tooltips used to render the titles
*
* Each tooltip represents the summary for all y-values of a certain x-value
* in the grid chart
*
* @var Tooltip
*/
private $tooltips = array();
/** /**
* Check if the current dataset has the proper structure for this chart. * Check if the current dataset has the proper structure for this chart.
* *
@ -169,6 +180,26 @@ class GridChart extends Chart
$this->legend->addDataset($graph); $this->legend->addDataset($graph);
} }
} }
$this->initTooltips($data);
}
private function initTooltips($data)
{
foreach ($data as &$graph) {
foreach ($graph['data'] as $x => $point) {
if (!array_key_exists($x, $this->tooltips)) {
$this->tooltips[$x] = new Tooltip(
array(
'color' => $graph['color'],
)
);
}
$this->tooltips[$x]->addDataPoint($point);
}
}
} }
/** /**
@ -353,11 +384,16 @@ class GridChart extends Chart
foreach ($this->graphs as $axisName => $graphs) { foreach ($this->graphs as $axisName => $graphs) {
$axis = $this->axis[$axisName]; $axis = $this->axis[$axisName];
$graphObj = null; $graphObj = null;
foreach ($graphs as $graph) { foreach ($graphs as $dataset => $graph) {
// determine the type and create a graph object for it // determine the type and create a graph object for it
switch ($graph['graphType']) { switch ($graph['graphType']) {
case self::TYPE_BAR: case self::TYPE_BAR:
$graphObj = new BarGraph($axis->transform($graph['data'])); $graphObj = new BarGraph(
$axis->transform($graph['data']),
$graphs,
$dataset,
$this->tooltips
);
break; break;
case self::TYPE_LINE: case self::TYPE_LINE:
$graphObj = new LineGraph($axis->transform($graph['data'])); $graphObj = new LineGraph($axis->transform($graph['data']));

View File

@ -7,6 +7,7 @@ namespace Icinga\Chart\Inline;
use Icinga\Chart\PieChart as PieChartRenderer; use Icinga\Chart\PieChart as PieChartRenderer;
use Imagick; use Imagick;
use Exception; use Exception;
use Icinga\Exception\IcingaException;
/** /**
* Draw an inline pie-chart directly from the available request parameters. * Draw an inline pie-chart directly from the available request parameters.
@ -17,11 +18,11 @@ class PieChart extends Inline
public function render($output = true) public function render($output = true)
{ {
$pie = new PieChartRenderer(); $pie = new PieChartRenderer();
$pie->alignTopLeft();
$pie->disableLegend(); $pie->disableLegend();
$pie->drawPie(array( $pie->drawPie(array(
'data' => $this->data, 'colors' => $this->colors, 'labels' => $this->labels 'data' => $this->data, 'colors' => $this->colors, 'labels' => $this->labels
)); ));
$pie->setWidth($this->width)->setHeight($this->height);
if ($output) { if ($output) {
echo $pie->render(); echo $pie->render();
} else { } else {
@ -33,7 +34,7 @@ class PieChart extends Inline
{ {
if (! class_exists('Imagick')) { if (! class_exists('Imagick')) {
// TODO: This is quick & dirty. 404? // TODO: This is quick & dirty. 404?
throw new Exception('Cannot render PNGs without Imagick'); throw new IcingaException('Cannot render PNGs without Imagick');
} }
$image = new Imagick(); $image = new Imagick();
$image->readImageBlob($this->render(false)); $image->readImageBlob($this->render(false));

View File

@ -16,7 +16,7 @@ use Icinga\Chart\Render\LayoutBox;
/** /**
* Graphing component for rendering Pie Charts. * Graphing component for rendering Pie Charts.
* *
* See the graphs.md documentation for futher information about how to use this component * See the graphs.md documentation for further information about how to use this component
*/ */
class PieChart extends Chart class PieChart extends Chart
{ {
@ -51,46 +51,6 @@ class PieChart extends Chart
*/ */
private $noCaption = false; private $noCaption = false;
/**
* Scaling level of the rendered svgs width in percent.
*
* @var float
*/
private $width = 100;
/**
* Scaling level of the rendered svgs height in percent.
*
* @var int
*/
private $height = 100;
/**
* Set the size of the rendered pie-chart svg.
*
* @param $width int The width in percent.
*
* @return self Fluent interface
*/
public function setWidth($width)
{
$this->width = $width;
return $this;
}
/**
* Set the size of the rendered pie-chart svg.
*
* @param $height int The height in percent.
*
* @return self Fluent interface
*/
public function setHeight($height)
{
$this->height = $height;
return $this;
}
/** /**
* Test if the given pies have the correct format * Test if the given pies have the correct format
* *
@ -111,10 +71,7 @@ class PieChart extends Chart
*/ */
protected function build() protected function build()
{ {
$this->renderer = new SVGRenderer( $this->renderer = new SVGRenderer(($this->type === self::STACKED) ? 1 : count($this->pies), 1);
$this->type === self::STACKED ? $this->width : count($this->pies) * $this->width,
$this->width
);
foreach ($this->pies as &$pie) { foreach ($this->pies as &$pie) {
$this->normalizeDataSet($pie); $this->normalizeDataSet($pie);
} }
@ -165,11 +122,16 @@ class PieChart extends Chart
*/ */
public function toSvg(RenderContext $ctx) public function toSvg(RenderContext $ctx)
{ {
$outerBox = new Canvas('outerGraph', new LayoutBox(0, 0, 100, 100));
$innerBox = new Canvas('graph', new LayoutBox(0, 0, 100, 100));
$labelBox = $ctx->getDocument()->createElement('g'); $labelBox = $ctx->getDocument()->createElement('g');
if (!$this->noCaption) { if (!$this->noCaption) {
// Scale SVG to make room for captions
$outerBox = new Canvas('outerGraph', new LayoutBox(33, -5, 40, 40));
$innerBox = new Canvas('graph', new LayoutBox(0, 0, 100, 100));
$innerBox->getLayout()->setPadding(10, 10, 10, 10); $innerBox->getLayout()->setPadding(10, 10, 10, 10);
} else {
$outerBox = new Canvas('outerGraph', new LayoutBox(1.5, -10, 124, 124));
$innerBox = new Canvas('graph', new LayoutBox(0, 0, 100, 100));
$innerBox->getLayout()->setPadding(0, 0, 0, 0);
} }
$this->createContentClipBox($innerBox); $this->createContentClipBox($innerBox);
$this->renderPies($innerBox, $labelBox); $this->renderPies($innerBox, $labelBox);
@ -274,9 +236,6 @@ class PieChart extends Chart
$lastRadius = 0; $lastRadius = 0;
foreach ($pie['data'] as $idx => $dataset) { foreach ($pie['data'] as $idx => $dataset) {
$color = $this->getColorForPieSlice($pie, $idx); $color = $this->getColorForPieSlice($pie, $idx);
if ($dataset === 100) {
$dataset = 99.9;
}
if ($dataset == 0) { if ($dataset == 0) {
$labelPos++; $labelPos++;
continue; continue;
@ -340,3 +299,4 @@ class PieChart extends Chart
$clipBox->addElement($rect); $clipBox->addElement($rect);
} }
} }

View File

@ -32,7 +32,7 @@ class PieSlice extends Animatable implements Drawable
* *
* @var float * @var float
*/ */
private $endRadian= 0; private $endRadian = 0;
/** /**
* The x position of the pie slice's center * The x position of the pie slice's center
@ -104,17 +104,21 @@ class PieSlice extends Animatable implements Drawable
*/ */
private function getPieSlicePath($x, $y, $r) private function getPieSlicePath($x, $y, $r)
{ {
// start at the center of the pieslice
$pathString = 'M ' . $x . ' ' . $y . ' ';
// The coordinate system is mirrored on the Y axis, so we have to flip cos and sin // The coordinate system is mirrored on the Y axis, so we have to flip cos and sin
$xStart = $x + ($r * sin($this->startRadian)); $xStart = $x + ($r * sin($this->startRadian));
$yStart = $y - ($r * cos($this->startRadian)); $yStart = $y - ($r * cos($this->startRadian));
$xEnd = $x + ($r * sin($this->endRadian));
$yEnd = $y - ($r * cos($this->endRadian));
// Draw a straight line to the upper part of the arc if ($this->endRadian - $this->startRadian == 2*M_PI) {
$pathString .= 'L ' . Format::formatSVGNumber($xStart) . ' ' . Format::formatSVGNumber($yStart); // To draw a full circle, adjust arc endpoint by a small (unvisible) value
$this->endRadian -= 0.001;
$pathString = 'M ' . Format::formatSVGNumber($xStart) . ' ' . Format::formatSVGNumber($yStart);
} else {
// Start at the center of the pieslice
$pathString = 'M ' . $x . ' ' . $y;
// Draw a straight line to the upper part of the arc
$pathString .= ' L ' . Format::formatSVGNumber($xStart) . ' ' . Format::formatSVGNumber($yStart);
}
// Instead of directly connecting the upper part of the arc (leaving a triangle), draw a bow with the radius // Instead of directly connecting the upper part of the arc (leaving a triangle), draw a bow with the radius
$pathString .= ' A ' . Format::formatSVGNumber($r) . ' ' . Format::formatSVGNumber($r); $pathString .= ' A ' . Format::formatSVGNumber($r) . ' ' . Format::formatSVGNumber($r);
// These are the flags for the bow, see the SVG path documentation for details // These are the flags for the bow, see the SVG path documentation for details
@ -122,7 +126,10 @@ class PieSlice extends Animatable implements Drawable
$pathString .= ' 0 ' . (($this->endRadian - $this->startRadian > M_PI) ? '1' : '0 ') . ' 1'; $pathString .= ' 0 ' . (($this->endRadian - $this->startRadian > M_PI) ? '1' : '0 ') . ' 1';
// xEnd and yEnd are the lower point of the arc // xEnd and yEnd are the lower point of the arc
$xEnd = $x + ($r * sin($this->endRadian));
$yEnd = $y - ($r * cos($this->endRadian));
$pathString .= ' ' . Format::formatSVGNumber($xEnd) . ' ' . Format::formatSVGNumber($yEnd); $pathString .= ' ' . Format::formatSVGNumber($xEnd) . ' ' . Format::formatSVGNumber($yEnd);
return $pathString; return $pathString;
} }
@ -152,7 +159,7 @@ class PieSlice extends Animatable implements Drawable
// Draw the handle // Draw the handle
$path = new Path(array($midX, $midY)); $path = new Path(array($midX, $midY));
$midX += ($addOffset + $r/1.8) * ($midRadius > M_PI ? -1 : 1); $midX += ($addOffset + $r/3) * ($midRadius > M_PI ? -1 : 1);
$path->append(array($midX, $midY))->toAbsolute(); $path->append(array($midX, $midY))->toAbsolute();
$midX += intval($r/2 * sin(M_PI/9)) * ($midRadius > M_PI ? -1 : 1); $midX += intval($r/2 * sin(M_PI/9)) * ($midRadius > M_PI ? -1 : 1);
@ -169,7 +176,7 @@ class PieSlice extends Animatable implements Drawable
// Draw the text box // Draw the text box
$text = new Text($rel[0]+1.5, $rel[1], $this->caption); $text = new Text($rel[0]+1.5, $rel[1], $this->caption);
$text->setFontSize('2.5em'); $text->setFontSize('5em');
$text->setAlignment(($midRadius > M_PI ? Text::ALIGN_END : Text::ALIGN_START)); $text->setAlignment(($midRadius > M_PI ? Text::ALIGN_END : Text::ALIGN_START));
$group->appendChild($path->toSvg($ctx)); $group->appendChild($path->toSvg($ctx));

View File

@ -4,8 +4,8 @@
namespace Icinga\Chart\Primitive; namespace Icinga\Chart\Primitive;
use \DomElement; use DomElement;
use \Icinga\Chart\Render\RenderContext; use Icinga\Chart\Render\RenderContext;
use Icinga\Chart\Format; use Icinga\Chart\Format;
/** /**

View File

@ -132,7 +132,7 @@ class RenderContext
* @param int $x The relative x coordinate * @param int $x The relative x coordinate
* @param int $y The relative y coordinate * @param int $y The relative y coordinate
* *
* @return array An x,y tupel containing absolute coordinates * @return array An x,y tuple containing absolute coordinates
* @see RenderContext::toRelative * @see RenderContext::toRelative
*/ */
public function toAbsolute($x, $y) public function toAbsolute($x, $y)

View File

@ -1,10 +1,7 @@
<?php <?php
/** // {{{ICINGA_LICENSE_HEADER}}}
* Created by PhpStorm. // {{{ICINGA_LICENSE_HEADER}}}
* User: mjentsch
* Date: 22.07.14
* Time: 10:17
*/
namespace Icinga\Chart\Render; namespace Icinga\Chart\Render;

View File

@ -19,6 +19,22 @@ use Icinga\Chart\Primitive\Canvas;
*/ */
class SVGRenderer class SVGRenderer
{ {
const X_ASPECT_RATIO_MIN = 'xMin';
const X_ASPECT_RATIO_MID = 'xMid';
const X_ASPECT_RATIO_MAX = 'xMax';
const Y_ASPECT_RATIO_MIN = 'YMin';
const Y_ASPECT_RATIO_MID = 'YMid';
const Y_ASPECT_RATIO_MAX = 'YMax';
const ASPECT_RATIO_PAD = 'meet';
const ASPECT_RATIO_CUTOFF = 'slice';
/** /**
* The XML-document * The XML-document
* *
@ -54,6 +70,35 @@ class SVGRenderer
*/ */
private $height = 100; private $height = 100;
/**
* Whether the aspect ratio is preversed
*
* @var bool
*/
private $preserveAspectRatio = false;
/**
* Horizontal alignment of SVG element
*
* @var string
*/
private $xAspectRatio = self::X_ASPECT_RATIO_MID;
/**
* Vertical alignment of SVG element
*
* @var string
*/
private $yAspectRatio = self::Y_ASPECT_RATIO_MID;
/**
* Define whether aspect differences should be handled using padding (default) or cutoff
*
* @var string
*/
private $xFillMode = "meet";
/** /**
* Create the root document and the SVG root node * Create the root document and the SVG root node
*/ */
@ -82,8 +127,8 @@ class SVGRenderer
$svg = $this->document->createElement('svg'); $svg = $this->document->createElement('svg');
$svg->setAttribute('xmlns', 'http://www.w3.org/2000/svg'); $svg->setAttribute('xmlns', 'http://www.w3.org/2000/svg');
$svg->setAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink'); $svg->setAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink');
$svg->setAttribute('width', $this->width . '%'); $svg->setAttribute('width', '100%');
$svg->setAttribute('height', $this->height . '%'); $svg->setAttribute('height', '100%');
$svg->setAttribute( $svg->setAttribute(
'viewBox', 'viewBox',
sprintf( sprintf(
@ -92,6 +137,17 @@ class SVGRenderer
$ctx->getNrOfUnitsY() $ctx->getNrOfUnitsY()
) )
); );
if ($this->preserveAspectRatio) {
$svg->setAttribute(
'preserveAspectRatio',
sprintf (
'%s%s %s',
$this->xAspectRatio,
$this->yAspectRatio,
$this->xFillMode
)
);
}
return $svg; return $svg;
} }
@ -141,4 +197,40 @@ class SVGRenderer
{ {
return $this->rootCanvas; return $this->rootCanvas;
} }
/**
* Preserve the aspect ratio of the rendered object
*
* Do not deform the content of the SVG when the aspect ratio of the viewBox
* differs from the aspect ratio of the SVG element, but add padding or cutoff
* instead
*
* @param bool $preserve Whether the aspect ratio should be preserved
*/
public function preserveAspectRatio($preserve = true)
{
$this->preserveAspectRatio = $preserve;
}
/**
* Change the horizontal alignment of the SVG element
*
* Change the horizontal alignment of the svg, when preserveAspectRatio is used and
* padding is present. Defaults to
*/
public function setXAspectRatioAlignment($alignment)
{
$this->xAspectRatio = $alignment;
}
/**
* Change the vertical alignment of the SVG element
*
* Change the vertical alignment of the svg, when preserveAspectRatio is used and
* padding is present.
*/
public function setYAspectRatioAlignment($alignment)
{
$this->yAspectRatio = $alignment;
}
} }

View File

@ -5,6 +5,7 @@
namespace Icinga\Cli; namespace Icinga\Cli;
use Icinga\Cli\Screen; use Icinga\Cli\Screen;
use Icinga\Exception\IcingaException;
// @see http://en.wikipedia.org/wiki/ANSI_escape_code // @see http://en.wikipedia.org/wiki/ANSI_escape_code
@ -74,7 +75,10 @@ class AnsiScreen extends Screen
protected function fgColor($color) protected function fgColor($color)
{ {
if (! array_key_exists($color, $this->fgColors)) { if (! array_key_exists($color, $this->fgColors)) {
throw new \Exception(sprintf('There is no such foreground color: %s', $color)); throw new IcingaException(
'There is no such foreground color: %s',
$color
);
} }
return $this->fgColors[$color]; return $this->fgColors[$color];
} }
@ -82,7 +86,10 @@ class AnsiScreen extends Screen
protected function bgColor($color) protected function bgColor($color)
{ {
if (! array_key_exists($color, $this->bgColors)) { if (! array_key_exists($color, $this->bgColors)) {
throw new \Exception(sprintf('There is no such background color: %s', $color)); throw new IcingaException(
'There is no such background color: %s',
$color
);
} }
return $this->bgColors[$color]; return $this->bgColors[$color];
} }

View File

@ -10,6 +10,7 @@ use Icinga\Cli\Params;
use Icinga\Application\Config; use Icinga\Application\Config;
use Icinga\Application\ApplicationBootstrap as App; use Icinga\Application\ApplicationBootstrap as App;
use Exception; use Exception;
use Icinga\Exception\IcingaException;
abstract class Command abstract class Command
{ {
@ -123,7 +124,7 @@ abstract class Command
public function fail($msg) public function fail($msg)
{ {
throw new Exception($msg); throw new IcingaException('%s', $msg);
} }
public function getDefaultActionName() public function getDefaultActionName()

View File

@ -332,7 +332,8 @@ class Loader
{ {
if (! $this->hasModule($module)) { if (! $this->hasModule($module)) {
throw new ProgrammingError( throw new ProgrammingError(
sprintf('There is no such module: %s', $module) 'There is no such module: %s',
$module
); );
} }
} }
@ -341,7 +342,8 @@ class Loader
{ {
if (! $this->hasCommand($command)) { if (! $this->hasCommand($command)) {
throw new ProgrammingError( throw new ProgrammingError(
sprintf('There is no such command: %s', $command) 'There is no such command: %s',
$command
); );
} }
} }
@ -351,7 +353,9 @@ class Loader
$this->assertModuleExists($module); $this->assertModuleExists($module);
if (! $this->hasModuleCommand($module, $command)) { if (! $this->hasModuleCommand($module, $command)) {
throw new ProgrammingError( throw new ProgrammingError(
sprintf("The module '%s' has no such command: %s", $module, $command) 'The module \'%s\' has no such command: %s',
$module,
$command
); );
} }
} }

View File

@ -38,6 +38,45 @@ class PreservingIniWriter extends Zend_Config_Writer_FileAbstract
parent::__construct($options); parent::__construct($options);
} }
/**
* Find all keys containing dots and convert it to a nested configuration
*
* Ensure that configurations with the same ini representation the have
* similarly nested Zend_Config objects. The configuration may be altered
* during that process.
*
* @param Zend_Config $config The configuration to normalize
* @return Zend_Config The normalized config
*/
private function normalizeKeys(Zend_Config $config)
{
foreach ($config as $key => $value) {
if (preg_match('/\./', $key) > 0) {
// remove old key
unset ($config->$key);
// insert new key
$nests = explode('.', $key);
$current = $config;
$i = 0;
for (; $i < count($nests) - 1; $i++) {
if (! isset($current->{$nests[$i]})) {
// configuration key doesn't exist, create a new nesting level
$current->{$nests[$i]} = new Zend_Config (array(), true);
}
// move to next nesting level
$current = $current->{$nests[$i]};
}
// reached last nesting level, insert value
$current->{$nests[$i]} = $value;
}
if ($value instanceof Zend_Config) {
$config->$key = $this->normalizeKeys ($value);
}
}
return $config;
}
/** /**
* Render the Zend_Config into a config file string * Render the Zend_Config into a config file string
* *
@ -50,6 +89,17 @@ class PreservingIniWriter extends Zend_Config_Writer_FileAbstract
} else { } else {
$oldconfig = new Zend_Config(array()); $oldconfig = new Zend_Config(array());
} }
// create an internal copy of the given configuration, since the user of this class
// won't expect that a configuration will ever be altered during
// the rendering process.
$extends = $this->_config->getExtends();
$this->_config = new Zend_Config ($this->_config->toArray(), true);
foreach ($extends as $extending => $extended) {
$this->_config->setExtend($extending, $extended);
}
$this->_config = $this->normalizeKeys($this->_config);
$newconfig = $this->_config; $newconfig = $this->_config;
$editor = new IniEditor(file_get_contents($this->_filename), $this->options); $editor = new IniEditor(file_get_contents($this->_filename), $this->options);
$this->diffConfigs($oldconfig, $newconfig, $editor); $this->diffConfigs($oldconfig, $newconfig, $editor);

View File

@ -142,7 +142,10 @@ class DbConnection implements Selectable
} }
break;*/ break;*/
default: default:
throw new ConfigurationError(sprintf('Backend "%s" is not supported', $this->dbType)); throw new ConfigurationError(
'Backend "%s" is not supported',
$this->dbType
);
} }
$this->dbAdapter = Zend_Db::factory($adapter, $adapterParamaters); $this->dbAdapter = Zend_Db::factory($adapter, $adapterParamaters);
$this->dbAdapter->setFetchMode(Zend_Db::FETCH_OBJ); $this->dbAdapter->setFetchMode(Zend_Db::FETCH_OBJ);

View File

@ -11,6 +11,7 @@ use Icinga\Data\Filter\FilterExpression;
use Icinga\Data\Filter\FilterOr; use Icinga\Data\Filter\FilterOr;
use Icinga\Data\Filter\FilterAnd; use Icinga\Data\Filter\FilterAnd;
use Icinga\Data\Filter\FilterNot; use Icinga\Data\Filter\FilterNot;
use Icinga\Exception\IcingaException;
use Zend_Db_Select; use Zend_Db_Select;
/** /**
@ -88,6 +89,17 @@ class DbQuery extends SimpleQuery
public function getSelectQuery() public function getSelectQuery()
{ {
$select = $this->dbSelect(); $select = $this->dbSelect();
// Add order fields to select for postgres distinct queries (#6351)
if ($this->hasOrder()
&& $this->getDatasource()->getDbType() === 'pgsql'
&& $select->getPart(Zend_Db_Select::DISTINCT) === true) {
foreach ($this->getOrder() as $fieldAndDirection) {
list($alias, $field) = explode('.', $fieldAndDirection[0]);
$this->columns[$field] = $fieldAndDirection[0];
}
}
$select->columns($this->columns); $select->columns($this->columns);
$this->applyFilterSql($select); $this->applyFilterSql($select);
@ -101,6 +113,7 @@ class DbQuery extends SimpleQuery
); );
} }
} }
return $select; return $select;
} }
@ -124,7 +137,10 @@ class DbQuery extends SimpleQuery
$op = ' AND '; $op = ' AND ';
$str .= ' NOT '; $str .= ' NOT ';
} else { } else {
throw new \Exception('Cannot render filter: ' . $filter); throw new IcingaException(
'Cannot render filter: %s',
$filter
);
} }
$parts = array(); $parts = array();
if (! $filter->isEmpty()) { if (! $filter->isEmpty()) {
@ -177,7 +193,7 @@ class DbQuery extends SimpleQuery
if (! $value) { if (! $value) {
/* /*
NOTE: It's too late to throw exceptions, we might finish in __toString NOTE: It's too late to throw exceptions, we might finish in __toString
throw new \Exception(sprintf( throw new IcingaException(sprintf(
'"%s" is not a valid time expression', '"%s" is not a valid time expression',
$value $value
)); ));

View File

@ -34,9 +34,12 @@ abstract class Filter
if ((string) $id === $this->getId()) { if ((string) $id === $this->getId()) {
return $this; return $this;
} }
throw new ProgrammingError(sprintf( throw new ProgrammingError(
'Trying to get invalid filter index "%s" from "%s" ("%s")', $id, $this, $this->id 'Trying to get invalid filter index "%s" from "%s" ("%s")',
)); $id,
$this,
$this->id
);
} }
public function getId() public function getId()
@ -129,14 +132,15 @@ abstract class Filter
public static function expression($col, $op, $expression) public static function expression($col, $op, $expression)
{ {
switch ($op) { switch ($op) {
case '=': return new FilterEqual($col, $op, $expression); case '=': return new FilterMatch($col, $op, $expression);
case '<': return new FilterLessThan($col, $op, $expression); case '<': return new FilterLessThan($col, $op, $expression);
case '>': return new FilterGreaterThan($col, $op, $expression); case '>': return new FilterGreaterThan($col, $op, $expression);
case '>=': return new FilterEqualOrGreaterThan($col, $op, $expression); case '>=': return new FilterEqualOrGreaterThan($col, $op, $expression);
case '<=': return new FilterEqualOrLessThan($col, $op, $expression); case '<=': return new FilterEqualOrLessThan($col, $op, $expression);
case '!=': return new FilterNotEqual($col, $op, $expression); case '!=': return new FilterMatchNot($col, $op, $expression);
default: throw new ProgrammingError( default: throw new ProgrammingError(
sprintf('There is no such filter sign: %s', $op) 'There is no such filter sign: %s',
$op
); );
} }
} }
@ -188,7 +192,7 @@ abstract class Filter
$args = $args[0]; $args = $args[0];
} }
} }
if (count($args) > 1) { if (count($args) > 1) {
return new FilterNot(array(new FilterAnd($args))); return new FilterNot(array(new FilterAnd($args)));
} else { } else {
return new FilterNot($args); return new FilterNot($args);
@ -203,7 +207,8 @@ abstract class Filter
case 'NOT': return self::not($filters); case 'NOT': return self::not($filters);
} }
throw new ProgrammingError( throw new ProgrammingError(
sprintf('"%s" is not a valid filter chain operator', $operator) '"%s" is not a valid filter chain operator',
$operator
); );
} }

View File

@ -4,11 +4,11 @@
namespace Icinga\Data\Filter; namespace Icinga\Data\Filter;
use Exception; use Icinga\Exception\IcingaException;
/** /**
* Filter Exception Class * Filter Exception Class
* *
* Filter Exceptions should be thrown on filter parse errors or similar * Filter Exceptions should be thrown on filter parse errors or similar
*/ */
class FilterException extends Exception {} class FilterException extends IcingaException {}

View File

@ -0,0 +1,22 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Data\Filter;
class FilterMatch extends FilterExpression
{
public function matches($row)
{
$expression = (string) $this->expression;
if (strpos($expression, '*') === false) {
return (string) $row->{$this->column} === $expression;
} else {
$parts = array();
foreach (preg_split('/\*/', $expression) as $part) {
$parts[] = preg_quote($part);
}
return preg_match('/^' . implode('.*', $parts) . '$/', $row->{$this->column});
}
}
}

View File

@ -0,0 +1,22 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Data\Filter;
class FilterMatchNot extends FilterExpression
{
public function matches($row)
{
$expression = (string) $this->expression;
if (strpos($expression, '*') === false) {
return (string) $row->{$this->column} !== $expression;
} else {
$parts = array();
foreach (preg_split('/\*/', $expression) as $part) {
$parts[] = preg_quote($part);
}
return ! preg_match('/^' . implode('.*', $parts) . '$/', $row->{$this->column});
}
}
}

View File

@ -0,0 +1,13 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Data\Filter;
class FilterNotEqual extends FilterExpression
{
public function matches($row)
{
return (string) $row->{$this->column} !== (string) $this->expression;
}
}

View File

@ -4,8 +4,8 @@
namespace Icinga\Data\Filter; namespace Icinga\Data\Filter;
use Exception; use Icinga\Exception\IcingaException;
class FilterParseException extends Exception class FilterParseException extends IcingaException
{ {
} }

View File

@ -15,7 +15,7 @@ class FilterQueryString
protected $reportDebug = false; protected $reportDebug = false;
protected $length; protected $length;
protected function __construct() protected function __construct()
{ {
} }
@ -111,13 +111,13 @@ class FilterQueryString
$extra .= "\n" . implode("\n", $this->debug); $extra .= "\n" . implode("\n", $this->debug);
} }
throw new FilterParseException(sprintf( throw new FilterParseException(
'Invalid filter "%s", unexpected %s at pos %d%s', 'Invalid filter "%s", unexpected %s at pos %d%s',
$this->string, $this->string,
$char, $char,
$this->pos, $this->pos,
$extra $extra
)); );
} }
protected function readFilters($nestingLevel = 0, $op = null) protected function readFilters($nestingLevel = 0, $op = null)

View File

@ -12,15 +12,25 @@ use Icinga\Data\Db\DbConnection;
use Icinga\Protocol\Livestatus\Connection as LivestatusConnection; use Icinga\Protocol\Livestatus\Connection as LivestatusConnection;
use Icinga\Protocol\Statusdat\Reader as StatusdatReader; use Icinga\Protocol\Statusdat\Reader as StatusdatReader;
use Icinga\Protocol\Ldap\Connection as LdapConnection; use Icinga\Protocol\Ldap\Connection as LdapConnection;
use Icinga\Protocol\File\Reader as FileReader; use Icinga\Protocol\File\FileReader;
/**
* Create resources from names or resource configuration
*/
class ResourceFactory implements ConfigAwareFactory class ResourceFactory implements ConfigAwareFactory
{ {
/** /**
* Resource configuration
*
* @var Zend_Config * @var Zend_Config
*/ */
private static $resources; private static $resources;
/**
* Set resource configurations
*
* @param Zend_Config $config
*/
public static function setConfig($config) public static function setConfig($config)
{ {
self::$resources = $config; self::$resources = $config;
@ -29,17 +39,19 @@ class ResourceFactory implements ConfigAwareFactory
/** /**
* Get the configuration for a specific resource * Get the configuration for a specific resource
* *
* @param $resourceName String The resource's name * @param $resourceName String The resource's name
* *
* @return Zend_Config The configuration of the resource * @return Zend_Config The configuration of the resource
* @throws \Icinga\Exception\ConfigurationError *
* @throws ConfigurationError
*/ */
public static function getResourceConfig($resourceName) public static function getResourceConfig($resourceName)
{ {
self::assertResourcesExist(); self::assertResourcesExist();
if (($resourceConfig = self::$resources->get($resourceName)) === null) { if (($resourceConfig = self::$resources->get($resourceName)) === null) {
throw new ConfigurationError( throw new ConfigurationError(
'Cannot load resource config "' . $resourceName . '". Resource does not exist' 'Cannot load resource config "%s". Resource does not exist',
$resourceName
); );
} }
return $resourceConfig; return $resourceConfig;
@ -71,13 +83,13 @@ class ResourceFactory implements ConfigAwareFactory
/** /**
* Check if the existing resources are set. If not, throw an error. * Check if the existing resources are set. If not, throw an error.
* *
* @throws \Icinga\Exception\ProgrammingError * @throws ProgrammingError
*/ */
private static function assertResourcesExist() private static function assertResourcesExist()
{ {
if (!isset(self::$resources)) { if (!isset(self::$resources)) {
throw new ProgrammingError( throw new ProgrammingError(
"The ResourceFactory must be initialised by setting a config, before it can be used" 'The ResourceFactory must be initialised by setting a config, before it can be used'
); );
} }
} }
@ -92,7 +104,7 @@ class ResourceFactory implements ConfigAwareFactory
* *
* @return DbConnection|LdapConnection|LivestatusConnection|StatusdatReader An objects that can be used to access * @return DbConnection|LdapConnection|LivestatusConnection|StatusdatReader An objects that can be used to access
* the given resource. The returned class depends on the configuration property 'type'. * the given resource. The returned class depends on the configuration property 'type'.
* @throws \Icinga\Exception\ConfigurationError When an unsupported type is given * @throws ConfigurationError When an unsupported type is given
*/ */
public static function createResource(Zend_Config $config) public static function createResource(Zend_Config $config)
{ {
@ -113,23 +125,22 @@ class ResourceFactory implements ConfigAwareFactory
$resource = new FileReader($config); $resource = new FileReader($config);
break; break;
default: default:
throw new ConfigurationError('Unsupported resource type "' . $config->type . '"'); throw new ConfigurationError(
'Unsupported resource type "%s"',
$config->type
);
} }
return $resource; return $resource;
} }
public static function ldapAvailable() /**
* Create a resource from name
*
* @param string $resourceName
* @return DbConnection|LdapConnection|LivestatusConnection|StatusdatReader
*/
public static function create($resourceName)
{ {
return extension_loaded('ldap'); return self::createResource(self::getResourceConfig($resourceName));
}
public static function pgsqlAvailable()
{
return extension_loaded('pgsql');
}
public static function mysqlAvailable()
{
return extension_loaded('mysql');
} }
} }

View File

@ -9,6 +9,7 @@ use Icinga\Data\Filter\Filter;
use Icinga\Web\Paginator\Adapter\QueryAdapter; use Icinga\Web\Paginator\Adapter\QueryAdapter;
use Zend_Paginator; use Zend_Paginator;
use Exception; use Exception;
use Icinga\Exception\IcingaException;
class SimpleQuery implements QueryInterface, Queryable class SimpleQuery implements QueryInterface, Queryable
{ {
@ -158,7 +159,7 @@ class SimpleQuery implements QueryInterface, Queryable
public function setOrderColumns(array $orderColumns) public function setOrderColumns(array $orderColumns)
{ {
throw new Exception('This function does nothing and will be removed'); throw new IcingaException('This function does nothing and will be removed');
} }
/** /**

View File

@ -4,11 +4,9 @@
namespace Icinga\Exception; namespace Icinga\Exception;
use RuntimeException;
/** /**
* Exception thrown if an error occurs during authentication * Exception thrown if an error occurs during authentication
*/ */
class AuthenticationException extends RuntimeException class AuthenticationException extends IcingaException
{ {
} }

View File

@ -8,6 +8,6 @@ namespace Icinga\Exception;
* Class ConfigurationError * Class ConfigurationError
* @package Icinga\Exception * @package Icinga\Exception
*/ */
class ConfigurationError extends \RuntimeException class ConfigurationError extends IcingaException
{ {
} }

View File

@ -0,0 +1,29 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Exception;
use Exception;
class IcingaException extends Exception
{
/**
* @param string $message format string for vsprintf()
* Any futher args: args for vsprintf()
* @see vsprintf
*
* If there is at least one exception, the last one will be also used for the exception chaining.
*/
public function __construct($message = '')
{
$args = array_slice(func_get_args(), 1);
$exc = null;
foreach ($args as &$arg) {
if ($arg instanceof Exception) {
$exc = $arg;
}
}
parent::__construct(vsprintf($message, $args), 0, $exc);
}
}

View File

@ -4,12 +4,10 @@
namespace Icinga\Exception; namespace Icinga\Exception;
use RuntimeException;
/** /**
* Class MissingParameterException * Class MissingParameterException
* @package Icinga\Exception * @package Icinga\Exception
*/ */
class MissingParameterException extends RuntimeException class MissingParameterException extends IcingaException
{ {
} }

View File

@ -8,6 +8,6 @@ namespace Icinga\Exception;
* Class NotImplementedError * Class NotImplementedError
* @package Icinga\Exception * @package Icinga\Exception
*/ */
class NotImplementedError extends \Exception class NotImplementedError extends IcingaException
{ {
} }

View File

@ -4,8 +4,6 @@
namespace Icinga\Exception; namespace Icinga\Exception;
use RuntimeException; class NotReadableError extends IcingaException
class NotReadableError extends RuntimeException
{ {
} }

View File

@ -4,8 +4,6 @@
namespace Icinga\Exception; namespace Icinga\Exception;
use RuntimeException; class NotWritableError extends IcingaException
class NotWritableError extends RuntimeException
{ {
} }

View File

@ -8,6 +8,6 @@ namespace Icinga\Exception;
* Class ProgrammingError * Class ProgrammingError
* @package Icinga\Exception * @package Icinga\Exception
*/ */
class ProgrammingError extends \Exception class ProgrammingError extends IcingaException
{ {
} }

View File

@ -4,11 +4,9 @@
namespace Icinga\Exception; namespace Icinga\Exception;
use \Exception;
/** /**
* Handle problems according to file system permissions * Handle problems according to file system permissions
*/ */
class SystemPermissionException extends Exception class SystemPermissionException extends IcingaException
{ {
} }

View File

@ -23,10 +23,17 @@ class Logger
/** /**
* The log writer to use * The log writer to use
* *
* @var LogWriter * @var \Icinga\Logger\LogWriter
*/ */
protected $writer; protected $writer;
/**
* The configured type
*
* @string Type (syslog, file)
*/
protected $type = 'none';
/** /**
* The maximum severity to emit * The maximum severity to emit
* *
@ -52,7 +59,7 @@ class Logger
$this->verbosity = $config->level; $this->verbosity = $config->level;
if ($config->enable) { if ($config->enable) {
$this->writer = $this->getWriter($config); $this->writer = $this->createWriter($config);
} }
} }
@ -71,16 +78,19 @@ class Logger
* *
* @param Zend_Config $config The configuration to initialize the writer with * @param Zend_Config $config The configuration to initialize the writer with
* *
* @return LogWriter The requested log writer * @return \Icinga\Logger\LogWriter The requested log writer
* * @throws ConfigurationError If the requested writer cannot be found
* @throws ConfigurationError In case the requested writer cannot be found
*/ */
protected function getWriter(Zend_Config $config) protected function createWriter(Zend_Config $config)
{ {
$class = 'Icinga\\Logger\\Writer\\' . ucfirst(strtolower($config->type)) . 'Writer'; $class = 'Icinga\\Logger\\Writer\\' . ucfirst(strtolower($config->type)) . 'Writer';
if (!class_exists($class)) { if (!class_exists($class)) {
throw new ConfigurationError('Cannot find log writer of type "' . $config->type . '"'); throw new ConfigurationError(
'Cannot find log writer of type "%s"',
$config->type
);
} }
$this->type = $config->type;
return new $class($config); return new $class($config);
} }
@ -191,4 +201,34 @@ class Logger
static::$instance->log(static::formatMessage(func_get_args()), static::$DEBUG); static::$instance->log(static::formatMessage(func_get_args()), static::$DEBUG);
} }
} }
/**
* Get the log writer to use
*
* @return \Icinga\Logger\LogWriter
*/
public function getWriter()
{
return $this->writer;
}
public static function writesToSyslog()
{
return static::$instance && static::$instance->type === 'syslog';
}
public static function writesToFile()
{
return static::$instance && static::$instance->type === 'file';
}
/**
* Get this' instance
*
* @return Logger
*/
public static function getInstance()
{
return static::$instance;
}
} }

View File

@ -5,6 +5,7 @@
namespace Icinga\Logger\Writer; namespace Icinga\Logger\Writer;
use Exception; use Exception;
use Icinga\Exception\IcingaException;
use Zend_Config; use Zend_Config;
use Icinga\Util\File; use Icinga\Util\File;
use Icinga\Logger\Logger; use Icinga\Logger\Logger;
@ -33,13 +34,20 @@ class FileWriter extends LogWriter
$this->path = $config->target; $this->path = $config->target;
if (substr($this->path, 0, 6) !== 'php://' && false === file_exists(dirname($this->path))) { if (substr($this->path, 0, 6) !== 'php://' && false === file_exists(dirname($this->path))) {
throw new ConfigurationError('Log path "' . dirname($this->path) . '" does not exist'); throw new ConfigurationError(
'Log path "%s" does not exist',
dirname($this->path)
);
} }
try { try {
$this->write(''); // Avoid to handle such errors on every write access $this->write(''); // Avoid to handle such errors on every write access
} catch (Exception $e) { } catch (Exception $e) {
throw new ConfigurationError('Cannot write to log file "' . $this->path . '" (' . $e->getMessage() . ')'); throw new ConfigurationError(
'Cannot write to log file "%s" (%s)',
$this->path,
$e->getMessage()
);
} }
} }
@ -61,7 +69,7 @@ class FileWriter extends LogWriter
* *
* @return string The string representation of the severity * @return string The string representation of the severity
* *
* @throws Exception In case the given severity is unknown * @throws IcingaException In case the given severity is unknown
*/ */
protected function getSeverityString($severity) protected function getSeverityString($severity)
{ {
@ -75,7 +83,10 @@ class FileWriter extends LogWriter
case Logger::$DEBUG: case Logger::$DEBUG:
return '- DEBUG -'; return '- DEBUG -';
default: default:
throw new Exception('Unknown severity "' . $severity . '"'); throw new IcingaException(
'Unknown severity "%s"',
$severity
);
} }
} }
@ -92,4 +103,12 @@ class FileWriter extends LogWriter
$file->fwrite($text); $file->fwrite($text);
$file->fflush(); $file->fflush();
} }
/**
* @return string
*/
public function getPath()
{
return $this->path;
}
} }

View File

@ -9,6 +9,7 @@ use Zend_Config;
use Icinga\Logger\Logger; use Icinga\Logger\Logger;
use Icinga\Logger\LogWriter; use Icinga\Logger\LogWriter;
use Icinga\Exception\ConfigurationError; use Icinga\Exception\ConfigurationError;
use Icinga\Exception\IcingaException;
/** /**
* Class to write messages to syslog * Class to write messages to syslog
@ -45,7 +46,8 @@ class SyslogWriter extends LogWriter
{ {
if (!array_key_exists($config->facility, $this->facilities)) { if (!array_key_exists($config->facility, $this->facilities)) {
throw new ConfigurationError( throw new ConfigurationError(
'Cannot create syslog writer with unknown facility "' . $config->facility . '"' 'Cannot create syslog writer with unknown facility "%s"',
$config->facility
); );
} }
@ -71,7 +73,10 @@ class SyslogWriter extends LogWriter
); );
if (!array_key_exists($severity, $priorities)) { if (!array_key_exists($severity, $priorities)) {
throw new Exception('Severity "' . $severity . '" cannot be mapped to a valid syslog priority'); throw new IcingaException(
'Severity "%s" cannot be mapped to a valid syslog priority',
$severity
);
} }
$this->open(); $this->open();

View File

@ -138,7 +138,10 @@ abstract class Command
*/ */
public function getHostgroupCommand($hostgroup) public function getHostgroupCommand($hostgroup)
{ {
throw new ProgrammingError(get_class($this) . ' does not provide a hostgroup command'); throw new ProgrammingError(
'%s does not provide a hostgroup command',
get_class($this)
);
} }
/** /**
@ -150,7 +153,10 @@ abstract class Command
*/ */
public function getServicegroupCommand($servicegroup) public function getServicegroupCommand($servicegroup)
{ {
throw new ProgrammingError(get_class($this) . ' does not provide a servicegroup command'); throw new ProgrammingError(
'%s does not provide a servicegroup command',
get_class($this)
);
} }
/** /**
@ -163,6 +169,9 @@ abstract class Command
*/ */
public function getGlobalCommand($instance = null) public function getGlobalCommand($instance = null)
{ {
throw new ProgrammingError(getclass($this) . ' does not provide a global command'); throw new ProgrammingError(
'%s does not provide a global command',
getclass($this)
);
} }
} }

View File

@ -49,11 +49,9 @@ class LocalPipe implements Transport
$file->fflush(); $file->fflush();
} catch (Exception $e) { } catch (Exception $e) {
throw new ConfigurationError( throw new ConfigurationError(
sprintf( 'Could not open icinga command pipe at "%s" (%s)',
'Could not open icinga command pipe at "%s" (%s)', $this->path,
$this->path, $e->getMessage()
$e->getMessage()
)
); );
} }

View File

@ -4,7 +4,7 @@
namespace Icinga\Protocol\Commandpipe\Transport; namespace Icinga\Protocol\Commandpipe\Transport;
use \Zend_Config; use Zend_Config;
/** /**
* Interface for Transport classes handling the concrete access to the command pipe * Interface for Transport classes handling the concrete access to the command pipe

View File

@ -2,9 +2,9 @@
namespace Icinga\Protocol\File; namespace Icinga\Protocol\File;
use RuntimeException; use Icinga\Exception\IcingaException;
/** /**
* Exception thrown if a file reader specific error occurs * Exception thrown if a file reader specific error occurs
*/ */
class FileReaderException extends RuntimeException {} class FileReaderException extends IcingaException {}

View File

@ -0,0 +1,82 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Protocol\File;
use FilterIterator;
use Icinga\Util\File;
/**
* Class FileIterator
*
* Iterate over a file, yielding only fields of non-empty lines which match a PCRE expression
*/
class FileIterator extends FilterIterator
{
/**
* A PCRE string with the fields to extract from the file's lines as named subpatterns
*
* @var string
*/
protected $fields;
/**
* An associative array of the current line's fields ($field => $value)
*
* @var array
*/
protected $currentData;
public function __construct($filename, $fields)
{
$this->fields = $fields;
$f = new File($filename);
$f->setFlags(
File::DROP_NEW_LINE |
File::READ_AHEAD |
File::SKIP_EMPTY
);
parent::__construct($f);
}
/**
* Return the current data
*
* @return array
*/
public function current()
{
return $this->currentData;
}
/**
* Accept lines matching the given PCRE pattern
*
* @return bool
*
* @throws FileReaderException If PHP failed parsing the PCRE pattern
*/
public function accept()
{
$data = array();
$matched = preg_match(
$this->fields,
$this->getInnerIterator()->current(),
$data
);
if ($matched === false) {
throw new FileReaderException('Failed parsing regular expression!');
} else if ($matched === 1) {
foreach ($data as $key => $value) {
if (is_int($key)) {
unset($data[$key]);
}
}
$this->currentData = $data;
return true;
}
return false;
}
}

View File

@ -8,13 +8,13 @@ use Icinga\Data\SimpleQuery;
use Icinga\Data\Filter\Filter; use Icinga\Data\Filter\Filter;
/** /**
* Class Query * Class FileQuery
* *
* Query for Datasource Icinga\Protocol\File\Reader * Query for Datasource Icinga\Protocol\File\FileReader
* *
* @package Icinga\Protocol\File * @package Icinga\Protocol\File
*/ */
class Query extends SimpleQuery class FileQuery extends SimpleQuery
{ {
/** /**
* Sort direction * Sort direction
@ -41,7 +41,7 @@ class Query extends SimpleQuery
* *
* @param string $dir Sort direction, 'ASC' or 'DESC' (default) * @param string $dir Sort direction, 'ASC' or 'DESC' (default)
* *
* @return Query * @return FileQuery
*/ */
public function order($field, $direction = null) public function order($field, $direction = null)
{ {
@ -66,7 +66,7 @@ class Query extends SimpleQuery
* *
* @param string $expression the filter expression to be applied * @param string $expression the filter expression to be applied
* *
* @return Query * @return FileQuery
*/ */
public function andWhere($expression) public function andWhere($expression)
{ {

View File

@ -4,16 +4,15 @@
namespace Icinga\Protocol\File; namespace Icinga\Protocol\File;
use FilterIterator; use Icinga\Data\Selectable;
use Iterator; use Countable;
use Icinga\Util\Enumerate;
use Zend_Config; use Zend_Config;
use Icinga\Protocol\File\FileReaderException;
use Icinga\Util\File;
/** /**
* Read file line by line * Read file line by line
*/ */
class Reader extends FilterIterator class FileReader implements Selectable, Countable
{ {
/** /**
* A PCRE string with the fields to extract from the file's lines as named subpatterns * A PCRE string with the fields to extract from the file's lines as named subpatterns
@ -23,11 +22,11 @@ class Reader extends FilterIterator
protected $fields; protected $fields;
/** /**
* An associative array of the current line's fields ($field => $value) * Name of the target file
* *
* @var array * @var string
*/ */
protected $currentData; protected $filename;
/** /**
* Create a new reader * Create a new reader
@ -39,67 +38,34 @@ class Reader extends FilterIterator
public function __construct(Zend_Config $config) public function __construct(Zend_Config $config)
{ {
foreach (array('filename', 'fields') as $key) { foreach (array('filename', 'fields') as $key) {
if (! isset($config->{$key})) { if (isset($config->{$key})) {
throw new FileReaderException('The directive `' . $key . '\' is required'); $this->{$key} = $config->{$key};
} else {
throw new FileReaderException('The directive `%s\' is required', $key);
} }
} }
$this->fields = $config->fields;
$f = new File($config->filename);
$f->setFlags(
File::DROP_NEW_LINE |
File::READ_AHEAD |
File::SKIP_EMPTY
);
parent::__construct($f);
} }
/** /**
* Return the current data * Instantiate a FileIterator object with the target file
* *
* @return array * @return FileIterator
*/ */
public function current() public function iterate()
{ {
return $this->currentData; return new Enumerate(
} new FileIterator($this->filename, $this->fields)
/**
* Accept lines matching the given PCRE pattern
*
* @return bool
*
* @throws FileReaderException If PHP failed parsing the PCRE pattern
*/
public function accept()
{
$data = array();
$matched = @preg_match(
$this->fields,
$this->getInnerIterator()->current(),
$data
); );
if ($matched === false) {
throw new FileReaderException('Failed parsing regular expression!');
} else if ($matched === 1) {
foreach ($data as $key) {
if (is_int($key)) {
unset($data[$key]);
}
}
$this->currentData = $data;
return true;
}
return false;
} }
/** /**
* Instantiate a Query object * Instantiate a FileQuery object
* *
* @return Query * @return FileQuery
*/ */
public function select() public function select()
{ {
return new Query($this); return new FileQuery($this);
} }
/** /**
@ -109,17 +75,17 @@ class Reader extends FilterIterator
*/ */
public function count() public function count()
{ {
return iterator_count($this); return iterator_count($this->iterate());
} }
/** /**
* Fetch result as an array of objects * Fetch result as an array of objects
* *
* @param Query $query * @param FileQuery $query
* *
* @return array * @return array
*/ */
public function fetchAll(Query $query) public function fetchAll(FileQuery $query)
{ {
$all = array(); $all = array();
foreach ($this->fetchPairs($query) as $index => $value) { foreach ($this->fetchPairs($query) as $index => $value) {
@ -131,32 +97,32 @@ class Reader extends FilterIterator
/** /**
* Fetch result as a key/value pair array * Fetch result as a key/value pair array
* *
* @param Query $query * @param FileQuery $query
* *
* @return array * @return array
*/ */
public function fetchPairs(Query $query) public function fetchPairs(FileQuery $query)
{ {
$skipLines = $query->getOffset(); $skip = $query->getOffset();
$readLines = $query->getLimit(); $read = $query->getLimit();
if ($skipLines === null) { if ($skip === null) {
$skipLines = 0; $skip = 0;
} }
$lines = array(); $lines = array();
if ($query->sortDesc()) { if ($query->sortDesc()) {
$count = $this->count($query); $count = $this->count($query);
if ($count <= $skipLines) { if ($count <= $skip) {
return $lines; return $lines;
} else if ($count < ($skipLines + $readLines)) { } else if ($count < ($skip + $read)) {
$readLines = $count - $skipLines; $read = $count - $skip;
$skipLines = 0; $skip = 0;
} else { } else {
$skipLines = $count - ($skipLines + $readLines); $skip = $count - ($skip + $read);
} }
} }
foreach ($this as $index => $line) { foreach ($this->iterate() as $index => $line) {
if ($index >= $skipLines) { if ($index >= $skip) {
if ($index >= $skipLines + $readLines) { if ($index >= $skip + $read) {
break; break;
} }
$lines[] = $line; $lines[] = $line;
@ -171,11 +137,11 @@ class Reader extends FilterIterator
/** /**
* Fetch first result row * Fetch first result row
* *
* @param Query $query * @param FileQuery $query
* *
* @return object * @return object
*/ */
public function fetchRow(Query $query) public function fetchRow(FileQuery $query)
{ {
$all = $this->fetchAll($query); $all = $this->fetchAll($query);
if (isset($all[0])) { if (isset($all[0])) {
@ -187,11 +153,11 @@ class Reader extends FilterIterator
/** /**
* Fetch first result column * Fetch first result column
* *
* @param Query $query * @param FileQuery $query
* *
* @return array * @return array
*/ */
public function fetchColumn(Query $query) public function fetchColumn(FileQuery $query)
{ {
$column = array(); $column = array();
foreach ($this->fetchPairs($query) as $pair) { foreach ($this->fetchPairs($query) as $pair) {
@ -206,11 +172,11 @@ class Reader extends FilterIterator
/** /**
* Fetch first column value from first result row * Fetch first column value from first result row
* *
* @param Query $query * @param FileQuery $query
* *
* @return mixed * @return mixed
*/ */
public function fetchOne(Query $query) public function fetchOne(FileQuery $query)
{ {
$pairs = $this->fetchPairs($query); $pairs = $this->fetchPairs($query);
if (isset($pairs[0])) { if (isset($pairs[0])) {

View File

@ -8,7 +8,7 @@ use Icinga\Protocol\Ldap\Exception as LdapException;
use Icinga\Application\Platform; use Icinga\Application\Platform;
use Icinga\Application\Config; use Icinga\Application\Config;
use Icinga\Logger\Logger; use Icinga\Logger\Logger;
use \Zend_Config; use Zend_Config;
/** /**
* Backend class managing all the LDAP stuff for you. * Backend class managing all the LDAP stuff for you.
@ -307,7 +307,7 @@ class Connection
$results = @ldap_search( $results = @ldap_search(
$this->ds, $this->ds,
$base, $base,
(string) $query, $query->create(),
$fields, $fields,
0, // Attributes and values 0, // Attributes and values
0 // No limit - at least where possible 0 // No limit - at least where possible
@ -619,7 +619,7 @@ class Connection
$result = @ldap_read( $result = @ldap_read(
$ds, $ds,
'', '',
(string) $query, $query->create(),
$query->listFields() $query->listFields()
); );

View File

@ -83,11 +83,9 @@ class Query
{ {
if (! preg_match('~^\d+~', $count . $offset)) { if (! preg_match('~^\d+~', $count . $offset)) {
throw new Exception( throw new Exception(
sprintf( 'Got invalid limit: %s, %s',
'Got invalid limit: %s, %s', $count,
$count, $offset
$offset
)
); );
} }
$this->limit_count = (int) $count; $this->limit_count = (int) $count;
@ -302,21 +300,11 @@ class Query
* *
* @string * @string
*/ */
public function __toString() public function create()
{
return $this->render();
}
/**
* Returns the LDAP filter that will be applied
*
* @string
*/
protected function render()
{ {
$parts = array(); $parts = array();
if (! isset($this->filters['objectClass']) || $this->filters['objectClass'] === null) { if (! isset($this->filters['objectClass']) || $this->filters['objectClass'] === null) {
// throw new Exception('Object class is mandatory'); throw new Exception('Object class is mandatory');
} }
foreach ($this->filters as $key => $value) { foreach ($this->filters as $key => $value) {
$parts[] = sprintf( $parts[] = sprintf(

View File

@ -4,6 +4,8 @@
namespace Icinga\Protocol\Ldap; namespace Icinga\Protocol\Ldap;
use Icinga\Exception\IcingaException;
/** /**
* This class is a special node object, representing your connections root node * This class is a special node object, representing your connections root node
* *
@ -95,16 +97,14 @@ class Root
/** /**
* @param $rdn * @param $rdn
* @return mixed * @return mixed
* @throws Exception * @throws IcingaException
*/ */
public function getChildByRDN($rdn) public function getChildByRDN($rdn)
{ {
if (!$this->hasChildRDN($rdn)) { if (!$this->hasChildRDN($rdn)) {
throw new Exception( throw new IcingaException(
sprintf( 'The child RDN "%s" is not available',
'The child RDN "%s" is not available', $rdn
$rdn
)
); );
} }
return $this->children[strtolower($rdn)]; return $this->children[strtolower($rdn)];
@ -154,28 +154,24 @@ class Root
/** /**
* @param $dn * @param $dn
* @return $this * @return $this
* @throws Exception * @throws IcingaException
*/ */
protected function assertSubDN($dn) protected function assertSubDN($dn)
{ {
$mydn = $this->getDN(); $mydn = $this->getDN();
$end = substr($dn, -1 * strlen($mydn)); $end = substr($dn, -1 * strlen($mydn));
if (strtolower($end) !== strtolower($mydn)) { if (strtolower($end) !== strtolower($mydn)) {
throw new Exception( throw new IcingaException(
sprintf( '"%s" is not a child of "%s"',
'"%s" is not a child of "%s"', $dn,
$dn, $mydn
$mydn
)
); );
} }
if (strlen($dn) === strlen($mydn)) { if (strlen($dn) === strlen($mydn)) {
throw new Exception( throw new IcingaException(
sprintf( '"%s" is not a child of "%s", they are equal',
'"%s" is not a child of "%s", they are equal', $dn,
$dn, $mydn
$mydn
)
); );
} }
return $this; return $this;

View File

@ -6,6 +6,7 @@ namespace Icinga\Protocol\Livestatus;
use Icinga\Application\Benchmark; use Icinga\Application\Benchmark;
use Exception; use Exception;
use Icinga\Exception\IcingaException;
/** /**
* Backend class managing handling MKI Livestatus connections * Backend class managing handling MKI Livestatus connections
@ -73,22 +74,18 @@ class Connection
$this->assertPhpExtensionLoaded('sockets'); $this->assertPhpExtensionLoaded('sockets');
if ($socket[0] === '/') { if ($socket[0] === '/') {
if (! is_writable($socket)) { if (! is_writable($socket)) {
throw new \Exception( throw new IcingaException(
sprintf( 'Cannot write to livestatus socket "%s"',
'Cannot write to livestatus socket "%s"', $socket
$socket
)
); );
} }
$this->socket_type = self::TYPE_UNIX; $this->socket_type = self::TYPE_UNIX;
$this->socket_path = $socket; $this->socket_path = $socket;
} else { } else {
if (! preg_match('~^tcp://([^:]+):(\d+)~', $socket, $m)) { if (! preg_match('~^tcp://([^:]+):(\d+)~', $socket, $m)) {
throw new \Exception( throw new IcingaException(
sprintf( 'Invalid TCP socket syntax: "%s"',
'Invalid TCP socket syntax: "%s"', $socket
$socket
)
); );
} }
// TODO: Better syntax checks // TODO: Better syntax checks
@ -156,17 +153,15 @@ class Connection
$length = (int) trim(substr($header, 4)); $length = (int) trim(substr($header, 4));
$body = $this->readFromSocket($length); $body = $this->readFromSocket($length);
if ($status !== 200) { if ($status !== 200) {
throw new Exception( throw new IcingaException(
sprintf( 'Problem while reading %d bytes from livestatus: %s',
'Problem while reading %d bytes from livestatus: %s', $length,
$length, $body
$body
)
); );
} }
$result = json_decode($body); $result = json_decode($body);
if ($result === null) { if ($result === null) {
throw new Exception('Got invalid response body from livestatus'); throw new IcingaException('Got invalid response body from livestatus');
} }
return $result; return $result;
@ -180,11 +175,9 @@ class Connection
while ($offset < $length) { while ($offset < $length) {
$data = socket_read($this->connection, $length - $offset); $data = socket_read($this->connection, $length - $offset);
if ($data === false) { if ($data === false) {
throw new Exception( throw new IcingaException(
sprintf( 'Failed to read from livestatus socket: %s',
'Failed to read from livestatus socket: %s', socket_strerror(socket_last_error($this->connection))
socket_strerror(socket_last_error($this->connection))
)
); );
} }
$size = strlen($data); $size = strlen($data);
@ -196,12 +189,10 @@ class Connection
} }
} }
if ($offset !== $length) { if ($offset !== $length) {
throw new \Exception( throw new IcingaException(
sprintf( 'Got only %d instead of %d bytes from livestatus socket',
'Got only %d instead of %d bytes from livestatus socket', $offset,
$offset, $length
$length
)
); );
} }
@ -212,7 +203,7 @@ class Connection
{ {
$res = socket_write($this->connection, $data); $res = socket_write($this->connection, $data);
if ($res === false) { if ($res === false) {
throw new \Exception('Writing to livestatus socket failed'); throw new IcingaException('Writing to livestatus socket failed');
} }
return true; return true;
} }
@ -220,11 +211,9 @@ class Connection
protected function assertPhpExtensionLoaded($name) protected function assertPhpExtensionLoaded($name)
{ {
if (! extension_loaded($name)) { if (! extension_loaded($name)) {
throw new \Exception( throw new IcingaException(
sprintf( 'The extension "%s" is not loaded',
'The extension "%s" is not loaded', $name
$name
)
); );
} }
} }
@ -250,13 +239,11 @@ class Connection
$this->connection = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); $this->connection = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if (! @socket_connect($this->connection, $this->socket_host, $this->socket_port)) { if (! @socket_connect($this->connection, $this->socket_host, $this->socket_port)) {
throw new \Exception( throw new IcingaException(
sprintf( 'Cannot connect to livestatus TCP socket "%s:%d": %s',
'Cannot connect to livestatus TCP socket "%s:%d": %s', $this->socket_host,
$this->socket_host, $this->socket_port,
$this->socket_port, socket_strerror(socket_last_error($this->connection))
socket_strerror(socket_last_error($this->connection))
)
); );
} }
socket_set_option($this->connection, SOL_TCP, TCP_NODELAY, 1); socket_set_option($this->connection, SOL_TCP, TCP_NODELAY, 1);
@ -266,11 +253,9 @@ class Connection
{ {
$this->connection = socket_create(AF_UNIX, SOCK_STREAM, 0); $this->connection = socket_create(AF_UNIX, SOCK_STREAM, 0);
if (! socket_connect($this->connection, $this->socket_path)) { if (! socket_connect($this->connection, $this->socket_path)) {
throw new \Exception( throw new IcingaException(
sprintf( 'Cannot connect to livestatus local socket "%s"',
'Cannot connect to livestatus local socket "%s"', $this->socket_path
$this->socket_path
)
); );
} }
} }

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