Merge branch 'bugfix/rebuild-form-builder-5525' into bugfix/commands-6593

Conflicts:
	library/Icinga/Protocol/Commandpipe/Transport/Transport.php
This commit is contained in:
Eric Lippmann 2014-08-29 17:24:44 +02:00
commit a01ee00c27
136 changed files with 1975 additions and 1409 deletions

View File

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

View File

@ -6,19 +6,16 @@ use Icinga\Web\Controller\BaseConfigController;
use Icinga\Web\Widget\AlertMessageBox;
use Icinga\Web\Notification;
use Icinga\Application\Modules\Module;
use Icinga\Web\Form;
use Icinga\Web\Widget;
use Icinga\Application\Icinga;
use Icinga\Application\Config as IcingaConfig;
use Icinga\Form\Config\GeneralForm;
use Icinga\Form\Config\Authentication\LdapBackendForm;
use Icinga\Form\Config\Authentication\DbBackendForm;
use Icinga\Form\Config\Authentication\AutologinBackendForm;
use Icinga\Form\Config\AuthenticationBackendReorderForm;
use Icinga\Form\Config\AuthenticationBackendConfigForm;
use Icinga\Form\Config\ResourceForm;
use Icinga\Form\Config\LoggingForm;
use Icinga\Form\Config\ConfirmRemovalForm;
use Icinga\Config\PreservingIniWriter;
use Icinga\Exception\ConfigurationError;
use Icinga\Data\ResourceFactory;
/**
@ -142,47 +139,17 @@ class ConfigController extends BaseConfigController
}
/**
* Action for reordering authentication backends
* Action for listing and reordering authentication backends
*/
public function authenticationAction()
{
$this->view->messageBox = new AlertMessageBox(true);
$form = new AuthenticationBackendReorderForm();
$form->setConfig(IcingaConfig::app('authentication'));
$form->handleRequest();
$this->view->form = $form;
$this->view->tabs->activate('authentication');
$config = IcingaConfig::app('authentication');
$backendOrder = array_keys($config->toArray());
$form = new Form();
$form->setName('form_reorder_authbackend');
$request = $this->getRequest();
if ($request->isPost()) {
$requestData = $request->getPost();
if ($form->isValid($requestData)) { // Validate the CSRF token
$reordered = false;
foreach ($backendOrder as $backendName) {
if (isset($requestData[$backendName])) {
array_splice($backendOrder, array_search($backendName, $backendOrder), 1);
array_splice($backendOrder, $requestData[$backendName], 0, $backendName);
$reordered = true;
break;
}
}
if ($reordered) {
$reorderedConfig = array();
foreach ($backendOrder as $backendName) {
$reorderedConfig[$backendName] = $config->{$backendName};
}
if ($this->writeAuthenticationFile($reorderedConfig)) {
Notification::success($this->translate('Authentication order updated!'));
$this->redirectNow('config/authentication');
}
}
}
}
$this->view->form = $form->create(); // Necessary in case its a GET request
$this->view->backendNames = $backendOrder;
$this->render('authentication/reorder');
}
/**
@ -190,172 +157,66 @@ class ConfigController extends BaseConfigController
*/
public function createauthenticationbackendAction()
{
$this->view->messageBox = new AlertMessageBox(true);
$this->view->tabs->activate('authentication');
$form = new AuthenticationBackendConfigForm();
$form->setConfig(IcingaConfig::app('authentication'));
$form->setResourceConfig(ResourceFactory::getResourceConfigs());
$form->setRedirectUrl('config/authentication');
$form->handleRequest();
$backendType = $this->getRequest()->getParam('type');
$authenticationConfig = IcingaConfig::app('authentication')->toArray();
try {
switch ($backendType) {
case 'ldap':
$form = new LdapBackendForm();
break;
case 'db':
$form = new DbBackendForm();
break;
case 'autologin':
foreach ($authenticationConfig as $ac) {
if (array_key_exists('backend', $ac) && $ac['backend'] === 'autologin') {
throw new ConfigurationError(
$this->translate('An autologin backend already exists')
);
}
}
$form = new AutologinBackendForm();
break;
default:
$this->addErrorMessage(sprintf(
$this->translate('There is no backend type `%s\''),
$backendType
));
$this->redirectNow('config/configurationerror');
}
} catch (ConfigurationError $e) {
$this->addErrorMessage($e->getMessage());
$this->redirectNow('config/configurationerror');
}
$request = $this->getRequest();
if ($request->isPost() && $form->isValid($request->getPost())) {
list($backendName, $backendConfig) = $form->getBackendConfig();
if (isset($authenticationConfig[$backendName])) {
$this->addErrorMessage(
$this->translate('Backend name already exists')
);
} else {
$authenticationConfig[$backendName] = $backendConfig;
if ($this->writeConfigFile($authenticationConfig, 'authentication')) {
$this->addSuccessMessage(
$this->translate('Backend Modification Written.')
);
$this->redirectNow('config/authentication');
}
}
}
$this->view->messageBox->addForm($form);
$this->view->form = $form;
$this->view->tabs->activate('authentication');
$this->render('authentication/create');
}
/**
* Form for editing backends
*
* Mostly the same like the createAuthenticationBackendAction, but with additional checks for backend existence
* and form population
* Action for editing authentication backends
*/
public function editauthenticationbackendAction()
{
$this->view->messageBox = new AlertMessageBox(true);
$form = new AuthenticationBackendConfigForm();
$form->setConfig(IcingaConfig::app('authentication'));
$form->setResourceConfig(ResourceFactory::getResourceConfigs());
$form->setRedirectUrl('config/authentication');
$form->handleRequest();
$configArray = IcingaConfig::app('authentication', true)->toArray();
$authBackend = $this->getParam('auth_backend');
if (false === isset($configArray[$authBackend])) {
$this->addErrorMessage(
$this->translate('Can\'t edit: Unknown Authentication Backend Provided')
);
$this->redirectNow('config/configurationerror');
}
if (false === array_key_exists('backend', $configArray[$authBackend])) {
$this->addErrorMessage(sprintf(
$this->translate('Backend "%s" has no `backend\' setting'),
$authBackend
));
$this->redirectNow('config/configurationerror');
}
$type = $configArray[$authBackend]['backend'];
switch ($type) {
case 'ldap':
$form = new LdapBackendForm();
break;
case 'db':
$form = new DbBackendForm();
break;
case 'autologin':
$form = new AutologinBackendForm();
break;
default:
$this->addErrorMessage(sprintf(
$this->translate('Can\'t edit: backend type "%s" of given resource not supported.'),
$type
));
$this->redirectNow('config/configurationerror');
}
$request = $this->getRequest();
if ($request->isPost()) {
if ($form->isValid($request->getPost())) {
list($backendName, $backendConfig) = $form->getBackendConfig();
$configArray[$backendName] = $backendConfig;
if ($backendName != $authBackend) {
unset($configArray[$authBackend]);
}
if ($this->writeAuthenticationFile($configArray)) {
// redirect to overview with success message
Notification::success(sprintf(
$this->translate('Backend "%s" saved'),
$backendName
));
$this->redirectNow('config/authentication');
}
return;
}
} else {
$form->setBackendConfig($authBackend, $configArray[$authBackend]);
}
$this->view->messageBox->addForm($form);
$this->view->name = $authBackend;
$this->view->form = $form;
$this->view->tabs->activate('authentication');
$this->render('authentication/modify');
}
/**
* Action for removing a backend from the authentication list.
*
* Redirects to the overview after removal is finished
* Action for removing a backend from the authentication list
*/
public function removeauthenticationbackendAction()
{
$this->view->messageBox = new AlertMessageBox(true);
$form = new ConfirmRemovalForm(array(
'onSuccess' => function ($request) {
$configForm = new AuthenticationBackendConfigForm();
$configForm->setConfig(IcingaConfig::app('authentication'));
$authBackend = $request->getQuery('auth_backend');
$configArray = IcingaConfig::app('authentication', true)->toArray();
$authBackend = $this->getParam('auth_backend');
if (false === array_key_exists($authBackend, $configArray)) {
$this->addErrorMessage(
$this->translate('Can\'t perform removal: Unknown authentication backend provided')
);
$this->redirectNow('config/configurationerror');
}
try {
$configForm->remove($authBackend);
} catch (InvalidArgumentException $e) {
Notification::error($e->getMessage());
return;
}
$form = new ConfirmRemovalForm();
$request = $this->getRequest();
if ($request->isPost() && $form->isValid($request->getPost())) {
unset($configArray[$authBackend]);
if ($this->writeAuthenticationFile($configArray)) {
Notification::success(sprintf(
$this->translate('Authentication Backend "%s" Removed'),
$authBackend
));
$this->redirectNow('config/authentication');
if ($configForm->save()) {
Notification::success(sprintf(
t('Authentication backend "%s" has been successfully removed'),
$authBackend
));
} else {
return false;
}
}
}
));
$form->setRedirectUrl('config/authentication');
$form->handleRequest();
$this->view->form = $form;
$this->view->name = $authBackend;
$this->view->tabs->activate('authentication');
$this->render('authentication/remove');
}

View File

@ -2,7 +2,6 @@
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
use \Zend_Config;
use Icinga\Web\Url;
use Icinga\Logger\Logger;
use Icinga\Config\PreservingIniWriter;
@ -12,6 +11,7 @@ use Icinga\Form\Dashboard\AddUrlForm;
use Icinga\Exception\NotReadableError;
use Icinga\Exception\ConfigurationError;
use Icinga\Web\Controller\ActionController;
use Icinga\Exception\IcingaException;
/**
* Handle creation, removal and displaying of dashboards, panes and components
@ -42,7 +42,7 @@ class DashboardController extends ActionController
}
$dashboard->readConfig($dashboardConfig);
} 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 $dashboard;

View File

@ -31,11 +31,11 @@ class LayoutController extends ActionController
{
$topbarHtmlParts = array();
/** @var Hook\Layout\TopBar $hook */
/** @var Hook\TopBarHook $hook */
$hook = null;
foreach (Hook::all('TopBar') as $hook) {
$topbarHtmlParts[] = $hook->getHtml($this->getRequest(), $this->view);
$topbarHtmlParts[] = $hook->getHtml($this->getRequest());
}
$this->view->topbarHtmlParts = $topbarHtmlParts;

View File

@ -45,8 +45,7 @@ class ListController extends Controller
file_exists($config_ini['logging']['target'])
)
) {
$config = ResourceFactory::getResourceConfig('logfile');
$resource = ResourceFactory::createResource($config);
$resource = ResourceFactory::create('logfile');
$this->view->logData = $resource->select()->order('DESC')->paginate();
} else {
$this->view->logData = null;

View File

@ -2,7 +2,7 @@
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
use \Zend_Controller_Action_Exception as ActionException;
use Zend_Controller_Action_Exception as ActionException;
use Icinga\Web\Controller\ActionController;
use Icinga\Application\Icinga;
use Icinga\Logger\Logger;

View File

@ -5,19 +5,19 @@
namespace Icinga\Form\Config\Authentication;
use Zend_Validate_Callback;
use Icinga\Web\Form;
/**
* Form class for adding/modifying autologin authentication backends
*/
class AutologinBackendForm extends BaseBackendForm
class AutologinBackendForm extends Form
{
/**
* Initialize this form
*/
public function init()
{
$this->setName('form_config_authentication_autologin');
$this->setSubmitLabel(t('Save Changes'));
$this->setName('form_config_authbackend_autologin');
}
/**
@ -31,7 +31,6 @@ class AutologinBackendForm extends BaseBackendForm
'name',
array(
'required' => true,
'allowEmpty' => false,
'label' => t('Backend Name'),
'helptext' => t('The name of this authentication backend'),
'validators' => array(
@ -53,7 +52,6 @@ class AutologinBackendForm extends BaseBackendForm
'strip_username_regexp',
array(
'required' => true,
'allowEmpty' => false,
'label' => t('Backend Domain Pattern'),
'helptext' => t('The domain pattern of this authentication backend'),
'value' => '/\@[^$]+$/',
@ -76,13 +74,15 @@ class AutologinBackendForm extends BaseBackendForm
}
/**
* Validate the configuration state of this backend
* Validate the configuration by creating a backend and requesting the user count
*
* Returns just true as autologins are being handled externally by the webserver.
* Returns always true as autologin backends are just "passive" backends. (The webserver authenticates users.)
*
* @return true
* @param Form $form The form to fetch the configuration values from
*
* @return bool Whether validation succeeded or not
*/
public function isValidAuthenticationBackend()
public function isValidAuthenticationBackend(Form $form)
{
return true;
}

View File

@ -1,94 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Form\Config\Authentication;
use Icinga\Web\Form;
/**
* Base form for authentication backend forms
*/
abstract class BaseBackendForm extends Form
{
/**
* Return whether the given values are complete/valid and check whether it is possible to connect to the backend
*
* If connection validation fails, a checkbox is prepended to the form to allow users to skip it.
*
* @param array $data The data to validate
*
* @return bool Whether the validation succeeded or not
*/
public function isValid($data)
{
if (false === parent::isValid($data)) {
return false;
}
if (
(false === isset($data['force_creation']) || false === $data['force_creation'])
&& false === $this->isValidAuthenticationBackend()
) {
$this->addForceCreationCheckbox();
return false;
}
return true;
}
/**
* Validate the configuration state of this backend with the concrete authentication backend.
*
* An implementation should not throw any exception, but use the add/setErrorMessages method
* of Zend_Form. If the 'force_creation' checkbox is set, this method won't be called.
*
* @return bool Whether validation succeeded or not
*/
abstract public function isValidAuthenticationBackend();
/**
* Return the backend's configuration values and its name
*
* The first value is the name and the second one the values as array.
*
* @return array
*/
public function getBackendConfig()
{
$values = $this->getValues();
$name = $values['name'];
unset($values['name']);
return array($name, $values);
}
/**
* Populate the form with the given configuration values
*
* @param string $name The name of the backend
* @param array $config The configuration values
*/
public function setBackendConfig($name, array $config)
{
$config['name'] = $name;
$this->populate($config);
}
/**
* Add a checkbox to be displayed at the beginning of the form
* which allows the user to skip the connection validation
*/
protected function addForceCreationCheckbox()
{
$this->addElement(
'checkbox',
'force_creation',
array(
'order' => 0,
'ignore' => true,
'label' => t('Force Changes'),
'helptext' => t('Check this box to enforce changes without connectivity validation')
)
);
}
}

View File

@ -5,17 +5,18 @@
namespace Icinga\Form\Config\Authentication;
use Exception;
use Icinga\Web\Form;
use Icinga\Web\Request;
use Icinga\Data\ResourceFactory;
use Icinga\Exception\ConfigurationError;
use Icinga\Authentication\Backend\DbUserBackend;
/**
* Form class for adding/modifying database authentication backends
*/
class DbBackendForm extends BaseBackendForm
class DbBackendForm extends Form
{
/**
* The available database resources prepared to be used as select input data
* The database resource names the user can choose from
*
* @var array
*/
@ -23,28 +24,23 @@ class DbBackendForm extends BaseBackendForm
/**
* Initialize this form
*
* Populates $this->resources.
*
* @throws ConfigurationError In case no database resources can be found
*/
public function init()
{
$this->setName('form_config_authentication_db');
$this->setSubmitLabel(t('Save Changes'));
$this->setName('form_config_authbackend_db');
}
$dbResources = array_keys(
ResourceFactory::getResourceConfigs('db')->toArray()
);
if (empty($dbResources)) {
throw new ConfigurationError(
t('There are no database resources')
);
}
// array_combine() is necessary in order to use the array as select input data
$this->resources = array_combine($dbResources, $dbResources);
/**
* Set the resource names the user can choose from
*
* @param array $resources The resources to choose from
*
* @return self
*/
public function setResources(array $resources)
{
$this->resources = $resources;
return $this;
}
/**
@ -69,7 +65,9 @@ class DbBackendForm extends BaseBackendForm
'required' => true,
'label' => t('Database Connection'),
'helptext' => t('The database connection to use for authenticating with this provider'),
'multiOptions' => $this->resources
'multiOptions' => false === empty($this->resources)
? array_combine($this->resources, $this->resources)
: array()
)
),
$this->createElement(
@ -84,25 +82,36 @@ class DbBackendForm extends BaseBackendForm
}
/**
* Validate the current configuration by creating a backend and requesting the user count
* Validate that the selected resource is a valid database authentication backend
*
* @return bool Whether validation succeeded or not
*
* @see BaseBackendForm::isValidAuthenticationBackend()
* @see Form::onSuccess()
*/
public function isValidAuthenticationBackend()
public function onSuccess(Request $request)
{
if (false === $this->isValidAuthenticationBackend($this)) {
return false;
}
}
/**
* Validate the configuration by creating a backend and requesting the user count
*
* @param Form $form The form to fetch the configuration values from
*
* @return bool Whether validation succeeded or not
*/
public function isValidAuthenticationBackend(Form $form)
{
$element = $form->getElement('resource');
try {
$testConnection = ResourceFactory::createResource(ResourceFactory::getResourceConfig(
$this->getValue('resource')
));
$dbUserBackend = new DbUserBackend($testConnection);
$dbUserBackend = new DbUserBackend(ResourceFactory::create($element->getValue()));
if ($dbUserBackend->count() < 1) {
$this->addErrorMessage(t('No users found under the specified database backend'));
$element->addError(t('No users found under the specified database backend'));
return false;
}
} catch (Exception $e) {
$this->addErrorMessage(sprintf(t('Using the specified backend failed: %s'), $e->getMessage()));
$element->addError(sprintf(t('Using the specified backend failed: %s'), $e->getMessage()));
return false;
}

View File

@ -5,17 +5,17 @@
namespace Icinga\Form\Config\Authentication;
use Exception;
use Icinga\Web\Form;
use Icinga\Data\ResourceFactory;
use Icinga\Exception\ConfigurationError;
use Icinga\Authentication\Backend\LdapUserBackend;
/**
* Form for adding or modifying LDAP authentication backends
* Form class for adding/modifying LDAP authentication backends
*/
class LdapBackendForm extends BaseBackendForm
class LdapBackendForm extends Form
{
/**
* The available ldap resources prepared to be used as select input data
* The ldap resource names the user can choose from
*
* @var array
*/
@ -23,28 +23,23 @@ class LdapBackendForm extends BaseBackendForm
/**
* Initialize this form
*
* Populates $this->resources.
*
* @throws ConfigurationError In case no database resources can be found
*/
public function init()
{
$this->setName('form_config_authentication_ldap');
$this->setSubmitLabel(t('Save Changes'));
$this->setName('form_config_authbackend_ldap');
}
$ldapResources = array_keys(
ResourceFactory::getResourceConfigs('ldap')->toArray()
);
if (empty($ldapResources)) {
throw new ConfigurationError(
t('There are no LDAP resources')
);
}
// array_combine() is necessary in order to use the array as select input data
$this->resources = array_combine($ldapResources, $ldapResources);
/**
* Set the resource names the user can choose from
*
* @param array $resources The resources to choose from
*
* @return self
*/
public function setResources(array $resources)
{
$this->resources = $resources;
return $this;
}
/**
@ -69,7 +64,9 @@ class LdapBackendForm extends BaseBackendForm
'required' => true,
'label' => t('LDAP Resource'),
'helptext' => t('The resource to use for authenticating with this provider'),
'multiOptions' => $this->resources
'multiOptions' => false === empty($this->resources)
? array_combine($this->resources, $this->resources)
: array()
)
),
$this->createElement(
@ -104,33 +101,37 @@ class LdapBackendForm extends BaseBackendForm
}
/**
* Validate the current configuration by connecting to a backend and requesting the user count
* Validate that the selected resource is a valid ldap authentication backend
*
* @return bool Whether validation succeeded or not
*
* @see BaseBackendForm::isValidAuthenticationBacken()
* @see Form::onSuccess()
*/
public function isValidAuthenticationBackend()
public function onSuccess(Request $request)
{
if (false === ResourceFactory::ldapAvailable()) {
// It should be possible to run icingaweb without the php ldap extension. When the user
// tries to create an ldap backend without ldap being installed we display an error.
$this->addErrorMessage(t('Using ldap is not possible, the php extension "ldap" is not installed.'));
if (false === $this->isValidAuthenticationBackend($this)) {
return false;
}
}
/**
* Validate the configuration by creating a backend and requesting the user count
*
* @param Form $form The form to fetch the configuration values from
*
* @return bool Whether validation succeeded or not
*/
public function isValidAuthenticationBackend(Form $form)
{
$element = $form->getElement('resource');
try {
$backend = ResourceFactory::createResource(
ResourceFactory::getResourceConfig($this->getValue('resource'))
$ldapUserBackend = new LdapUserBackend(
ResourceFactory::create($element->getValue()),
$form->getElement('user_class')->getValue(),
$form->getElement('user_name_attribute')->getValue()
);
$testConn = new LdapUserBackend(
$backend,
$this->getValue('user_class'),
$this->getValue('user_name_attribute')
);
$testConn->assertAuthenticationPossible();
} catch (Exception $exc) {
$this->addErrorMessage(sprintf(t('Connection validation failed: %s'), $exc->getMessage()));
$ldapUserBackend->assertAuthenticationPossible();
} catch (Exception $e) {
$element->addError(sprintf(t('Connection validation failed: %s'), $e->getMessage()));
return false;
}

View File

@ -0,0 +1,318 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Form\Config;
use InvalidArgumentException;
use Icinga\Web\Request;
use Icinga\Form\ConfigForm;
use Icinga\Web\Notification;
use Icinga\Application\Config;
use Icinga\Application\Platform;
use Icinga\Exception\ConfigurationError;
use Icinga\Form\Config\Authentication\DbBackendForm;
use Icinga\Form\Config\Authentication\LdapBackendForm;
use Icinga\Form\Config\Authentication\AutologinBackendForm;
class AuthenticationBackendConfigForm extends ConfigForm
{
/**
* The available resources split by type
*
* @var array
*/
protected $resources;
/**
* Initialize this form
*/
public function init()
{
$this->setName('form_config_authbackend');
$this->setSubmitLabel(t('Save Changes'));
}
/**
* Set the resource configuration to use
*
* @param Config $resources The resource configuration
*
* @return self
*
* @throws ConfigurationError In case no resources are available for authentication
*/
public function setResourceConfig(Config $resourceConfig)
{
$resources = array();
foreach ($resourceConfig as $name => $resource) {
$resources[strtolower($resource->type)][] = $name;
}
if (empty($resources)) {
throw new ConfigurationError(t('Could not find any resources for authentication'));
}
$this->resources = $resources;
return $this;
}
/**
* Return a form object for the given backend type
*
* @param string $type The backend type for which to return a form
*
* @return Form
*/
public function getBackendForm($type)
{
if ($type === 'db') {
$form = new DbBackendForm();
$form->setResources(isset($this->resources['db']) ? $this->resources['db'] : array());
} elseif ($type === 'ldap') {
$form = new LdapBackendForm();
$form->setResources(isset($this->resources['ldap']) ? $this->resources['ldap'] : array());
} elseif ($type === 'autologin') {
$form = new AutologinBackendForm();
} else {
throw new InvalidArgumentException(sprintf(t('Invalid backend type "%s" provided'), $type));
}
return $form;
}
/**
* Add a particular authentication backend
*
* The backend to add is identified by the array-key `name'.
*
* @param array $values The values to extend the configuration with
*
* @return self
*
* @throws InvalidArgumentException In case the backend does already exist
*/
public function add(array $values)
{
$name = isset($values['name']) ? $values['name'] : '';
if (! $name) {
throw new InvalidArgumentException(t('Authentication backend name missing'));
} elseif ($this->config->get($name) !== null) {
throw new InvalidArgumentException(t('Authentication backend already exists'));
}
unset($values['name']);
$this->config->{$name} = $values;
return $this;
}
/**
* Edit a particular authentication backend
*
* @param string $name The name of the backend to edit
* @param array $values The values to edit the configuration with
*
* @return array The edited backend configuration
*
* @throws InvalidArgumentException In case the backend does not exist
*/
public function edit($name, array $values)
{
if (! $name) {
throw new InvalidArgumentException(t('Old authentication backend name missing'));
} elseif (! ($newName = isset($values['name']) ? $values['name'] : '')) {
throw new InvalidArgumentException(t('New authentication backend name missing'));
} elseif (($backendConfig = $this->config->get($name)) === null) {
throw new InvalidArgumentException(t('Unknown authentication backend provided'));
}
if ($newName !== $name) {
// Only remove the old entry if it has changed as the order gets screwed when editing backend names
unset($this->config->{$name});
}
unset($values['name']);
$this->config->{$newName} = array_merge($backendConfig->toArray(), $values);
return $this->config->{$newName};
}
/**
* Remove the given authentication backend
*
* @param string $name The name of the backend to remove
*
* @return array The removed backend configuration
*
* @throws InvalidArgumentException In case the backend does not exist
*/
public function remove($name)
{
if (! $name) {
throw new InvalidArgumentException(t('Authentication backend name missing'));
} elseif (($backendConfig = $this->config->get($name)) === null) {
throw new InvalidArgumentException(t('Unknown authentication backend provided'));
}
unset($this->config->{$name});
return $backendConfig;
}
/**
* Move the given authentication backend up or down in order
*
* @param string $name The name of the backend to be moved
* @param int $position The new (absolute) position of the backend
*
* @return self
*
* @throws InvalidArgumentException In case the backend does not exist
*/
public function move($name, $position)
{
if (! $name) {
throw new InvalidArgumentException(t('Authentication backend name missing'));
} elseif ($this->config->get($name) === null) {
throw new InvalidArgumentException(t('Unknown authentication backend provided'));
}
$backendOrder = $this->config->keys();
array_splice($backendOrder, array_search($name, $backendOrder), 1);
array_splice($backendOrder, $position, 0, $name);
$newConfig = array();
foreach ($backendOrder as $backendName) {
$newConfig[$backendName] = $this->config->get($backendName);
}
$config = new Config($newConfig);
$this->config = $config->setConfigFile($this->config->getConfigFile());
return $this;
}
/**
* Add or edit an authentication backend and save the configuration
*
* Performs a connectivity validation using the submitted values. A checkbox is
* added to the form to skip the check if it fails and redirection is aborted.
*
* @see Form::onSuccess()
*/
public function onSuccess(Request $request)
{
if (($el = $this->getElement('force_creation')) === null || false === $el->isChecked()) {
$backendForm = $this->getBackendForm($this->getElement('type')->getValue());
if (false === $backendForm->isValidAuthenticationBackend($this)) {
$this->addForceCreationCheckbox();
return false;
}
}
$authBackend = $request->getQuery('auth_backend');
try {
if ($authBackend === null) { // create new backend
$this->add($this->getValues());
$message = t('Authentication backend "%s" has been successfully created');
} else { // edit existing backend
$this->edit($authBackend, $this->getValues());
$message = t('Authentication backend "%s" has been successfully changed');
}
} catch (InvalidArgumentException $e) {
Notification::error($e->getMessage());
return;
}
if ($this->save()) {
Notification::success(sprintf($message, $this->getElement('name')->getValue()));
} else {
return false;
}
}
/**
* Populate the form in case an authentication backend is being edited
*
* @see Form::onShow()
*
* @throws ConfigurationError In case the backend name is missing in the request or is invalid
*/
public function onShow(Request $request)
{
$authBackend = $request->getQuery('auth_backend');
if ($authBackend !== null) {
if ($authBackend === '') {
throw new ConfigurationError(t('Authentication backend name missing'));
} elseif (false === isset($this->config->{$authBackend})) {
throw new ConfigurationError(t('Unknown authentication backend provided'));
} elseif (false === isset($this->config->{$authBackend}->backend)) {
throw new ConfigurationError(sprintf(t('Backend "%s" has no `backend\' setting'), $authBackend));
}
$configValues = $this->config->{$authBackend}->toArray();
$configValues['type'] = $configValues['backend'];
$configValues['name'] = $authBackend;
$this->populate($configValues);
}
}
/**
* Add a checkbox to be displayed at the beginning of the form
* which allows the user to skip the connection validation
*/
protected function addForceCreationCheckbox()
{
$this->addElement(
'checkbox',
'force_creation',
array(
'order' => 0,
'ignore' => true,
'label' => t('Force Changes'),
'helptext' => t('Check this box to enforce changes without connectivity validation')
)
);
}
/**
* @see Form::createElements()
*/
public function createElements(array $formData)
{
$backendTypes = array();
$backendType = isset($formData['type']) ? $formData['type'] : 'db';
if (isset($this->resources['db'])) {
$backendTypes['db'] = t('Database');
}
if (isset($this->resources['ldap']) && ($backendType === 'ldap' || Platform::extensionLoaded('ldap'))) {
$backendTypes['ldap'] = 'LDAP';
}
$autologinBackends = array_filter(
$this->config->toArray(),
function ($authBackendCfg) {
return isset($authBackendCfg['backend']) && $authBackendCfg['backend'] === 'autologin';
}
);
if ($backendType === 'autologin' || empty($autologinBackends)) {
$backendTypes['autologin'] = t('Autologin');
}
$typeSelection = $this->createElement(
'select',
'type',
array(
'ignore' => true,
'required' => true,
'autosubmit' => true,
'label' => t('Backend Type'),
'helptext' => t('The type of the resource to use for this authenticaton backend'),
'multiOptions' => $backendTypes
)
);
return array_merge(
array($typeSelection),
$this->getBackendForm($backendType)->createElements($formData)
);
}
}

View File

@ -0,0 +1,68 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Form\Config;
use InvalidArgumentException;
use Icinga\Web\Request;
use Icinga\Web\Notification;
use Icinga\Form\ConfigForm;
class AuthenticationBackendReorderForm extends ConfigForm
{
/**
* Initialize this form
*/
public function init()
{
$this->setName('form_reorder_authbackend');
$this->setViewScript('form/reorder-authbackend.phtml');
}
/**
* Return the ordered backend names
*
* @return array
*/
public function getBackendOrder()
{
return $this->config->keys();
}
/**
* Update the authentication backend order and save the configuration
*
* @see Form::onSuccess()
*/
public function onSuccess(Request $request)
{
$formData = $this->getRequestData($request);
if (isset($formData['backend_newpos'])) {
$configForm = $this->getConfigForm();
list($backendName, $position) = explode('|', $formData['backend_newpos'], 2);
try {
if ($configForm->move($backendName, $position)->save()) {
Notification::success(t('Authentication order updated!'));
} else {
return false;
}
} catch (InvalidArgumentException $e) {
Notification::error($e->getMessage());
}
}
}
/**
* Return the config form for authentication backends
*
* @return ConfigForm
*/
protected function getConfigForm()
{
$form = new AuthenticationBackendConfigForm();
$form->setConfig($this->config);
return $form;
}
}

View File

@ -5,6 +5,7 @@
namespace Icinga\Form\Config;
use Exception;
use Icinga\Application\Platform;
use Zend_Config;
use Icinga\Web\Form;
use Icinga\Application\Icinga;
@ -118,14 +119,14 @@ class ResourceForm extends Form
* 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.
*/
if ($config['db'] === 'mysql' && false === ResourceFactory::mysqlAvailable()) {
if ($config['db'] === 'mysql' && false === Platform::extensionLoaded('mysql')) {
$this->addErrorMessage(
t('You need to install the php extension "mysql" and the ' .
'Zend_Pdo_Mysql classes to use MySQL database resources.')
);
return false;
}
if ($config['db'] === 'pgsql' && false === ResourceFactory::pgsqlAvailable()) {
if ($config['db'] === 'pgsql' && false === Platform::extensionLoaded('pgsql')) {
$this->addErrorMessage(
t('You need to install the php extension "pgsql" and the ' .
'Zend_Pdo_Pgsql classes to use PostgreSQL database resources.')

View File

@ -0,0 +1,67 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Form;
use Exception;
use Icinga\Web\Form;
use Icinga\Application\Config;
use Icinga\Config\PreservingIniWriter;
/**
* Form base-class providing standard functionality for configuration forms
*/
class ConfigForm extends Form
{
/**
* The configuration to work with
*
* @var Config
*/
protected $config;
/**
* Set the configuration to use when populating the form or when saving the user's input
*
* @param Config $config The configuration to use
*
* @return self
*/
public function setConfig(Config $config)
{
$this->config = $config;
return $this;
}
/**
* Persist the current configuration to disk
*
* If an error occurs the user is shown a view describing the issue and displaying the raw INI configuration.
*
* @return bool Whether the configuration could be persisted
*/
public function save()
{
$writer = new PreservingIniWriter(
array(
'config' => $this->config,
'filename' => $this->config->getConfigFile()
)
);
try {
$writer->write();
} catch (Exception $e) {
$this->addDecorator('ViewScript', array(
'viewScript' => 'showConfiguration.phtml',
'errorMessage' => $e->getMessage(),
'configString' => $writer->render(),
'filePath' => $this->config->getConfigFile()
));
return false;
}
return true;
}
}

View File

@ -2,7 +2,7 @@
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
use \Zend_View_Helper_FormElement;
use Zend_View_Helper_FormElement;
/**
* Helper to generate a "datetime" element

View File

@ -2,7 +2,7 @@
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
use \Zend_View_Helper_FormElement;
use Zend_View_Helper_FormElement;
/**
* Helper to generate a "datetime" element

View File

@ -1,57 +0,0 @@
<div class="controls">
<?= $tabs; ?>
</div>
<div class="content" data-base-target="_next">
<?= $messageBox; ?>
<p>
<a href="<?= $this->href('/config/createAuthenticationBackend', array('type' => 'ldap')); ?>">
<?= $this->icon('create.png'); ?><?= $this->translate('Create A New LDAP Authentication Backend'); ?>
</a>
<br>
<a href="<?= $this->href('/config/createAuthenticationBackend', array('type' => 'db')); ?>">
<?= $this->icon('create.png'); ?><?= $this->translate('Create A New DB Authentication Backend'); ?>
</a>
<br>
<a href="<?= $this->href('/config/createAuthenticationBackend', array('type' => 'autologin')); ?>">
<?= $this->icon('create.png'); ?><?= $this->translate('Create A New Autologin Authentication Backend'); ?>
</a>
</p>
<form id="<?= $form->getName(); ?>" name="<?= $form->getName(); ?>" enctype="<?= $form->getEncType(); ?>" method="<?= $form->getMethod(); ?>">
<?= $form->getElement($form->getTokenElementName()); ?>
<table class="action">
<thead>
<th>Backend</th>
<th style="width: 5em"><?= $this->translate('Remove'); ?></th>
<th style="width: 5em"><?= $this->translate('Order'); ?></th>
</thead>
<tbody>
<?php for ($i = 0; $i < count($backendNames); $i++): ?>
<tr>
<td class="action">
<a href="<?= $this->href('config/editAuthenticationBackend', array('auth_backend' => $backendNames[$i])); ?>">
<?= $this->icon('edit.png'); ?> <?= $this->escape($backendNames[$i]); ?>
</a>
</td>
<td>
<a href="<?= $this->href('config/removeAuthenticationBackend', array('auth_backend' => $backendNames[$i])); ?>">
<?= $this->icon('remove.png', $this->translate('Remove')); ?>
</a>
</td>
<td>
<?php if ($i > 0): ?>
<button type="submit" name="<?= $backendNames[$i]; ?>" value="<?= $i - 1; ?>">
<?= $this->icon('up.png', $this->translate('Move up in authentication order')); ?>
</button>
<?php endif; ?>
<?php if ($i + 1 < count($backendNames)): ?>
<button type="submit" name="<?= $backendNames[$i]; ?>" value="<?= $i + 1; ?>">
<?= $this->icon('down.png', $this->translate('Move down in authentication order')); ?>
</button>
<?php endif; ?>
</td>
</tr>
<?php endfor; ?>
</tbody>
</table>
</form>
</div>

View File

@ -1,15 +1,7 @@
<h4>
<i class="icinga-icon-create"></i>
Create New Authentication Backend
</h4>
<?php if (isset($this->messageBox)): ?>
<?= $this->messageBox->render() ?>
<?php endif ?>
<h4><?= $this->translate('Create New Authentication Backend'); ?></h4>
<p>
Create a new backend for authenticating your users. This backend will be added at the end of your authentication order.
<?= $this->translate(
'Create a new backend for authenticating your users. This backend will be added at the end of your authentication order.'
); ?>
</p>
<?= $this->form ?>
<?= $form; ?>

View File

@ -1,8 +1,2 @@
<h4>
<?php printf(
$this->translate('Edit Backend "%s"'),
$this->escape($this->name)
); ?>
</h4>
<?= $messageBox; ?>
<?= $this->form; ?>
<h4><?= $this->translate('Edit Backend'); ?></h4>
<?= $form; ?>

View File

@ -1,8 +1,2 @@
<h4>
<?php printf(
$this->translate('Remove Backend "%s"'),
$this->escape($name)
); ?>
</h4>
<?= $messageBox ?>
<?= $form ?>
<h4><?= $this->translate('Remove Backend'); ?></h4>
<?= $form; ?>

View File

@ -0,0 +1,11 @@
<div class="controls">
<?= $tabs; ?>
</div>
<div class="content" data-base-target="_next">
<p>
<a href="<?= $this->href('/config/createAuthenticationBackend'); ?>">
<?= $this->icon('create.png'); ?><?= $this->translate('Create A New Authentication Backend'); ?>
</a>
</p>
<?= $form; ?>
</div>

View File

@ -0,0 +1,40 @@
<form id="<?= $form->getName(); ?>" name="<?= $form->getName(); ?>" enctype="<?= $form->getEncType(); ?>" method="<?= $form->getMethod(); ?>">
<table class="action">
<thead>
<th>Backend</th>
<th style="width: 5em"><?= $this->translate('Remove'); ?></th>
<th style="width: 5em"><?= $this->translate('Order'); ?></th>
</thead>
<tbody>
<?php $backendNames = $form->getBackendOrder(); ?>
<?php for ($i = 0; $i < count($backendNames); $i++): ?>
<tr>
<td class="action">
<a href="<?= $this->href('config/editAuthenticationBackend', array('auth_backend' => $backendNames[$i])); ?>">
<?= $this->icon('edit.png'); ?> <?= $this->escape($backendNames[$i]); ?>
</a>
</td>
<td>
<a href="<?= $this->href('config/removeAuthenticationBackend', array('auth_backend' => $backendNames[$i])); ?>">
<?= $this->icon('remove.png', $this->translate('Remove')); ?>
</a>
</td>
<td>
<?php if ($i > 0): ?>
<button type="submit" name="backend_newpos" value="<?= sprintf('%s|%s', $backendNames[$i], $i - 1); ?>">
<?= $this->icon('up.png', $this->translate('Move up in authentication order')); ?>
</button>
<?php endif; ?>
<?php if ($i + 1 < count($backendNames)): ?>
<button type="submit" name="backend_newpos" value="<?= sprintf('%s|%s', $backendNames[$i], $i + 1); ?>">
<?= $this->icon('down.png', $this->translate('Move down in authentication order')); ?>
</button>
<?php endif; ?>
</td>
</tr>
<?php endfor; ?>
</tbody>
</table>
<?= $form->getElement($form->getTokenElementName()); ?>
<?= $form->getElement($form->getUidElementName()); ?>
</form>

View File

@ -0,0 +1,28 @@
<div>
<h4><?= $this->translate('Saving Configuration Failed'); ?></h4>
<br>
<p>
<?= sprintf(
$this->translate('The file %s couldn\'t be stored. (Error: "%s")'),
$this->escape($filePath),
$this->escape($errorMessage)
); ?>
<br>
<?= $this->translate('This could have one or more of the following reasons:'); ?>
</p>
<ul>
<li><?= $this->translate('You don\'t have file-system permissions to write to the file'); ?></li>
<li><?= $this->translate('Something went wrong while writing the file'); ?></li>
<li><?= $this->translate('There\'s an application error preventing you from persisting the configuration'); ?></li>
</ul>
</div>
<p>
<?= $this->translate('Details can be found in the application log. (If you don\'t have access to this log, call your administrator in this case)'); ?>
<br>
<?= $this->translate('In case you can access the file by yourself, you can open it and insert the config manually:'); ?>
</p>
<p>
<pre>
<code><?= $this->escape($configString); ?></code>
</pre>
</p>

View File

@ -83,7 +83,7 @@ BuildArch: noarch
AutoReqProv: Off
%endif
Source0: icingaweb2-%{version}.tar.gz
Source: icingaweb2-%{version}.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root

View File

@ -14,6 +14,7 @@ use Icinga\Exception\NotReadableError;
use Icinga\Logger\Logger;
use Icinga\Util\DateTimeFactory;
use Icinga\Util\Translator;
use Icinga\Exception\IcingaException;
/**
* This class bootstraps a thin Icinga application layer
@ -332,7 +333,7 @@ abstract class ApplicationBootstrap
try {
$this->moduleManager->loadEnabledModules();
} 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;
}
@ -369,7 +370,7 @@ abstract class ApplicationBootstrap
try {
$this->config = Config::app();
} 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());
}
return $this;
@ -417,7 +418,7 @@ abstract class ApplicationBootstrap
ResourceFactory::setConfig($config);
} catch (NotReadableError $e) {
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)
);
}

View File

@ -7,7 +7,6 @@ namespace Icinga\Application;
use Zend_Config;
use Zend_Config_Ini;
use Icinga\Exception\NotReadableError;
use Icinga\Exception\ProgrammingError;
/**
* Global registry of application and module configuration.
@ -22,11 +21,11 @@ class Config extends Zend_Config
public static $configDir;
/**
* The INI file this configuration has been loaded from
* The INI file this configuration has been loaded from or should be written to
*
* @var string
*/
private $configFile;
protected $configFile;
/**
* Application config instances per file
@ -42,30 +41,28 @@ class Config extends Zend_Config
*/
protected static $modules = array();
private $instance;
/**
* Load configuration from the config file $filename
* Load configuration from the given INI file
*
* @param string $file The file to parse
*
* @param string $filename The filename to parse
* @throws NotReadableError When the file does not exist or cannot be read
*/
public function __construct($filename)
public static function fromIni($file)
{
parent::__construct(array(), true);
$filepath = realpath($filename);
$config = new static(array(), true);
$filepath = realpath($file);
if ($filepath === false) {
$this->configFile = $filename;
$config->setConfigFile($file);
} elseif (is_readable($filepath)) {
$this->configFile = $filepath;
$this->merge(new Zend_Config_Ini($filepath));
$config->setConfigFile($filepath);
$config->merge(new Zend_Config_Ini($filepath));
} else {
throw new NotReadableError(
'Cannot read config file "%s". Permission denied',
$filename
);
throw new NotReadableError('Cannot read config file "%s". Permission denied', $filepath);
}
return $config;
}
/**
@ -80,7 +77,7 @@ class Config extends Zend_Config
public static function app($configname = 'config', $fromDisk = false)
{
if (!isset(self::$app[$configname]) || $fromDisk) {
self::$app[$configname] = new Config(self::resolvePath($configname . '.ini'));
self::$app[$configname] = Config::fromIni(self::resolvePath($configname . '.ini'));
}
return self::$app[$configname];
}
@ -101,7 +98,7 @@ class Config extends Zend_Config
}
$moduleConfigs = self::$modules[$modulename];
if (!isset($moduleConfigs[$configname]) || $fromDisk) {
$moduleConfigs[$configname] = new Config(
$moduleConfigs[$configname] = Config::fromIni(
self::resolvePath('modules/' . $modulename . '/' . $configname . '.ini')
);
}
@ -126,15 +123,28 @@ class Config extends Zend_Config
}
/**
* Return the application wide config file
* Return this config's file path
*
* @return string
* @return string
*/
public function getConfigFile()
{
return $this->configFile;
}
/**
* Set this config's file path
*
* @param string $filepath The path to the config file
*
* @return self
*/
public function setConfigFile($filepath)
{
$this->configFile = $filepath;
return $this;
}
/**
* Prepend configuration base dir if input is relative
*

View File

@ -19,6 +19,7 @@ use Icinga\Web\Widget;
use Icinga\Web\Widget\Dashboard\Pane;
use Icinga\Util\File;
use Icinga\Exception\ProgrammingError;
use Icinga\Exception\IcingaException;
/**
* Module handling
@ -176,6 +177,7 @@ class Module
/**
* Add a pane to dashboard
*
* @param $id
* @param $name
* @return Pane
*/
@ -199,19 +201,21 @@ class Module
/**
* Add a menu Section to the Sidebar menu
*
* @param $name
* @param string $id
* @param string $name
* @param array $properties
* @return mixed
*/
protected function menuSection($name, array $properties = array())
protected function menuSection($id, $name, array $properties = array())
{
if (array_key_exists($name, $this->menuItems)) {
$this->menuItems[$name]->setProperties($properties);
if (array_key_exists($id, $this->menuItems)) {
$this->menuItems[$id]->setProperties($properties);
} else {
$this->menuItems[$name] = new Menu($name, new Zend_Config($properties));
$this->menuItems[$id] = new Menu($id, new Zend_Config($properties));
$this->menuItems[$id]->setTitle($name);
}
return $this->menuItems[$name];
return $this->menuItems[$id];
}
/**
@ -627,8 +631,9 @@ class Module
protected function providePermission($name, $description)
{
if ($this->providesPermission($name)) {
throw new Exception(
sprintf('Cannot provide permission "%s" twice', $name)
throw new IcingaException(
'Cannot provide permission "%s" twice',
$name
);
}
$this->permissionList[$name] = (object) array(
@ -648,8 +653,9 @@ class Module
protected function provideRestriction($name, $description)
{
if ($this->providesRestriction($name)) {
throw new Exception(
sprintf('Cannot provide restriction "%s" twice', $name)
throw new IcingaException(
'Cannot provide restriction "%s" twice',
$name
);
}
$this->restrictionList[$name] = (object) array(

View File

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

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

View File

@ -11,6 +11,7 @@ use Icinga\Exception\AuthenticationException;
use Exception;
use Zend_Db_Expr;
use Zend_Db_Select;
use Icinga\Exception\IcingaException;
class DbUserBackend extends UserBackend
{
@ -60,7 +61,10 @@ class DbUserBackend extends UserBackend
return false;
}
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());

View File

@ -13,6 +13,7 @@ use Icinga\Exception\NotReadableError;
use Icinga\Application\Config as IcingaConfig;
use Icinga\User\Preferences;
use Icinga\User\Preferences\PreferencesStore;
use Icinga\Exception\IcingaException;
class Manager
{
@ -55,7 +56,11 @@ class Manager
$config = IcingaConfig::app();
} catch (NotReadableError $e) {
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());
}
@ -68,8 +73,10 @@ class Manager
$preferences = new Preferences($preferencesStore->load());
} catch (NotReadableError $e) {
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
)
);
$preferences = new Preferences();

View File

@ -9,12 +9,15 @@ use Icinga\Chart\Legend;
use Icinga\Chart\Palette;
use Icinga\Chart\Primitive\Drawable;
use Icinga\Chart\SVGRenderer;
use Icinga\Exception\IcingaException;
/**
* Base class for charts, extended by all other Chart classes.
*/
abstract class Chart implements Drawable
{
protected $align = false;
/**
* SVG renderer that handles
*
@ -87,19 +90,33 @@ abstract class Chart implements Drawable
*
* 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
*/
public function render()
{
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();
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);
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

@ -7,6 +7,7 @@ namespace Icinga\Chart\Inline;
use Icinga\Chart\PieChart as PieChartRenderer;
use Imagick;
use Exception;
use Icinga\Exception\IcingaException;
/**
* Draw an inline pie-chart directly from the available request parameters.
@ -17,11 +18,11 @@ class PieChart extends Inline
public function render($output = true)
{
$pie = new PieChartRenderer();
$pie->alignTopLeft();
$pie->disableLegend();
$pie->drawPie(array(
'data' => $this->data, 'colors' => $this->colors, 'labels' => $this->labels
));
$pie->setWidth($this->width)->setHeight($this->height);
if ($output) {
echo $pie->render();
} else {
@ -33,7 +34,7 @@ class PieChart extends Inline
{
if (! class_exists('Imagick')) {
// 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->readImageBlob($this->render(false));

View File

@ -16,7 +16,7 @@ use Icinga\Chart\Render\LayoutBox;
/**
* 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
{
@ -51,46 +51,6 @@ class PieChart extends Chart
*/
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
*
@ -111,10 +71,7 @@ class PieChart extends Chart
*/
protected function build()
{
$this->renderer = new SVGRenderer(
$this->type === self::STACKED ? $this->width : count($this->pies) * $this->width,
$this->width
);
$this->renderer = new SVGRenderer(($this->type === self::STACKED) ? 1 : count($this->pies), 1);
foreach ($this->pies as &$pie) {
$this->normalizeDataSet($pie);
}
@ -165,11 +122,16 @@ class PieChart extends Chart
*/
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');
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);
} 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->renderPies($innerBox, $labelBox);
@ -274,9 +236,6 @@ class PieChart extends Chart
$lastRadius = 0;
foreach ($pie['data'] as $idx => $dataset) {
$color = $this->getColorForPieSlice($pie, $idx);
if ($dataset === 100) {
$dataset = 99.9;
}
if ($dataset == 0) {
$labelPos++;
continue;
@ -340,3 +299,4 @@ class PieChart extends Chart
$clipBox->addElement($rect);
}
}

View File

@ -32,7 +32,7 @@ class PieSlice extends Animatable implements Drawable
*
* @var float
*/
private $endRadian= 0;
private $endRadian = 0;
/**
* 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)
{
// 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
$xStart = $x + ($r * sin($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
$pathString .= 'L ' . Format::formatSVGNumber($xStart) . ' ' . Format::formatSVGNumber($yStart);
if ($this->endRadian - $this->startRadian == 2*M_PI) {
// 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
$pathString .= ' A ' . Format::formatSVGNumber($r) . ' ' . Format::formatSVGNumber($r);
// 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';
// 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);
return $pathString;
}
@ -152,7 +159,7 @@ class PieSlice extends Animatable implements Drawable
// Draw the handle
$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();
$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
$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));
$group->appendChild($path->toSvg($ctx));

View File

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

View File

@ -132,7 +132,7 @@ class RenderContext
* @param int $x The relative x 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
*/
public function toAbsolute($x, $y)

View File

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

View File

@ -19,6 +19,22 @@ use Icinga\Chart\Primitive\Canvas;
*/
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
*
@ -54,6 +70,35 @@ class SVGRenderer
*/
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
*/
@ -82,8 +127,8 @@ class SVGRenderer
$svg = $this->document->createElement('svg');
$svg->setAttribute('xmlns', 'http://www.w3.org/2000/svg');
$svg->setAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink');
$svg->setAttribute('width', $this->width . '%');
$svg->setAttribute('height', $this->height . '%');
$svg->setAttribute('width', '100%');
$svg->setAttribute('height', '100%');
$svg->setAttribute(
'viewBox',
sprintf(
@ -92,6 +137,17 @@ class SVGRenderer
$ctx->getNrOfUnitsY()
)
);
if ($this->preserveAspectRatio) {
$svg->setAttribute(
'preserveAspectRatio',
sprintf (
'%s%s %s',
$this->xAspectRatio,
$this->yAspectRatio,
$this->xFillMode
)
);
}
return $svg;
}
@ -141,4 +197,40 @@ class SVGRenderer
{
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;
use Icinga\Cli\Screen;
use Icinga\Exception\IcingaException;
// @see http://en.wikipedia.org/wiki/ANSI_escape_code
@ -74,7 +75,10 @@ class AnsiScreen extends Screen
protected function fgColor($color)
{
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];
}
@ -82,7 +86,10 @@ class AnsiScreen extends Screen
protected function bgColor($color)
{
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];
}

View File

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

View File

@ -38,6 +38,45 @@ class PreservingIniWriter extends Zend_Config_Writer_FileAbstract
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
*
@ -50,6 +89,17 @@ class PreservingIniWriter extends Zend_Config_Writer_FileAbstract
} else {
$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;
$editor = new IniEditor(file_get_contents($this->_filename), $this->options);
$this->diffConfigs($oldconfig, $newconfig, $editor);

View File

@ -11,6 +11,7 @@ use Icinga\Data\Filter\FilterExpression;
use Icinga\Data\Filter\FilterOr;
use Icinga\Data\Filter\FilterAnd;
use Icinga\Data\Filter\FilterNot;
use Icinga\Exception\IcingaException;
use Zend_Db_Select;
/**
@ -124,7 +125,10 @@ class DbQuery extends SimpleQuery
$op = ' AND ';
$str .= ' NOT ';
} else {
throw new \Exception('Cannot render filter: ' . $filter);
throw new IcingaException(
'Cannot render filter: %s',
$filter
);
}
$parts = array();
if (! $filter->isEmpty()) {
@ -177,7 +181,7 @@ class DbQuery extends SimpleQuery
if (! $value) {
/*
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',
$value
));

View File

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

View File

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

View File

@ -14,13 +14,23 @@ use Icinga\Protocol\Statusdat\Reader as StatusdatReader;
use Icinga\Protocol\Ldap\Connection as LdapConnection;
use Icinga\Protocol\File\Reader as FileReader;
/**
* Create resources from names or resource configuration
*/
class ResourceFactory implements ConfigAwareFactory
{
/**
* Resource configuration
*
* @var Zend_Config
*/
private static $resources;
/**
* Set resource configurations
*
* @param Zend_Config $config
*/
public static function setConfig($config)
{
self::$resources = $config;
@ -29,10 +39,11 @@ class ResourceFactory implements ConfigAwareFactory
/**
* 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
* @throws \Icinga\Exception\ConfigurationError
* @return Zend_Config The configuration of the resource
*
* @throws ConfigurationError
*/
public static function getResourceConfig($resourceName)
{
@ -72,7 +83,7 @@ class ResourceFactory implements ConfigAwareFactory
/**
* Check if the existing resources are set. If not, throw an error.
*
* @throws \Icinga\Exception\ProgrammingError
* @throws ProgrammingError
*/
private static function assertResourcesExist()
{
@ -93,7 +104,7 @@ class ResourceFactory implements ConfigAwareFactory
*
* @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'.
* @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)
{
@ -122,18 +133,14 @@ class ResourceFactory implements ConfigAwareFactory
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');
}
public static function pgsqlAvailable()
{
return extension_loaded('pgsql');
}
public static function mysqlAvailable()
{
return extension_loaded('mysql');
return self::createResource(self::getResourceConfig($resourceName));
}
}

View File

@ -9,6 +9,7 @@ use Icinga\Data\Filter\Filter;
use Icinga\Web\Paginator\Adapter\QueryAdapter;
use Zend_Paginator;
use Exception;
use Icinga\Exception\IcingaException;
class SimpleQuery implements QueryInterface, Queryable
{
@ -158,7 +159,7 @@ class SimpleQuery implements QueryInterface, Queryable
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

@ -5,6 +5,7 @@
namespace Icinga\Logger\Writer;
use Exception;
use Icinga\Exception\IcingaException;
use Zend_Config;
use Icinga\Util\File;
use Icinga\Logger\Logger;
@ -68,7 +69,7 @@ class FileWriter extends LogWriter
*
* @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)
{
@ -82,7 +83,10 @@ class FileWriter extends LogWriter
case Logger::$DEBUG:
return '- DEBUG -';
default:
throw new Exception('Unknown severity "' . $severity . '"');
throw new IcingaException(
'Unknown severity "%s"',
$severity
);
}
}

View File

@ -9,6 +9,7 @@ use Zend_Config;
use Icinga\Logger\Logger;
use Icinga\Logger\LogWriter;
use Icinga\Exception\ConfigurationError;
use Icinga\Exception\IcingaException;
/**
* Class to write messages to syslog
@ -72,7 +73,10 @@ class SyslogWriter extends LogWriter
);
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();

View File

@ -8,7 +8,7 @@ use Icinga\Protocol\Ldap\Exception as LdapException;
use Icinga\Application\Platform;
use Icinga\Application\Config;
use Icinga\Logger\Logger;
use \Zend_Config;
use Zend_Config;
/**
* Backend class managing all the LDAP stuff for you.

View File

@ -4,6 +4,8 @@
namespace Icinga\Protocol\Ldap;
use Icinga\Exception\IcingaException;
/**
* Search class
*
@ -82,12 +84,10 @@ class Query
public function limit($count = null, $offset = null)
{
if (! preg_match('~^\d+~', $count . $offset)) {
throw new Exception(
sprintf(
'Got invalid limit: %s, %s',
$count,
$offset
)
throw new IcingaException(
'Got invalid limit: %s, %s',
$count,
$offset
);
}
$this->limit_count = (int) $count;
@ -316,7 +316,7 @@ class Query
{
$parts = array();
if (! isset($this->filters['objectClass']) || $this->filters['objectClass'] === null) {
// throw new Exception('Object class is mandatory');
// throw new IcingaException('Object class is mandatory');
}
foreach ($this->filters as $key => $value) {
$parts[] = sprintf(

View File

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

View File

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

View File

@ -5,6 +5,7 @@
namespace Icinga\Protocol\Livestatus;
use Icinga\Protocol\AbstractQuery;
use Icinga\Exception\IcingaException;
class Query extends AbstractQuery
{
@ -86,12 +87,10 @@ class Query extends AbstractQuery
public function limit($count = null, $offset = null)
{
if (! preg_match('~^\d+~', $count . $offset)) {
throw new Exception(
sprintf(
'Got invalid limit: %s, %s',
$count,
$offset
)
throw new IcingaException(
'Got invalid limit: %s, %s',
$count,
$offset
);
}
$this->limit_count = (int) $count;
@ -122,11 +121,9 @@ class Query extends AbstractQuery
public function from($table, $columns = null)
{
if (! $this->connection->hasTable($table)) {
throw new Exception(
sprintf(
'This livestatus connection does not provide "%s"',
$table
)
throw new IcingaException(
'This livestatus connection does not provide "%s"',
$table
);
}
$this->table = $table;
@ -169,7 +166,7 @@ class Query extends AbstractQuery
public function __toString()
{
if ($this->table === null) {
throw new Exception('Table is required');
throw new IcingaException('Table is required');
}
$default_headers = array(
'OutputFormat: json',

View File

@ -4,6 +4,8 @@
namespace Icinga\Protocol\Nrpe;
use Icinga\Exception\IcingaException;
class Connection
{
protected $host;
@ -47,11 +49,10 @@ class Connection
// TODO: Check result checksum!
$result = fread($conn, 8192);
if ($result === false) {
throw new \Exception('CHECK_NRPE: Error receiving data from daemon.');
throw new IcingaException('CHECK_NRPE: Error receiving data from daemon.');
} elseif (strlen($result) === 0) {
throw new \Exception(
'CHECK_NRPE: Received 0 bytes from daemon.'
. ' Check the remote server logs for error messages'
throw new IcingaException(
'CHECK_NRPE: Received 0 bytes from daemon. Check the remote server logs for error messages'
);
}
// TODO: CHECK_NRPE: Receive underflow - only %d bytes received (%d expected)
@ -80,7 +81,10 @@ class Connection
$ctx
);
if (! $this->connection) {
throw new \Exception(sprintf('NRPE Connection failed: ' . $errstr));
throw new IcingaException(
'NRPE Connection failed: %s',
$errstr
);
}
}

View File

@ -9,6 +9,7 @@ use Icinga\Exception\ProgrammingError;
use Icinga\Data\SimpleQuery;
use Icinga\Protocol\Statusdat\View\MonitoringObjectList;
use Icinga\Protocol\Statusdat\Query\IQueryPart;
use Icinga\Exception\IcingaException;
/**
* Base implementation for Statusdat queries.
@ -163,7 +164,7 @@ class Query extends SimpleQuery
* @param array $columns An array of attributes to use (required for fetchPairs())
*
* @return $this Fluent interface
* @throws \Exception If the target is unknonw
* @throws IcingaException If the target is unknonw
*/
public function from($table, array $attributes = null)
{
@ -173,7 +174,10 @@ class Query extends SimpleQuery
if (isset(self::$VALID_TARGETS[$table])) {
$this->source = $table;
} else {
throw new \Exception('Unknown from target for status.dat :' . $table);
throw new IcingaException(
'Unknown from target for status.dat :%s',
$table
);
}
return $this;
}
@ -397,16 +401,15 @@ class Query extends SimpleQuery
/**
* Fetch the result as an associative array using the first column as the key and the second as the value
*
* @return array An associative array with the result
* @throws \Exception If no attributes are defined
* @return array An associative array with the result
* @throws IcingaException If no attributes are defined
*/
public function fetchPairs()
{
$result = array();
if (count($this->getColumns()) < 2) {
throw new Exception(
'Status.dat "fetchPairs()" query expects at least' .
' columns to be set in the query expression'
throw new IcingaException(
'Status.dat "fetchPairs()" query expects at least columns to be set in the query expression'
);
}
$attributes = $this->getColumns();

View File

@ -4,6 +4,8 @@
namespace Icinga\Protocol\Statusdat\Query;
use Icinga\Exception\IcingaException;
class Expression implements IQueryPart
{
/**
@ -70,7 +72,7 @@ class Expression implements IQueryPart
/**
* @param $token
* @throws \Exception
* @throws IcingaException
*/
private function getOperatorType($token)
{
@ -106,7 +108,11 @@ class Expression implements IQueryPart
$this->CB = "isNotIn";
break;
default:
throw new \Exception("Unknown operator $token in expression $this->expression !");
throw new IcingaException(
'Unknown operator %s in expression %s !',
$token,
$this->expression
);
}
}

View File

@ -4,6 +4,8 @@
namespace Icinga\Protocol\Statusdat\Query;
use Icinga\Exception\IcingaException;
/**
* Class Group
* @package Icinga\Protocol\Statusdat\Query
@ -130,7 +132,7 @@ class Group implements IQueryPart
}
/**
* @throws \Exception
* @throws IcingaException
*/
private function tokenize()
{
@ -154,7 +156,10 @@ class Group implements IQueryPart
}
if ($token === self::GROUP_END) {
if ($subgroupCount < 1) {
throw new \Exception("Invalid Query: unexpected ')' at pos " . $this->parsePos);
throw new IcingaException(
'Invalid Query: unexpected \')\' at pos %s',
$this->parsePos
);
}
$subgroupCount--;
/*
@ -192,7 +197,7 @@ class Group implements IQueryPart
$this->subExpressionLength = $this->parsePos - $this->subExpressionStart;
}
if ($subgroupCount > 0) {
throw new \Exception("Unexpected end of query, are you missing a parenthesis?");
throw new IcingaException('Unexpected end of query, are you missing a parenthesis?');
}
$this->startNewSubExpression();

View File

@ -4,10 +4,11 @@
namespace Icinga\Protocol\Statusdat\View;
use \Iterator;
use \Countable;
use \ArrayAccess;
use \Exception;
use Iterator;
use Countable;
use ArrayAccess;
use Exception;
use Icinga\Exception\IcingaException;
/**
* Wrapper around an array of monitoring objects that can be enhanced with an optional
@ -115,7 +116,7 @@ class MonitoringObjectList implements Iterator, Countable, ArrayAccess
public function __set($name, $value)
{
throw new Exception("Setting is currently not available for objects");
throw new IcingaException('Setting is currently not available for objects');
}
public function offsetExists($offset)

View File

@ -4,7 +4,7 @@
namespace Icinga\User\Preferences;
use \Zend_Config;
use Zend_Config;
use Icinga\User;
use Icinga\User\Preferences;
use Icinga\Data\ResourceFactory;

View File

@ -5,6 +5,7 @@
namespace Icinga\Util;
use Exception;
use Icinga\Exception\IcingaException;
/**
* Helper class to ease internationalization when using gettext
@ -53,12 +54,16 @@ class Translator
* @param string $name The name of the domain to register
* @param string $directory The directory where message catalogs can be found
*
* @throws Exception In case the domain was not successfully registered
* @throws IcingaException In case the domain was not successfully registered
*/
public static function registerDomain($name, $directory)
{
if (bindtextdomain($name, $directory) === false) {
throw new Exception("Cannot register domain '$name' with path '$directory'");
throw new IcingaException(
'Cannot register domain \'%s\' with path \'%s\'',
$name,
$directory
);
}
bind_textdomain_codeset($name, 'UTF-8');
self::$knownDomains[$name] = $directory;
@ -69,14 +74,17 @@ class Translator
*
* @param string $localeName The name of the locale to use
*
* @throws Exception In case the locale's name is invalid
* @throws IcingaException In case the locale's name is invalid
*/
public static function setupLocale($localeName)
{
if (setlocale(LC_ALL, $localeName . '.UTF-8') === false && setlocale(LC_ALL, $localeName) === false) {
setlocale(LC_ALL, 'C'); // C == "use whatever is hardcoded"
if ($localeName !== self::DEFAULT_LOCALE) {
throw new Exception("Cannot set locale '$localeName' for category 'LC_ALL'");
throw new IcingaException(
'Cannot set locale \'%s\' for category \'LC_ALL\'',
$localeName
);
}
} else {
$locale = setlocale(LC_ALL, 0);

View File

@ -8,6 +8,7 @@ use Exception;
use Icinga\Authentication\Manager as AuthManager;
use Icinga\Application\Benchmark;
use Icinga\Application\Config;
use Icinga\Exception\IcingaException;
use Icinga\Util\Translator;
use Icinga\Web\Widget\Tabs;
use Icinga\Web\Window;
@ -177,7 +178,10 @@ class ActionController extends Zend_Controller_Action
{
if (! $this->Auth()->hasPermission($name)) {
// TODO: Shall this be an Auth Exception? Or a 404?
throw new Exception(sprintf('Auth error, no permission for "%s"', $name));
throw new IcingaException(
'Auth error, no permission for "%s"',
$name
);
}
}
@ -381,7 +385,7 @@ class ActionController extends Zend_Controller_Action
if ($this->view->title) {
if (preg_match('~[\r\n]~', $this->view->title)) {
// TODO: Innocent exception and error log for hack attempts
throw new Exception('No way, guy');
throw new IcingaException('No way, guy');
}
$resp->setHeader(
'X-Icinga-Title',

View File

@ -4,10 +4,12 @@
namespace Icinga\Web;
use LogicException;
use Zend_Form;
use Zend_View_Interface;
use Icinga\Application\Icinga;
use Icinga\Web\Form\Decorator\HelpText;
use Icinga\Web\Form\Decorator\NoScriptApply;
use Icinga\Web\Form\Decorator\ElementWrapper;
use Icinga\Web\Form\Element\CsrfCounterMeasure;
@ -23,6 +25,13 @@ class Form extends Zend_Form
*/
protected $created = false;
/**
* The callback to call instead of Form::onSuccess()
*
* @var Closure
*/
protected $onSuccess;
/**
* Label to use for the standard submit button
*
@ -60,6 +69,40 @@ class Form extends Zend_Form
*/
protected $tokenElementName = 'CSRFToken';
/**
* Name of the form identification element
*
* @var string
*/
protected $uidElementName = 'formUID';
/**
* Create a new form
*
* Accepts an additional option `onSuccess' which is a
* callback that is called instead of this form's method.
*
* @see Zend_Form::__construct()
*
* @throws LogicException In case `onSuccess' is not callable
*/
public function __construct($options = null)
{
if (is_array($options) && isset($options['onSuccess'])) {
$this->onSuccess = $options['onSuccess'];
unset($options['onSuccess']);
} elseif (isset($options->onSuccess)) {
$this->onSuccess = $options->onSuccess;
unset($options->onSuccess);
}
if ($this->onSuccess !== null && false === is_callable($this->onSuccess)) {
throw new LogicException('The option `onSuccess\' is not callable');
}
parent::__construct($options);
}
/**
* Set the label to use for the standard submit button
*
@ -185,6 +228,29 @@ class Form extends Zend_Form
return $this->tokenElementName;
}
/**
* Set the name to use for the form identification element
*
* @param string $name The name to set
*
* @return self
*/
public function setUidElementName($name)
{
$this->uidElementName = $name;
return $this;
}
/**
* Return the name of the form identification element
*
* @return string
*/
public function getUidElementName()
{
return $this->uidElementName;
}
/**
* Create this form
*
@ -233,7 +299,7 @@ class Form extends Zend_Form
*
* @param Request $request The valid request used to process this form
*
* @return bool Whether any redirection should take place
* @return null|bool Return FALSE in case no redirect should take place
*/
public function onSuccess(Request $request)
{
@ -300,6 +366,14 @@ class Form extends Zend_Form
$el->removeDecorator('HtmlTag');
$el->removeDecorator('Label');
$el->removeDecorator('DtDdWrapper');
if ($el->getAttrib('autosubmit')) {
// Need to add this decorator first or it interferes with the other's two HTML otherwise
$el->addDecorator(new NoScriptApply()); // Non-JS environments
$el->setAttrib('class', 'autosubmit'); // JS environments
unset($el->autosubmit);
}
$el->addDecorator(new ElementWrapper());
$el->addDecorator(new HelpText());
}
@ -317,7 +391,7 @@ class Form extends Zend_Form
{
$this->addElement(
'hidden',
'form_uid',
$this->uidElementName,
array(
'ignore' => true,
'value' => $this->getName()
@ -373,8 +447,10 @@ class Form extends Zend_Form
$formData = $this->getRequestData($request);
if ($this->wasSent($formData)) {
$this->populate($formData); // Necessary to get isSubmitted() to work
if ($this->isSubmitted() || ! $this->getSubmitLabel()) {
if ($this->isValid($formData) && $this->onSuccess($request)) {
if (! $this->getSubmitLabel() || $this->isSubmitted()) {
if ($this->isValid($formData)
&& (($this->onSuccess !== null && false !== call_user_func($this->onSuccess, $request))
|| ($this->onSuccess === null && false !== $this->onSuccess($request)))) {
$this->getResponse()->redirectAndExit($this->getRedirectUrl());
}
} else {
@ -416,7 +492,7 @@ class Form extends Zend_Form
*/
public function wasSent(array $formData)
{
return isset($formData['form_uid']) && $formData['form_uid'] === $this->getName();
return isset($formData[$this->uidElementName]) && $formData[$this->uidElementName] === $this->getName();
}
/**

View File

@ -4,7 +4,7 @@
namespace Icinga\Web\Form\Decorator;
use \Zend_Form_Decorator_Abstract;
use Zend_Form_Decorator_Abstract;
/**
* Decorator to hide elements using a &gt;noscript&lt; tag instead of

View File

@ -0,0 +1,35 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Web\Form\Decorator;
use Zend_Form_Decorator_Abstract;
use Icinga\Application\Icinga;
/**
* Decorator to add a submit button encapsulated in noscript-tags
*
* This enables users in non-JS environments to update the contents
* of a form without the use of the main submit button.
*/
class NoScriptApply extends Zend_Form_Decorator_Abstract
{
/**
* Add a submit button encapsulated in noscript-tags to the element
*
* @param string $content The html rendered so far
*
* @return string The updated html
*/
public function render($content = '')
{
if ($content) {
$content .= '<noscript><button name="noscript_apply" style="margin-left: 0.5em;" type="submit" value="1">'
. Icinga::app()->getViewRenderer()->view->icon('refresh.png') . '&nbsp;' . t('Apply')
. '</button></noscript>';
}
return $content;
}
}

View File

@ -5,9 +5,9 @@
namespace Icinga\Web\Form\Element;
use Icinga\Web\Form\Validator\DateTimeValidator;
use \Zend_Form_Element_Text;
use \Zend_Form_Element;
use \Icinga\Util\DateTimeFactory;
use Zend_Form_Element_Text;
use Zend_Form_Element;
use Icinga\Util\DateTimeFactory;
/**
* Datetime form element which returns the input as Unix timestamp after the input has been proven valid. Utilizes

View File

@ -4,8 +4,8 @@
namespace Icinga\Web\Form\Element;
use \Icinga\Web\Form\Validator\TriStateValidator;
use \Zend_Form_Element_Xhtml;
use Icinga\Web\Form\Validator\TriStateValidator;
use Zend_Form_Element_Xhtml;
/**
* A checkbox that can display three different states:

View File

@ -4,7 +4,7 @@
namespace Icinga\Web\Form\Validator;
use \Zend_Validate_Abstract;
use Zend_Validate_Abstract;
/**
* Validator that checks if a textfield contains a correct date format

View File

@ -4,9 +4,9 @@
namespace Icinga\Web\Form\Validator;
use \Icinga\Util\DateTimeFactory;
use \Zend_Validate_Abstract;
use \Icinga\Exception\ProgrammingError;
use Icinga\Util\DateTimeFactory;
use Zend_Validate_Abstract;
use Icinga\Exception\ProgrammingError;
/**
* Validator that checks if a textfield contains a correct date format

View File

@ -4,7 +4,7 @@
namespace Icinga\Web\Form\Validator;
use \Zend_Validate_Abstract;
use Zend_Validate_Abstract;
/**
* Validator that checks if a textfield contains a correct time format

View File

@ -4,7 +4,7 @@
namespace Icinga\Web\Form\Validator;
use \Zend_Validate_Abstract;
use Zend_Validate_Abstract;
class TriStateValidator extends Zend_Validate_Abstract
{

View File

@ -4,8 +4,8 @@
namespace Icinga\Web\Form\Validator;
use \Zend_Validate_Abstract;
use \Icinga\Application\Config as IcingaConfig;
use Zend_Validate_Abstract;
use Icinga\Application\Config as IcingaConfig;
/**
* Validator that interprets the value as a path and checks if it's writable

View File

@ -41,6 +41,15 @@ class Hook
*/
public static $BASE_NS = 'Icinga\\Web\\Hook\\';
/**
* Append this string to base class
*
* All base classes renamed to *Hook
*
* @var string
*/
public static $classSuffix = 'Hook';
/**
* Reset object state
*/
@ -114,7 +123,7 @@ class Hook
*/
private static function assertValidHook($instance, $name)
{
$base_class = self::$BASE_NS . ucfirst($name);
$base_class = self::$BASE_NS . ucfirst($name) . self::$classSuffix;
if (!$instance instanceof $base_class) {
throw new ProgrammingError(
'%s is not an instance of %s',

View File

@ -1,145 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Web\Hook\Configuration;
use Icinga\Exception\ProgrammingError;
/**
* Class ConfigurationTab
*
* Hook to represent configuration tabs
*
* @package Icinga\Web\Hook\Configuration
*/
class ConfigurationTab implements ConfigurationTabInterface
{
/**
* Module name
* @var string
*/
private $moduleName;
/**
* Url segment to invoke controller
* @var string
*/
private $url;
/**
* Title of the tab
* @var string
*/
private $title;
/**
* Create a new instance
*
* @param string|null $name
* @param string|null $url
* @param string|null $title
*/
public function __construct($name = null, $url = null, $title = null)
{
if ($name !== null) {
$this->setModuleName($name);
if ($title === null) {
$this->setTitle($name);
}
}
if ($url !== null) {
$this->setUrl($url);
}
if ($title !== null) {
$this->setTitle($title);
}
}
/**
* Setter for title
* @param string $title
*/
public function setTitle($title)
{
$this->title = $title;
}
/**
* Getter for title
* @return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Setter for url
* @param string $url
*/
public function setUrl($url)
{
$this->url = $url;
}
/**
* Getter for url
* @return string
*/
public function getUrl()
{
return $this->url;
}
/**
* Setter for module name
* @param string $moduleName
*/
public function setModuleName($moduleName)
{
$this->moduleName = $moduleName;
}
private function assertConfiguration()
{
if (!$this->moduleName) {
throw new ProgrammingError('moduleName is missing');
}
if (!$this->getUrl()) {
throw new ProgrammingError('url is missing');
}
if (!$this->getTitle()) {
throw new ProgrammingError('title is missing');
}
}
/**
* Returns a tab configuration to build configuration links
* @return array
*/
public function getTab()
{
$this->assertConfiguration();
return array(
'title' => $this->getTitle(),
'url' => $this->getUrl()
);
}
/**
* Return the tab key
* @return string
*/
public function getModuleName()
{
$this->assertConfiguration();
return $this->moduleName;
}
}

View File

@ -1,107 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Web\Hook\Configuration;
use Icinga\Exception\ProgrammingError;
use Icinga\Web\Hook;
use Icinga\Web\Widget\Tabs;
/**
* Class ConfigurationTabBuilder
*
* Glue config tabs together
*
* @package Icinga\Web\Hook\Configuration
*/
class ConfigurationTabBuilder
{
/**
* Namespace for configuration tabs
*/
const HOOK_NAMESPACE = 'Configuration/Tabs';
/**
* Tabs widget
* @var Tabs
*/
private $tabs;
/**
* Create a new instance
* @param Tabs $tabs
*/
public function __construct(Tabs $tabs)
{
$this->setTabs($tabs);
$this->initializeSystemConfigurationTabs();
}
/**
* Setter for tabs
* @param \Icinga\Web\Widget\Tabs $tabs
*/
public function setTabs($tabs)
{
$this->tabs = $tabs;
}
/**
* Getter for tabs
* @return \Icinga\Web\Widget\Tabs
*/
public function getTabs()
{
return $this->tabs;
}
/**
* Build the tabs
*
*/
public function build()
{
/** @var ConfigurationTab $configTab */
$configTab = null;
foreach (Hook::all(self::HOOK_NAMESPACE) as $configTab) {
if (!$configTab instanceof ConfigurationTabInterface) {
throw new ProgrammingError('tab not instance of ConfigTabInterface');
}
$this->getTabs()->add($configTab->getModuleName(), $configTab->getTab());
}
}
/**
* Initialize system configuration tabs
*/
public function initializeSystemConfigurationTabs()
{
$configurationTab = new ConfigurationTab(
'configuration',
'configuration/index',
'Configuration'
);
// Display something about us
Hook::registerObject(
ConfigurationTabBuilder::HOOK_NAMESPACE,
$configurationTab->getModuleName(),
$configurationTab
);
$modulesOverviewTab = new ConfigurationTab(
'modules',
'modules/overview',
'Modules'
);
Hook::registerObject(
ConfigurationTabBuilder::HOOK_NAMESPACE,
$modulesOverviewTab->getModuleName(),
$modulesOverviewTab
);
}
}

View File

@ -1,27 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Web\Hook\Configuration;
/**
* Interface ConfigurationTabInterface
*
* Used to register configuration tab settings
*
* @package Icinga\Web\Hook\Configuration
*/
interface ConfigurationTabInterface
{
/**
* Returns a tab configuration to build configuration links
* @return array
*/
public function getTab();
/**
* Return the tab key
* @return string
*/
public function getModuleName();
}

View File

@ -4,6 +4,8 @@
namespace Icinga\Web\Hook;
use Icinga\Exception\ProgrammingError;
/**
* Icinga Web Grapher Hook base class
*
@ -14,7 +16,7 @@ namespace Icinga\Web\Hook;
* @author Icinga-Web Team <info@icinga.org>
* @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
*/
class Grapher
abstract class GrapherHook
{
/**
* Whether this grapher provides preview images
@ -56,9 +58,13 @@ class Grapher
/**
* Whether a graph for the given host[, service [, plot]] exists
*
* @param string $host
* @param string $service
* @param string $plot
*
* @return bool
*/
public function hasGraph($host, $service = null, $plot = null)
public function has($host, $service = null, $plot = null)
{
return false;
}
@ -66,13 +72,47 @@ class Grapher
/**
* Get a preview image for the given host[, service [, plot]] exists
*
* WARNING: We are not sure yet whether this will remain as is
* @param string $host
* @param string $service
* @param string $plot
*
* @return string
* @return string
*
* @throws ProgrammingError
*/
public function getPreviewImage($host, $service = null, $plot = null)
public function getPreviewHtml($host, $service = null, $plot = null)
{
throw new Exception('This backend has no preview images');
throw new ProgrammingError('This backend has no preview images');
}
/**
* Whether a tiny graph for the given host[, service [, plot]] exists
*
* @param string $host
* @param string $service
* @param string $plot
*
* @return bool
*/
public function hasTinyPreview($host, $service = null, $plot = null)
{
return false;
}
/**
* Get a tiny preview image for the given host[, service [, plot]] exists
*
* @param string $host
* @param string $service
* @param string $plot
*
* @return string
*
* @throws ProgrammingError
*/
public function getTinyPreviewHtml($host, $service = null, $plot = null)
{
throw new ProgrammingError('This backend has no tiny preview images');
}
/**
@ -80,10 +120,11 @@ class Grapher
*
* WARNING: We are not sure yet whether this will remain as is
*
* @return string
* @param string $host
* @param string $service
* @param string $plot
*
* @return string
*/
public function getGraphUrl($host, $service = null, $plot = null)
{
throw new Exception('This backend has no images');
}
abstract function getGraphUrl($host, $service = null, $plot = null);
}

View File

@ -14,7 +14,7 @@ namespace Icinga\Web\Hook;
* @author Icinga-Web Team <info@icinga.org>
* @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
*/
abstract class Ticket
abstract class TicketHook
{
/**
* Constructor must live without arguments right now

View File

@ -4,21 +4,20 @@
namespace Icinga\Web\Hook;
use \Icinga\Web\Request;
use \Zend_View;
use Icinga\Web\Request;
use Zend_View;
/**
* Hook to extend topbar items
*/
interface TopBar
abstract class TopBarHook extends WebBaseHook
{
/**
* Function to generate top bar content
*
* @param Request $request
* @param Zend_View $view
*
* @return string
*/
public function getHtml($request, $view);
abstract public function getHtml($request);
}

View File

@ -0,0 +1,51 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Web\Hook;
use Zend_Controller_Action_HelperBroker;
use Zend_View;
/**
* Base class for web hooks
*
* The class provides access to the view
*/
class WebBaseHook
{
/**
* View instance
*
* @var Zend_View
*/
private $view;
/**
* Set the view instance
*
* @param Zend_View $view
*/
public function setView(Zend_View $view)
{
$this->view = $view;
}
/**
* Get the view instance
*
* @return Zend_View
*/
public function getView()
{
if ($this->view === null) {
$viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
if ($viewRenderer->view === null) {
$viewRenderer->initView();
}
$this->view = $viewRenderer->view;
}
return $this->view;
}
}

View File

@ -5,6 +5,7 @@
namespace Icinga\Web;
use Icinga\Exception\ConfigurationError;
use Icinga\Logger\Logger;
use Zend_Config;
use RecursiveIterator;
use Icinga\Application\Config;
@ -172,34 +173,34 @@ class Menu implements RecursiveIterator
*/
protected function addMainMenuItems()
{
$this->add(t('Dashboard'), array(
$this->add('dashboard', t('Dashboard'), array(
'url' => 'dashboard',
'icon' => 'img/icons/dashboard.png',
'priority' => 10
));
$section = $this->add(t('System'), array(
$section = $this->add('system', t('System'), array(
'icon' => 'img/icons/configuration.png',
'priority' => 200
));
$section->add(t('Preferences'), array(
$section->add('preferences', t('Preferences'), array(
'url' => 'preference',
'priority' => 200
));
$section->add(t('Configuration'), array(
$section->add('configuration', t('Configuration'), array(
'url' => 'config',
'priority' => 300
));
$section->add(t('Modules'), array(
$section->add('modules', t('Modules'), array(
'url' => 'config/modules',
'priority' => 400
));
$section->add(t('ApplicationLog'), array(
$section->add('applicationlog', t('ApplicationLog'), array(
'url' => 'list/applicationlog',
'priority' => 500
));
$this->add(t('Logout'), array(
$this->add('logout', t('Logout'), array(
'url' => 'authentication/logout',
'icon' => 'img/icons/logout.png',
'priority' => 300
@ -427,9 +428,10 @@ class Menu implements RecursiveIterator
* @param array $config
* @return Menu
*/
public function add($name, $config = array())
public function add($id, $name, $config = array())
{
return $this->addSubMenu($name, new Zend_Config($config));
$config['title'] = $name;
return $this->addSubMenu($id, new Zend_Config($config));
}
/**

View File

@ -4,9 +4,10 @@
namespace Icinga\Web\Session;
use \Exception;
use \ArrayIterator;
use \IteratorAggregate;
use Exception;
use ArrayIterator;
use Icinga\Exception\IcingaException;
use IteratorAggregate;
/**
* Container for session values
@ -76,7 +77,10 @@ class SessionNamespace implements IteratorAggregate
public function __get($key)
{
if (!array_key_exists($key, $this->values)) {
throw new Exception('Cannot access non-existent session value "' . $key . '"');
throw new IcingaException(
'Cannot access non-existent session value "%s"',
$key
);
}
return $this->get($key);
@ -178,7 +182,7 @@ class SessionNamespace implements IteratorAggregate
public function write()
{
if (!$this->session) {
throw new Exception('Cannot save, session not set');
throw new IcingaException('Cannot save, session not set');
}
$this->session->write();

View File

@ -50,7 +50,7 @@ class InlinePie extends AbstractWidget
sparkType="pie"></span>
<noscript>
<img class="inlinepie"
title="{title}" src="{url}" style="width: {width}px; height: {height}px; {style}"
title="{title}" src="{url}" style="position: relative; top: 10px; width: {width}px; height: {height}px; {style}"
data-icinga-colors="{colors}" data-icinga-values="{data}"
/>
</noscript>

View File

@ -4,6 +4,7 @@
namespace Icinga\Web\Widget\Dashboard;
use Icinga\Exception\IcingaException;
use Icinga\Util\Dimension;
use Icinga\Web\Form;
use Icinga\Web\Url;
@ -29,6 +30,13 @@ class Component extends AbstractWidget
*/
private $url;
/**
* The id of this Component
*
* @var string
*/
private $id;
/**
* The title being displayed on top of the component
* @var
@ -59,12 +67,14 @@ EOD;
/**
* Create a new component displaying the given url in the provided pane
*
* @param string $id The id to use for this component
* @param string $title The title to use for this component
* @param Url|string $url The url this component uses for displaying information
* @param Pane $pane The pane this Component will be added to
*/
public function __construct($title, $url, Pane $pane)
public function __construct($id, $title, $url, Pane $pane)
{
$this->id = $id;
$this->title = $title;
$this->pane = $pane;
if ($url instanceof Url) {
@ -72,11 +82,9 @@ EOD;
} elseif ($url) {
$this->url = Url::fromPath($url);
} else {
throw new Exception(
sprintf(
'Cannot create dashboard component "%s" without valid URL',
$title
)
throw new IcingaException(
'Cannot create dashboard component "%s" without valid URL',
$title
);
}
}
@ -187,14 +195,14 @@ EOD;
/**
* Create a @see Component instance from the given Zend config, using the provided title
*
* @param $id The id for this component
* @param $title The title for this component
* @param Zend_Config $config The configuration defining url, parameters, height, width, etc.
* @param Pane $pane The pane this component belongs to
*
* @return Component A newly created Component for use in the Dashboard
*/
public static function fromIni($title, Zend_Config $config, Pane $pane)
public static function fromIni($id, $title, Zend_Config $config, Pane $pane)
{
$height = null;
$width = null;
@ -202,7 +210,27 @@ EOD;
$parameters = $config->toArray();
unset($parameters['url']); // otherwise there's an url = parameter in the Url
$cmp = new Component($title, Url::fromPath($url, $parameters), $pane);
$cmp = new Component($id, $title, Url::fromPath($url, $parameters), $pane);
return $cmp;
}
/**
* Set the components id
*
* @param $id string
*/
public function setId($id)
{
$this->id = $id;
}
/**
* Retrieve the components id
*
* @return string
*/
public function getId()
{
return $this->id;
}
}

View File

@ -83,44 +83,44 @@ class Pane extends AbstractWidget
/**
* Return true if a component with the given title exists in this pane
*
* @param string $title The title of the component to check for existence
* @param string $id The id of the component to check for existence
*
* @return bool
*/
public function hasComponent($title)
public function hasComponent($id)
{
return array_key_exists($title, $this->components);
return array_key_exists($id, $this->components);
}
/**
* Return a component with the given name if existing
*
* @param string $title The title of the component to return
* @param string $id The id of the component to return
*
* @return Component The component with the given title
* @throws ProgrammingError If the component doesn't exist
*/
public function getComponent($title)
public function getComponent($id)
{
if ($this->hasComponent($title)) {
return $this->components[$title];
if ($this->hasComponent($id)) {
return $this->components[$id];
}
throw new ProgrammingError(
'Trying to access invalid component: %s',
$title
$id
);
}
/**
* Removes the component with the given title if it exists in this pane
* Removes the component with the given id if it exists in this pane
*
* @param string $title The pane
* @param string $id The pane
* @return Pane $this
*/
public function removeComponent($title)
public function removeComponent($id)
{
if ($this->hasComponent($title)) {
unset($this->components[$title]);
if ($this->hasComponent($id)) {
unset($this->components[$id]);
}
return $this;
}
@ -146,6 +146,7 @@ class Pane extends AbstractWidget
/**
* Add a component to this pane, optionally creating it if $component is a string
*
* @param string $id An unique Identifier
* @param string|Component $component The component object or title
* (if a new component will be created)
* @param string|null $url An Url to be used when component is a string
@ -153,12 +154,12 @@ class Pane extends AbstractWidget
* @return self
* @throws \Icinga\Exception\ConfigurationError
*/
public function addComponent($component, $url = null)
public function addComponent($id, $component, $url = null)
{
if ($component instanceof Component) {
$this->components[$component->getTitle()] = $component;
} elseif (is_string($component) && $url !== null) {
$this->components[$component] = new Component($component, $url, $this);
$this->components[$component->getId()] = $component;
} elseif (is_string($id) && is_string($component) && $url !== null) {
$this->components[$id] = new Component($id, $component, $url, $this);
} else {
throw new ConfigurationError('Invalid component added: %s', $component);
}
@ -175,15 +176,15 @@ class Pane extends AbstractWidget
{
/* @var $component Component */
foreach ($components as $component) {
if (array_key_exists($component->getTitle(), $this->components)) {
if (preg_match('/_(\d+)$/', $component->getTitle(), $m)) {
$name = preg_replace('/_\d+$/', $m[1]++, $component->getTitle());
if (array_key_exists($component->getId(), $this->components)) {
if (preg_match('/-(\d+)$/', $component->getId(), $m)) {
$name = preg_replace('/-\d+$/', $m[1]++, $component->getId());
} else {
$name = $component->getTitle() . '_2';
$name = $component->getId() . '-2';
}
$this->components[$name] = $component;
} else {
$this->components[$component->getTitle()] = $component;
$this->components[$component->getId()] = $component;
}
}
@ -193,17 +194,18 @@ class Pane extends AbstractWidget
/**
* Add a component to the current pane
*
* @param $id
* @param $title
* @param $url
* @return Component
* @param null $url
* @return mixed
*
* @see addComponent()
*/
public function add($title, $url = null)
public function add($id, $title, $url = null)
{
$this->addComponent($title, $url);
$this->addComponent($id, $title, $url);
return $this->components[$title];
return $this->components[$id];
}
/**

View File

@ -2,7 +2,7 @@
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
use \Zend_Controller_Action_Exception;
use Zend_Controller_Action_Exception;
use Icinga\Application\Icinga;
use Icinga\Module\Doc\DocController;

View File

@ -2,7 +2,7 @@
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
use \Zend_Controller_Action_Exception;
use Zend_Controller_Action_Exception;
use Icinga\Application\Icinga;
use Icinga\Module\Doc\DocController;
use Icinga\Module\Doc\Exception\DocException;

View File

@ -4,8 +4,7 @@
/* @var $this \Icinga\Application\Modules\Module */
$section = $this->menuSection($this->translate('Documentation'), array(
'title' => 'Documentation',
$section = $this->menuSection('documentation', $this->translate('Documentation'), array(
'icon' => 'img/icons/comment.png',
'url' => 'doc',
'priority' => 80

View File

@ -15,9 +15,15 @@ use Icinga\Chart\Unit\StaticAxis;
class Monitoring_ChartController extends Controller
{
public function init()
{
$this->view->compact = $this->_request->getParam('view') === 'compact';
}
public function testAction()
{
$this->chart = new GridChart();
$this->chart->alignTopLeft();
$this->chart->setAxisLabel('X axis label', 'Y axis label')->setXAxis(new StaticAxis());
$data1 = array();
$data2 = array();
@ -90,7 +96,7 @@ class Monitoring_ChartController extends Controller
$this->view->height = intval($this->getParam('height', 500));
$this->view->width = intval($this->getParam('width', 500));
if (count($query) === 1) {
$this->drawGroupPie($query[0]);
$this->drawHostGroupPie($query[0]);
} else {
$this->drawHostGroupChart($query);
}
@ -115,8 +121,12 @@ class Monitoring_ChartController extends Controller
$this->view->height = intval($this->getParam('height', 500));
$this->view->width = intval($this->getParam('width', 500));
$this->drawServiceGroupChart($query);
if (count($query) === 1) {
$this->drawServiceGroupPie($query[0]);
} else {
$this->drawServiceGroupChart($query);
}
}
private function drawServiceGroupChart($query)
@ -132,6 +142,7 @@ class Monitoring_ChartController extends Controller
$unknownBars[] = array($servicegroup->servicegroup, $servicegroup->services_unknown_unhandled);
}
$this->view->chart = new GridChart();
$this->view->chart->alignTopLeft();
$this->view->chart->setAxisLabel('', t('Services'))
->setXAxis(new StaticAxis())
->setAxisMin(null, 0);
@ -184,6 +195,7 @@ class Monitoring_ChartController extends Controller
);
}
$this->view->chart = new GridChart();
$this->view->chart->alignTopLeft();
$this->view->chart->setAxisLabel('', t('Hosts'))
->setXAxis(new StaticAxis())
->setAxisMin(null, 0);
@ -209,31 +221,13 @@ class Monitoring_ChartController extends Controller
);
}
private function drawGroupPie($query)
private function drawServiceGroupPie($query)
{
$this->view->chart = new PieChart();
if (isset($query->hosts_up)) {
$this->view->chart->drawPie(array(
'data' => array(
// (int) $query->hosts_up,
(int) $query->hosts_down_handled,
(int) $query->hosts_down_unhandled,
(int) $query->hosts_unreachable_handled,
(int) $query->hosts_unreachable_unhandled,
(int) $query->hosts_pending
),
'colors' => array( '#ff4444', '#ff0000', '#E066FF', '#f099FF', '#fefefe'),
'labels'=> array(
// (int) $query->hosts_up . ' Up Hosts',
(int) $query->hosts_down_handled . t(' Down Hosts (Handled)'),
(int) $query->hosts_down_unhandled . t(' Down Hosts (Unhandled)'),
(int) $query->hosts_unreachable_handled . t(' Unreachable Hosts (Handled)'),
(int) $query->hosts_unreachable_unhandled . t(' Unreachable Hosts (Unhandled)'),
(int) $query->hosts_pending . t(' Pending Hosts')
)
), array(
$this->view->chart->alignTopLeft();
$this->view->chart->drawPie(array(
'data' => array(
// (int) $query->services_ok,
(int) $query->services_ok,
(int) $query->services_warning_unhandled,
(int) $query->services_warning_handled,
(int) $query->services_critical_unhandled,
@ -242,9 +236,9 @@ class Monitoring_ChartController extends Controller
(int) $query->services_unknown_handled,
(int) $query->services_pending
),
'colors' => array('#ff4444', '#ff0000', '#ffff00', '#ffff33', '#E066FF', '#f099FF', '#fefefe'),
'colors' => array('#44bb77', '#ff4444', '#ff0000', '#ffff00', '#ffff33', '#E066FF', '#f099FF', '#fefefe'),
'labels'=> array(
// $query->services_ok . ' Up Services',
$query->services_ok . ' Up Services',
$query->services_warning_handled . t(' Warning Services (Handled)'),
$query->services_warning_unhandled . t(' Warning Services (Unhandled)'),
$query->services_critical_handled . t(' Down Services (Handled)'),
@ -252,8 +246,54 @@ class Monitoring_ChartController extends Controller
$query->services_unknown_handled . t(' Unreachable Services (Handled)'),
$query->services_unknown_unhandled . t(' Unreachable Services (Unhandled)'),
$query->services_pending . t(' Pending Services')
)
)
));
}
private function drawHostGroupPie($query)
{
$this->view->chart = new PieChart();
$this->view->chart->alignTopLeft();
$this->view->chart->drawPie(array(
'data' => array(
(int) $query->hosts_up,
(int) $query->hosts_down_handled,
(int) $query->hosts_down_unhandled,
(int) $query->hosts_unreachable_handled,
(int) $query->hosts_unreachable_unhandled,
(int) $query->hosts_pending
),
'colors' => array('#44bb77', '#ff4444', '#ff0000', '#E066FF', '#f099FF', '#fefefe'),
'labels'=> array(
(int) $query->hosts_up . ' Up Hosts',
(int) $query->hosts_down_handled . t(' Down Hosts (Handled)'),
(int) $query->hosts_down_unhandled . t(' Down Hosts (Unhandled)'),
(int) $query->hosts_unreachable_handled . t(' Unreachable Hosts (Handled)'),
(int) $query->hosts_unreachable_unhandled . t(' Unreachable Hosts (Unhandled)'),
(int) $query->hosts_pending . t(' Pending Hosts')
)
), array(
'data' => array(
(int) $query->services_ok,
(int) $query->services_warning_unhandled,
(int) $query->services_warning_handled,
(int) $query->services_critical_unhandled,
(int) $query->services_critical_handled,
(int) $query->services_unknown_unhandled,
(int) $query->services_unknown_handled,
(int) $query->services_pending
),
'colors' => array('#44bb77', '#ff4444', '#ff0000', '#ffff00', '#ffff33', '#E066FF', '#f099FF', '#fefefe'),
'labels'=> array(
$query->services_ok . ' Up Services',
$query->services_warning_handled . t(' Warning Services (Handled)'),
$query->services_warning_unhandled . t(' Warning Services (Unhandled)'),
$query->services_critical_handled . t(' Down Services (Handled)'),
$query->services_critical_unhandled . t(' Down Services (Unhandled)'),
$query->services_unknown_handled . t(' Unreachable Services (Handled)'),
$query->services_unknown_unhandled . t(' Unreachable Services (Unhandled)'),
$query->services_pending . t(' Pending Services')
)
));
}
}
}

View File

@ -25,6 +25,7 @@ use Icinga\Module\Monitoring\Form\Command\DelayNotificationForm;
use Icinga\Module\Monitoring\Form\Command\RescheduleNextCheckForm;
use Icinga\Module\Monitoring\Form\Command\ScheduleDowntimeForm;
use Icinga\Module\Monitoring\Form\Command\SubmitPassiveCheckResultForm;
use Icinga\Exception\IcingaException;
/**
* Class Monitoring_CommandController
@ -238,13 +239,16 @@ class Monitoring_CommandController extends Controller
$given = array_intersect_key($supported, $this->getRequest()->getParams());
if (empty($given)) {
throw new \Exception('Missing parameter, supported: '.implode(', ', array_flip($supported)));
throw new IcingaException(
'Missing parameter, supported: %s',
implode(', ', array_flip($supported))
);
}
if (isset($given['host'])) {
$objects = $this->selectCommandTargets(!in_array("service", $supported));
if (empty($objects)) {
throw new \Exception("No objects found for your command");
throw new IcingaException('No objects found for your command');
}
}

View File

@ -2,8 +2,6 @@
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
use \Exception;
use \Zend_Config;
use Icinga\Config\PreservingIniWriter;
use Icinga\Web\Controller\ModuleActionController;
use Icinga\Web\Notification;

View File

@ -2,7 +2,7 @@
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
use \Icinga\Module\Monitoring\Command\Meta;
use Icinga\Module\Monitoring\Command\Meta;
/**
* Class MonitoringCommands

View File

@ -25,6 +25,9 @@ class Monitoring_ShowController extends Controller
*/
protected $backend;
/**
* @var Hook\GrapherHook
*/
protected $grapher;
/**
@ -61,8 +64,8 @@ class Monitoring_ShowController extends Controller
. ' on ' . $o->host_name;
$this->getTabs()->activate('service');
$o->populate();
if ($this->grapher && $this->grapher->hasGraph($o->host_name, $o->service_description)) {
$this->view->grapherHtml = $this->grapher->getPreviewImage($o->host_name, $o->service_description);
if ($this->grapher && $this->grapher->hasPreviews($o->host_name, $o->service_description)) {
$this->view->grapherHtml = $this->grapher->getPreviewHtml($o->host_name, $o->service_description);
}
}
@ -76,8 +79,8 @@ class Monitoring_ShowController extends Controller
$this->getTabs()->activate('host');
$this->view->title = $o->host_name;
$o->populate();
if ($this->grapher && $this->grapher->hasGraph($o->host_name)) {
$this->view->grapherHtml = $this->grapher->getPreviewImage($o->host_name);
if ($this->grapher && $this->grapher->hasPreviews($o->host_name)) {
$this->view->grapherHtml = $this->grapher->getPreviewHtml($o->host_name);
}
}
@ -105,19 +108,22 @@ class Monitoring_ShowController extends Controller
public function contactAction()
{
$contact = $this->getParam('contact');
if (! $contact) {
$contactName = $this->getParam('contact');
if (! $contactName) {
throw new Zend_Controller_Action_Exception(
$this->translate('The parameter `contact\' is required'),
404
);
}
$query = $this->backend->select()->from('contact', array(
'contact_name',
'contact_id',
'contact_alias',
'contact_email',
'contact_pager',
'contact_object_id',
'contact_notify_service_timeperiod',
'contact_notify_service_recovery',
'contact_notify_service_warning',
@ -132,9 +138,36 @@ class Monitoring_ShowController extends Controller
'contact_notify_host_flapping',
'contact_notify_host_downtime',
));
$query->where('contact_name', $contact);
$this->view->contacts = $query->paginate();
$this->view->contact_name = $contact;
$query->where('contact_name', $contactName);
$contact = $query->getQuery()->fetchRow();
if ($contact) {
$commands = $this->backend->select()->from('command', array(
'command_line',
'command_name'
))->where('contact_id', $contact->contact_id);
$this->view->commands = $commands->paginate();
$notifications = $this->backend->select()->from('notification', array(
'host',
'service',
'notification_output',
'notification_contact',
'notification_start_time',
'notification_state'
));
$notifications->where('contact_object_id', $contact->contact_object_id);
$this->view->compact = true;
$this->view->notifications = $notifications->paginate();
}
$this->view->contact = $contact;
$this->view->contactName = $contactName;
}
/**

View File

@ -2,9 +2,9 @@
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
use \DateTime;
use \DateInterval;
use \Zend_Config;
use DateTime;
use DateInterval;
use Zend_Config;
use Icinga\Web\Url;
use Icinga\Util\Format;
use Icinga\Application\Config;

View File

@ -4,10 +4,10 @@
namespace Icinga\Module\Monitoring\Form\Command;
use \Icinga\Web\Form\Element\DateTimePicker;
use \Icinga\Protocol\Commandpipe\Comment;
use \Icinga\Util\DateTimeFactory;
use \Icinga\Module\Monitoring\Command\AcknowledgeCommand;
use Icinga\Web\Form\Element\DateTimePicker;
use Icinga\Protocol\Commandpipe\Comment;
use Icinga\Util\DateTimeFactory;
use Icinga\Module\Monitoring\Command\AcknowledgeCommand;
/**
* Form for problem acknowledgements

View File

@ -4,10 +4,10 @@
namespace Icinga\Module\Monitoring\Form\Command;
use \Icinga\Web\Form\Element\TriStateCheckbox;
use \Icinga\Web\Form;
use \Zend_Form_Element_Hidden;
use \Zend_Form;
use Icinga\Web\Form\Element\TriStateCheckbox;
use Icinga\Web\Form;
use Zend_Form_Element_Hidden;
use Zend_Form;
/**
* A form to edit multiple command flags of multiple commands at once. When some commands have

View File

@ -5,7 +5,7 @@
namespace Icinga\Module\Monitoring\Form\Command;
use Zend_Controller_Request_Abstract;
use \Zend_Form_Element_Hidden;
use Zend_Form_Element_Hidden;
use Icinga\Module\Monitoring\Command\AcknowledgeCommand;
use Icinga\Module\Monitoring\Command\SingleArgumentCommand;

View File

@ -4,7 +4,7 @@
namespace Icinga\Module\Monitoring\Form\Command;
use \Icinga\Exception\ProgrammingError;
use Icinga\Exception\ProgrammingError;
/**
* Form for submitting passive check results

View File

@ -34,7 +34,7 @@ class Zend_View_Helper_Perfdata extends Zend_View_Helper_Abstract
// TODO: Should we trust sprintf-style placeholders in perfdata titles?
$pieChart->setTooltipFormat('{{label}}: {{formatted}} ({{percent}}%)');
}
$pieChart->setStyle('margin: 0.2em 0.5em 0.2em 0.5em;');
// $pieChart->setStyle('margin: 0.2em 0.5em 0.2em 0.5em;');
$table[] = '<tr><th>' . $pieChart->render()
. htmlspecialchars($perfdata->getLabel())
. '</th><td> '

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