From 49562e75d7ed96574385a180caee282710950044 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Wed, 3 Sep 2014 15:08:37 +0200 Subject: [PATCH 01/44] Adjust ..\Monitoring\Form\Config\SecurityForm to use handleRequest() refs #5525 --- .../controllers/ConfigController.php | 25 ++----- .../forms/Config/SecurityConfigForm.php | 68 +++++++++++++++++++ .../application/forms/Config/SecurityForm.php | 42 ------------ 3 files changed, 73 insertions(+), 62 deletions(-) create mode 100644 modules/monitoring/application/forms/Config/SecurityConfigForm.php delete mode 100644 modules/monitoring/application/forms/Config/SecurityForm.php diff --git a/modules/monitoring/application/controllers/ConfigController.php b/modules/monitoring/application/controllers/ConfigController.php index ce22d73df..a1bed1a4e 100644 --- a/modules/monitoring/application/controllers/ConfigController.php +++ b/modules/monitoring/application/controllers/ConfigController.php @@ -8,7 +8,7 @@ use Icinga\Web\Notification; use Icinga\Form\ConfirmRemovalForm; use Icinga\Module\Monitoring\Form\Config\BackendForm; use Icinga\Module\Monitoring\Form\Config\InstanceForm; -use Icinga\Module\Monitoring\Form\Config\SecurityForm; +use Icinga\Module\Monitoring\Form\Config\SecurityConfigForm; use Icinga\Exception\NotReadableError; /** @@ -254,26 +254,11 @@ class Monitoring_ConfigController extends ModuleActionController */ public function securityAction() { - $this->view->tabs = $this->Module()->getConfigTabs()->activate('security'); - - $form = new SecurityForm(); - $request = $this->getRequest(); - $config = $this->Config()->toArray(); - if ($request->isPost()) { - if ($form->isValid($request->getPost())) { - $config['security'] = $form->getValues(); - if ($this->writeConfiguration(new Zend_Config($config))) { - Notification::success('Configuration modified successfully'); - $this->redirectNow('monitoring/config/security'); - } else { - $this->render('show-configuration'); - return; - } - } - } elseif (isset($config['security'])) { - $form->populate($config['security']); - } + $form = new SecurityConfigForm(); + $form->setConfig($this->Config()); + $form->handleRequest(); $this->view->form = $form; + $this->view->tabs = $this->Module()->getConfigTabs()->activate('security'); } } diff --git a/modules/monitoring/application/forms/Config/SecurityConfigForm.php b/modules/monitoring/application/forms/Config/SecurityConfigForm.php new file mode 100644 index 000000000..33a03328e --- /dev/null +++ b/modules/monitoring/application/forms/Config/SecurityConfigForm.php @@ -0,0 +1,68 @@ +setName('form_config_monitoring_security'); + $this->setSubmitLabel(t('Save Changes')); + } + + /** + * @see Form::onSuccess() + */ + public function onSuccess(Request $request) + { + $this->config->security = $this->getValues(); + + if ($this->save()) { + Notification::success(t('New security configuration has successfully been stored')); + } else { + return false; + } + } + + /** + * @see Form::onRequest() + */ + public function onRequest(Request $request) + { + if (isset($this->config->security)) { + $this->populate($this->config->security->toArray()); + } + } + + /** + * @see Form::createElements() + */ + public function createElements(array $formData) + { + $this->addElement( + 'text', + 'protected_customvars', + array( + 'required' => true, + 'label' => 'Protected Custom Variables', + 'description' => 'Comma separated case insensitive list of protected custom variables.' + . ' Use * as a placeholder for zero or more wildcard characters.' + . ' Existance of those custom variables will be shown, but their values will be masked.' + ) + ); + + return $this; + } +} diff --git a/modules/monitoring/application/forms/Config/SecurityForm.php b/modules/monitoring/application/forms/Config/SecurityForm.php deleted file mode 100644 index 48368d0f1..000000000 --- a/modules/monitoring/application/forms/Config/SecurityForm.php +++ /dev/null @@ -1,42 +0,0 @@ -setName('form_config_monitoring_security'); - $this->setSubmitLabel(t('Save Changes')); - } - - /** - * @see Form::createElements() - */ - public function createElements(array $formData) - { - return array( - $this->createElement( - 'text', - 'protected_customvars', - array( - 'label' => 'Protected Custom Variables', - 'required' => true, - 'helptext' => 'Comma separated case insensitive list of protected custom variables.' - . ' Use * as a placeholder for zero or more wildcard characters.' - . ' Existance of those custom variables will be shown, but their values will be masked.' - ) - ) - ); - } -} From 9d66cc90232f664bc6b534acf3eeefbec3343821 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Thu, 4 Sep 2014 08:47:16 +0200 Subject: [PATCH 02/44] Adjust Monitoring\InstanceForm to use handleRequest() & Co. refs #5525 --- .../controllers/ConfigController.php | 94 +++----- .../Config/Instance/LocalInstanceForm.php | 37 +++ .../Config/Instance/RemoteInstanceForm.php | 68 ++++++ .../forms/Config/InstanceConfigForm.php | 211 ++++++++++++++++++ .../application/forms/Config/InstanceForm.php | 156 ------------- .../views/scripts/config/removeinstance.phtml | 4 +- 6 files changed, 348 insertions(+), 222 deletions(-) create mode 100644 modules/monitoring/application/forms/Config/Instance/LocalInstanceForm.php create mode 100644 modules/monitoring/application/forms/Config/Instance/RemoteInstanceForm.php create mode 100644 modules/monitoring/application/forms/Config/InstanceConfigForm.php delete mode 100644 modules/monitoring/application/forms/Config/InstanceForm.php diff --git a/modules/monitoring/application/controllers/ConfigController.php b/modules/monitoring/application/controllers/ConfigController.php index a1bed1a4e..5636b5b17 100644 --- a/modules/monitoring/application/controllers/ConfigController.php +++ b/modules/monitoring/application/controllers/ConfigController.php @@ -7,7 +7,7 @@ use Icinga\Web\Controller\ModuleActionController; use Icinga\Web\Notification; use Icinga\Form\ConfirmRemovalForm; use Icinga\Module\Monitoring\Form\Config\BackendForm; -use Icinga\Module\Monitoring\Form\Config\InstanceForm; +use Icinga\Module\Monitoring\Form\Config\InstanceConfigForm; use Icinga\Module\Monitoring\Form\Config\SecurityConfigForm; use Icinga\Exception\NotReadableError; @@ -134,29 +134,31 @@ class Monitoring_ConfigController extends ModuleActionController */ public function removeinstanceAction() { - $instance = $this->getParam('instance'); - $instancesConfig = $this->Config('instances')->toArray(); - if (false === array_key_exists($instance, $instancesConfig)) { - // TODO: Should behave as in the app's config controller (Specific redirect to an error action) - Notification::error(sprintf($this->translate('Cannot remove "%s". Instance not found.'), $instance)); - $this->redirectNow('monitoring/config'); - } + $config = $this->Config('instances'); + $form = new ConfirmRemovalForm(array( + 'onSuccess' => function ($request) use ($config) { + $instanceName = $request->getQuery('instance'); + $configForm = new InstanceConfigForm(); + $configForm->setConfig($config); - $form = new ConfirmRemovalForm(); - $request = $this->getRequest(); - if ($request->isPost() && $form->isValid($request->getPost())) { - unset($instancesConfig[$instance]); - if ($this->writeConfiguration($instancesConfig, 'instances')) { - Notification::success(sprintf($this->translate('Instance "%s" successfully removed.'), $instance)); - $this->redirectNow('monitoring/config'); - } else { - $this->render('show-configuration'); - return; + try { + $configForm->remove($instanceName); + } catch (InvalidArgumentException $e) { + Notification::error($e->getMessage()); + return; + } + + if ($configForm->save()) { + Notification::success(sprintf(t('Instance "%s" successfully removed.'), $instanceName)); + } else { + return false; + } } - } + )); + $form->setRedirectUrl('monitoring/config'); + $form->handleRequest(); $this->view->form = $form; - $this->view->name = $instance; } /** @@ -164,36 +166,10 @@ class Monitoring_ConfigController extends ModuleActionController */ public function editinstanceAction() { - $instance = $this->getParam('instance'); - $instancesConfig = $this->Config('instances')->toArray(); - if (false === array_key_exists($instance, $instancesConfig)) { - // TODO: Should behave as in the app's config controller (Specific redirect to an error action) - Notification::error(sprintf($this->translate('Cannot edit "%s". Instance not found.'), $instance)); - $this->redirectNow('monitoring/config'); - } - - $form = new InstanceForm(); - $request = $this->getRequest(); - if ($request->isPost()) { - if ($form->isValid($request->getPost())) { - list($newName, $config) = $form->getInstanceConfig(); - - if ($newName !== $instance) { - unset($instancesConfig[$instance]); // We can safely use unset as all values are part of the form - } - - $instancesConfig[$newName] = $config; - if ($this->writeConfiguration($instancesConfig, 'instances')) { - Notification::success(sprintf($this->translate('Instance "%s" successfully modified.'), $instance)); - $this->redirectNow('monitoring/config'); - } else { - $this->render('show-configuration'); - return; - } - } - } else { - $form->setInstanceConfig($instance, $instancesConfig[$instance]); - } + $form = new InstanceConfigForm(); + $form->setConfig($this->Config('instances')); + $form->setRedirectUrl('monitoring/config'); + $form->handleRequest(); $this->view->form = $form; } @@ -203,20 +179,10 @@ class Monitoring_ConfigController extends ModuleActionController */ public function createinstanceAction() { - $form = new InstanceForm(); - $request = $this->getRequest(); - if ($request->isPost() && $form->isValid($request->getPost())) { - list($name, $config) = $form->getInstanceConfig(); - $instancesConfig = $this->Config('instances')->toArray(); - $instancesConfig[$name] = $config; - if ($this->writeConfiguration($instancesConfig, 'instances')) { - Notification::success(sprintf($this->translate('Instance "%s" created successfully.'), $name)); - $this->redirectNow('monitoring/config'); - } else { - $this->render('show-configuration'); - return; - } - } + $form = new InstanceConfigForm(); + $form->setConfig($this->Config('instances')); + $form->setRedirectUrl('monitoring/config'); + $form->handleRequest(); $this->view->form = $form; } diff --git a/modules/monitoring/application/forms/Config/Instance/LocalInstanceForm.php b/modules/monitoring/application/forms/Config/Instance/LocalInstanceForm.php new file mode 100644 index 000000000..513ba2433 --- /dev/null +++ b/modules/monitoring/application/forms/Config/Instance/LocalInstanceForm.php @@ -0,0 +1,37 @@ +setName('form_config_monitoring_instance_local'); + } + + /** + * @see Form::createElements() + */ + public function createElements(array $formData) + { + $this->addElement( + 'text', + 'path', + array( + 'required' => true, + 'label' => t('Local Filepath'), + 'value' => '/usr/local/icinga/var/rw/icinga.cmd', + 'description' => t('The file path where the icinga commandpipe can be found') + ) + ); + + return $this; + } +} diff --git a/modules/monitoring/application/forms/Config/Instance/RemoteInstanceForm.php b/modules/monitoring/application/forms/Config/Instance/RemoteInstanceForm.php new file mode 100644 index 000000000..0e78a0aec --- /dev/null +++ b/modules/monitoring/application/forms/Config/Instance/RemoteInstanceForm.php @@ -0,0 +1,68 @@ +setName('form_config_monitoring_instance_remote'); + } + + /** + * @see Form::createElements() + */ + public function createElements(array $formData) + { + $this->addElement( + 'text', + 'host', + array( + 'required' => true, + 'label' => t('Remote Host'), + 'description' => t( + 'Enter the hostname or address of the machine on which the icinga instance is running' + ) + ) + ); + $this->addElement( + new Number( + array( + 'required' => true, + 'name' => 'port', + 'label' => t('Remote SSH Port'), + 'description' => t('Enter the ssh port to use for connecting to the remote icinga instance'), + 'value' => 22 + ) + ) + ); + $this->addElement( + 'text', + 'user', + array( + 'required' => true, + 'label' => t('Remote SSH User'), + 'description' => t( + 'Enter the username to use for connecting to the remote machine or leave blank for default' + ) + ) + ); + $this->addElement( + 'text', + 'path', + array( + 'required' => true, + 'label' => t('Remote Filepath'), + 'value' => '/usr/local/icinga/var/rw/icinga.cmd', + 'description' => t('The file path where the icinga commandpipe can be found') + ) + ); + + return $this; + } +} diff --git a/modules/monitoring/application/forms/Config/InstanceConfigForm.php b/modules/monitoring/application/forms/Config/InstanceConfigForm.php new file mode 100644 index 000000000..011284a9a --- /dev/null +++ b/modules/monitoring/application/forms/Config/InstanceConfigForm.php @@ -0,0 +1,211 @@ +setName('form_config_monitoring_instance'); + $this->setSubmitLabel(t('Save Changes')); + } + + /** + * Return a form object for the given instance type + * + * @param string $type The instance type for which to return a form + * + * @return Form + * + * @throws InvalidArgumentException In case the given instance type is invalid + */ + public function getInstanceForm($type) + { + if ($type === 'local') { + return new LocalInstanceForm(); + } elseif ($type === 'remote') { + return new RemoteInstanceForm(); + } else { + throw new InvalidArgumentException(sprintf(t('Invalid instance type "%s" provided'), $type)); + } + } + + /** + * Add a new instance + * + * The resource 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 resource already exists + */ + public function add(array $values) + { + $name = isset($values['name']) ? $values['name'] : ''; + if (! $name) { + throw new InvalidArgumentException(t('Instance name missing')); + } elseif ($this->config->get($name) !== null) { + throw new InvalidArgumentException(t('Instance already exists')); + } + + unset($values['name']); + $this->config->{$name} = $values; + return $this; + } + + /** + * Edit an existing instance + * + * @param string $name The name of the resource to edit + * @param array $values The values to edit the configuration with + * + * @return array The edited resource configuration + * + * @throws InvalidArgumentException In case the resource name is missing or invalid + */ + public function edit($name, array $values) + { + if (! $name) { + throw new InvalidArgumentException(t('Old instance name missing')); + } elseif (! ($newName = isset($values['name']) ? $values['name'] : '')) { + throw new InvalidArgumentException(t('New instance name missing')); + } elseif (! ($instanceConfig = $this->config->get($name))) { + throw new InvalidArgumentException(t('Unknown instance name provided')); + } + + unset($values['name']); + unset($this->config->{$name}); + $this->config->{$newName} = array_merge($instanceConfig->toArray(), $values); + return $this->config->{$newName}; + } + + /** + * Remove a instance + * + * @param string $name The name of the resource to remove + * + * @return array The removed resource confguration + * + * @throws InvalidArgumentException In case the resource name is missing or invalid + */ + public function remove($name) + { + if (! $name) { + throw new InvalidArgumentException(t('Instance name missing')); + } elseif (! ($instanceConfig = $this->config->get($name))) { + throw new InvalidArgumentException(t('Unknown instance name provided')); + } + + unset($this->config->{$name}); + return $instanceConfig; + } + + /** + * @see Form::onSuccess() + */ + public function onSuccess(Request $request) + { + $instanceName = $request->getQuery('instance'); + + try { + if ($instanceName === null) { // create new instance + $this->add($this->getValues()); + $message = t('Instance "%s" created successfully.'); + } else { // edit existing instance + $this->edit($instanceName, $this->getValues()); + $message = t('Instance "%s" edited successfully.'); + } + } catch (InvalidArgumentException $e) { + Notification::error($e->getMessage()); + return; + } + + if ($this->save()) { + Notification::success(sprintf($message, $this->getElement('name')->getValue())); + } else { + return false; + } + } + + /** + * @see Form::onRequest() + * + * @throws ConfigurationError In case the instance name is missing or invalid + */ + public function onRequest(Request $request) + { + $instanceName = $request->getQuery('instance'); + if ($instanceName !== null) { + if (! $instanceName) { + throw new ConfigurationError(t('Instance name missing')); + } elseif (false === isset($this->config->{$instanceName})) { + throw new ConfigurationError(t('Unknown instance name provided')); + } + + $instanceConfig = $this->config->{$instanceName}->toArray(); + $instanceConfig['name'] = $instanceName; + if (isset($instanceConfig['host'])) { + // Necessary as we have no config directive for setting the instance's type + $instanceConfig['type'] = 'remote'; + } + $this->populate($instanceConfig); + } + } + + /** + * @see Form::createElements() + */ + public function createElements(array $formData) + { + $instanceType = isset($formData['type']) ? $formData['type'] : 'local'; + + $this->addElement( + 'text', + 'name', + array( + 'required' => true, + 'label' => t('Instance Name') + ) + ); + $this->addElement( + 'select', + 'type', + array( + 'required' => true, + 'ignore' => true, + 'autosubmit' => true, + 'label' => t('Instance Type'), + 'description' => t( + 'When configuring a remote host, you need to setup passwordless key authentication' + ), + 'multiOptions' => array( + 'local' => t('Local Command Pipe'), + 'remote' => t('Remote Command Pipe') + ), + 'value' => $instanceType + ) + ); + + $this->addElements($this->getInstanceForm($instanceType)->createElements($formData)->getElements()); + + return $this; + } +} diff --git a/modules/monitoring/application/forms/Config/InstanceForm.php b/modules/monitoring/application/forms/Config/InstanceForm.php deleted file mode 100644 index 3794e3c54..000000000 --- a/modules/monitoring/application/forms/Config/InstanceForm.php +++ /dev/null @@ -1,156 +0,0 @@ -setName('form_config_monitoring_instances'); - $this->setSubmitLabel(t('Save Changes')); - } - - /** - * @see Form::createElements() - */ - public function createElements(array $formData) - { - $elements = array( - $this->createElement( - 'text', - 'name', - array( - 'required' => true, - 'label' => t('Instance Name') - ) - ), - $this->createElement( - 'select', - 'type', - array( - 'required' => true, - 'ignore' => true, - 'label' => t('Instance Type'), - 'class' => 'autosubmit', - 'helptext' => t( - 'When configuring a remote host, you need to setup passwordless key authentication' - ), - 'multiOptions' => array( - 'local' => t('Local Command Pipe'), - 'remote' => t('Remote Command Pipe') - ) - ) - ) - ); - - if (isset($formData['type']) && $formData['type'] === 'remote') { - $elements[] = $this->createElement( - 'text', - 'host', - array( - 'required' => true, - 'label' => t('Remote Host'), - 'helptext' => t( - 'Enter the hostname or address of the machine on which the icinga instance is running' - ) - ) - ); - $elements[] = new Number( - array( - 'required' => true, - 'name' => 'port', - 'label' => t('Remote SSH Port'), - 'helptext' => t('Enter the ssh port to use for connecting to the remote icinga instance'), - 'value' => 22, - 'decorators' => array( // The order is important! - 'ViewHelper', - 'Errors', - new ElementWrapper(), - new HelpText() - ) - ) - ); - $elements[] = $this->createElement( - 'text', - 'user', - array( - 'required' => true, - 'label' => t('Remote SSH User'), - 'helptext' => t( - 'Enter the username to use for connecting to the remote machine or leave blank for default' - ) - ) - ); - } else { - // TODO(5967,5525): Without this element, switching the type to "local" causes - // the form to be processed as it's complete in that case. - $elements[] = $this->createElement( - 'hidden', - 'hitchhiker', - array( - 'required' => true, - 'ignore' => true, - 'value' => 'Arthur' - ) - ); - } - - $elements[] = $this->createElement( - 'text', - 'path', - array( - 'required' => true, - 'label' => t('Pipe Filepath'), - 'value' => '/usr/local/icinga/var/rw/icinga.cmd', - 'helptext' => t('The file path where the icinga commandpipe can be found') - ) - ); - return $elements; - } - - /** - * Return the instance configuration values and its name - * - * The first value is the name and the second one the values as array. - * - * @return array - */ - public function getInstanceConfig() - { - $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 instance - * @param array $config The configuration values - */ - public function setInstanceConfig($name, array $config) - { - $config['name'] = $name; - - if (isset($config['host'])) { - // Necessary as we have no config directive for setting the instance's type - $config['type'] = 'remote'; - } - - $this->populate($config); - } -} diff --git a/modules/monitoring/application/views/scripts/config/removeinstance.phtml b/modules/monitoring/application/views/scripts/config/removeinstance.phtml index 586452173..306d41815 100644 --- a/modules/monitoring/application/views/scripts/config/removeinstance.phtml +++ b/modules/monitoring/application/views/scripts/config/removeinstance.phtml @@ -1,4 +1,4 @@

translate('Remove Existing Instance'); ?>

-

Are you sure you want to remove the instance escape($name); ?>?

-

If you have still any environments or views referring to this instance, you won't be able to send commands anymore after deletion.

+

translate('Are you sure you want to remove this instance?'); ?>

+

translate('If you have still any environments or views referring to this instance, you won\'t be able to send commands anymore after deletion.'); ?>

\ No newline at end of file From 439d1895a7c16dd5bbb35699858a14706ac38231 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Thu, 4 Sep 2014 11:25:47 +0200 Subject: [PATCH 03/44] Adjust Monitoring\BackendForm to use handleRequest() & Co. refs #5525 --- .../controllers/ConfigController.php | 144 +++-------- .../forms/Config/BackendConfigForm.php | 244 ++++++++++++++++++ .../application/forms/Config/BackendForm.php | 125 --------- .../views/scripts/config/index.phtml | 161 +++++------- 4 files changed, 346 insertions(+), 328 deletions(-) create mode 100644 modules/monitoring/application/forms/Config/BackendConfigForm.php delete mode 100644 modules/monitoring/application/forms/Config/BackendForm.php diff --git a/modules/monitoring/application/controllers/ConfigController.php b/modules/monitoring/application/controllers/ConfigController.php index 5636b5b17..c2de49be1 100644 --- a/modules/monitoring/application/controllers/ConfigController.php +++ b/modules/monitoring/application/controllers/ConfigController.php @@ -2,14 +2,13 @@ // {{{ICINGA_LICENSE_HEADER}}} // {{{ICINGA_LICENSE_HEADER}}} -use Icinga\Config\PreservingIniWriter; -use Icinga\Web\Controller\ModuleActionController; use Icinga\Web\Notification; +use Icinga\Data\ResourceFactory; use Icinga\Form\ConfirmRemovalForm; -use Icinga\Module\Monitoring\Form\Config\BackendForm; +use Icinga\Web\Controller\ModuleActionController; +use Icinga\Module\Monitoring\Form\Config\BackendConfigForm; use Icinga\Module\Monitoring\Form\Config\InstanceConfigForm; use Icinga\Module\Monitoring\Form\Config\SecurityConfigForm; -use Icinga\Exception\NotReadableError; /** * Configuration controller for editing monitoring resources @@ -21,19 +20,9 @@ class Monitoring_ConfigController extends ModuleActionController */ public function indexAction() { + $this->view->backendsConfig = $this->Config('backends'); + $this->view->instancesConfig = $this->Config('instances'); $this->view->tabs = $this->Module()->getConfigTabs()->activate('backends'); - foreach (array('backends', 'instances') as $element) { - try { - $elementConfig = $this->Config($element); - if ($elementConfig === null) { - $this->view->{$element} = array(); - } else { - $this->view->{$element} = $elementConfig->toArray(); - } - } catch (NotReadableError $e) { - $this->view->{$element} = $e; - } - } } /** @@ -41,38 +30,11 @@ class Monitoring_ConfigController extends ModuleActionController */ public function editbackendAction() { - // Fetch the backend to be edited - $backend = $this->getParam('backend'); - $backendsConfig = $this->Config('backends')->toArray(); - if (false === array_key_exists($backend, $backendsConfig)) { - // TODO: Should behave as in the app's config controller (Specific redirect to an error action) - Notification::error(sprintf($this->translate('Cannot edit "%s". Backend not found.'), $backend)); - $this->redirectNow('monitoring/config'); - } - - $form = new BackendForm(); - $request = $this->getRequest(); - if ($request->isPost()) { - if ($form->isValid($request->getPost())) { - list($newName, $config) = $form->getBackendConfig(); - - if ($newName !== $backend) { - // Backend name has changed - unset($backendsConfig[$backend]); // We can safely use unset as all values are part of the form - } - - $backendsConfig[$newName] = $config; - if ($this->writeConfiguration($backendsConfig, 'backends')) { - Notification::success(sprintf($this->translate('Backend "%s" successfully modified.'), $backend)); - $this->redirectNow('monitoring/config'); - } else { - $this->render('show-configuration'); - return; - } - } - } else { - $form->setBackendConfig($backend, $backendsConfig[$backend]); - } + $form = new BackendConfigForm(); + $form->setConfig($this->Config('backends')); + $form->setResourceConfig(ResourceFactory::getResourceConfigs()); + $form->setRedirectUrl('monitoring/config'); + $form->handleRequest(); $this->view->form = $form; } @@ -82,20 +44,11 @@ class Monitoring_ConfigController extends ModuleActionController */ public function createbackendAction() { - $form = new BackendForm(); - $request = $this->getRequest(); - if ($request->isPost() && $form->isValid($request->getPost())) { - list($name, $config) = $form->getBackendConfig(); - $backendsConfig = $this->Config('backends')->toArray(); - $backendsConfig[$name] = $config; - if ($this->writeConfiguration($backendsConfig, 'backends')) { - Notification::success(sprintf($this->translate('Backend "%s" created successfully.'), $name)); - $this->redirectNow('monitoring/config'); - } else { - $this->render('show-configuration'); - return; - } - } + $form = new BackendConfigForm(); + $form->setConfig($this->Config('backends')); + $form->setResourceConfig(ResourceFactory::getResourceConfigs()); + $form->setRedirectUrl('monitoring/config'); + $form->handleRequest(); $this->view->form = $form; } @@ -105,26 +58,29 @@ class Monitoring_ConfigController extends ModuleActionController */ public function removebackendAction() { - $backend = $this->getParam('backend'); - $backendsConfig = $this->Config('backends')->toArray(); - if (false === array_key_exists($backend, $backendsConfig)) { - // TODO: Should behave as in the app's config controller (Specific redirect to an error action) - Notification::error(sprintf($this->translate('Cannot remove "%s". Backend not found.'), $backend)); - $this->redirectNow('monitoring/config'); - } + $config = $this->Config('backends'); + $form = new ConfirmRemovalForm(array( + 'onSuccess' => function ($request) use ($config) { + $backendName = $request->getQuery('backend'); + $configForm = new BackendConfigForm(); + $configForm->setConfig($config); - $form = new ConfirmRemovalForm(); - $request = $this->getRequest(); - if ($request->isPost() && $form->isValid($request->getPost())) { - unset($backendsConfig[$backend]); - if ($this->writeConfiguration($backendsConfig, 'backends')) { - Notification::success(sprintf($this->translate('Backend "%s" successfully removed.'), $backend)); - $this->redirectNow('monitoring/config'); - } else { - $this->render('show-configuration'); - return; + try { + $configForm->remove($backendName); + } catch (InvalidArgumentException $e) { + Notification::error($e->getMessage()); + return; + } + + if ($configForm->save()) { + Notification::success(sprintf(t('Backend "%s" successfully removed.'), $backendName)); + } else { + return false; + } } - } + )); + $form->setRedirectUrl('monitoring/config'); + $form->handleRequest(); $this->view->form = $form; } @@ -187,34 +143,6 @@ class Monitoring_ConfigController extends ModuleActionController $this->view->form = $form; } - /** - * Write configuration to an ini file - * - * @param Zend_Config $config The configuration to write - * @param string $file The config file to write to - * - * @return bool Whether the configuration was written or not - */ - protected function writeConfiguration($config, $file = null) - { - if (is_array($config)) { - $config = new Zend_Config($config); - } - $target = $this->Config($file)->getConfigFile(); - $writer = new PreservingIniWriter(array('filename' => $target, 'config' => $config)); - - try { - $writer->write(); - } catch (Exception $exc) { - $this->view->exceptionMessage = $exc->getMessage(); - $this->view->iniConfigurationString = $writer->render(); - $this->view->file = $target; - return false; - } - - return true; - } - /** * Display a form to adjust security relevant settings */ diff --git a/modules/monitoring/application/forms/Config/BackendConfigForm.php b/modules/monitoring/application/forms/Config/BackendConfigForm.php new file mode 100644 index 000000000..84f68b57e --- /dev/null +++ b/modules/monitoring/application/forms/Config/BackendConfigForm.php @@ -0,0 +1,244 @@ +setName('form_config_monitoring_backends'); + $this->setSubmitLabel(t('Save Changes')); + } + + /** + * Set the resource configuration to use + * + * @param Config $resources The resource configuration + * + * @return self + * + * @throws ConfigurationError In case there are no valid monitoring backend resources + */ + public function setResourceConfig(Config $resourceConfig) + { + $resources = array(); + foreach ($resourceConfig as $name => $resource) { + if ($resource->type === 'db' || $resource->type === 'statusdat' || $resource->type === 'livestatus') { + $resources[$resource->type === 'db' ? 'ido' : strtolower($resource->type)][] = $name; + } + } + + if (empty($resources)) { + throw new ConfigurationError(t('Could not find any valid monitoring backend resources')); + } + + $this->resources = $resources; + return $this; + } + + /** + * Add a particular monitoring 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('Monitoring backend name missing')); + } elseif ($this->config->get($name) !== null) { + throw new InvalidArgumentException(t('Monitoring backend already exists')); + } + + unset($values['name']); + $this->config->{$name} = $values; + return $this; + } + + /** + * Edit a particular monitoring 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 monitoring backend name missing')); + } elseif (! ($newName = isset($values['name']) ? $values['name'] : '')) { + throw new InvalidArgumentException(t('New monitoring backend name missing')); + } elseif (($backendConfig = $this->config->get($name)) === null) { + throw new InvalidArgumentException(t('Unknown monitoring backend provided')); + } + + unset($values['name']); + unset($this->config->{$name}); + $this->config->{$newName} = $values; + return $this->config->{$newName}; + } + + /** + * Remove the given monitoring 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('Monitoring backend name missing')); + } elseif (($backendConfig = $this->config->get($name)) === null) { + throw new InvalidArgumentException(t('Unknown monitoring backend provided')); + } + + unset($this->config->{$name}); + return $backendConfig; + } + + /** + * Add or edit a monitoring backend and save the configuration + * + * @see Form::onSuccess() + */ + public function onSuccess(Request $request) + { + $monitoringBackend = $request->getQuery('backend'); + try { + if ($monitoringBackend === null) { // create new backend + $this->add($this->getValues()); + $message = t('Monitoring backend "%s" has been successfully created'); + } else { // edit existing backend + $this->edit($monitoringBackend, $this->getValues()); + $message = t('Monitoring 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 a monitoring backend is being edited + * + * @see Form::onRequest() + * + * @throws ConfigurationError In case the backend name is missing in the request or is invalid + */ + public function onRequest(Request $request) + { + $monitoringBackend = $request->getQuery('backend'); + if ($monitoringBackend !== null) { + if ($monitoringBackend === '') { + throw new ConfigurationError(t('Monitoring backend name missing')); + } elseif (false === isset($this->config->{$monitoringBackend})) { + throw new ConfigurationError(t('Unknown monitoring backend provided')); + } + + $backendConfig = $this->config->{$monitoringBackend}->toArray(); + $backendConfig['name'] = $monitoringBackend; + $this->populate($backendConfig); + } + } + + /** + * @see Form::createElements() + */ + public function createElements(array $formData) + { + $resourceType = isset($formData['type']) ? $formData['type'] : key($this->resources); + + $resourceTypes = array(); + if ($resourceType === 'ido' || array_key_exists('ido', $this->resources)) { + $resourceTypes['ido'] = 'IDO Backend'; + } + if ($resourceType === 'statusdat' || array_key_exists('statusdat', $this->resources)) { + $resourceTypes['statusdat'] = 'Status.dat'; + } + if ($resourceType === 'livestatus' || array_key_exists('livestatus', $this->resources)) { + $resourceTypes['livestatus'] = 'Livestatus'; + } + + $this->addElement( + 'checkbox', + 'disabled', + array( + 'required' => true, + 'label' => t('Disable This Backend') + ) + ); + $this->addElement( + 'text', + 'name', + array( + 'required' => true, + 'label' => t('Backend Name'), + 'description' => t('The identifier of this backend') + ) + ); + $this->addElement( + 'select', + 'type', + array( + 'required' => true, + 'autosubmit' => true, + 'label' => t('Backend Type'), + 'description' => t('The data source used for retrieving monitoring information'), + 'multiOptions' => $resourceTypes, + 'value' => $resourceType + ) + ); + $this->addElement( + 'select', + 'resource', + array( + 'required' => true, + 'label' => t('Resource'), + 'description' => t('The resource to use'), + 'multiOptions' => $this->resources[$resourceType] + ) + ); + + return $this; + } +} diff --git a/modules/monitoring/application/forms/Config/BackendForm.php b/modules/monitoring/application/forms/Config/BackendForm.php deleted file mode 100644 index f74c9bbaf..000000000 --- a/modules/monitoring/application/forms/Config/BackendForm.php +++ /dev/null @@ -1,125 +0,0 @@ -setName('form_config_monitoring_backends'); - $this->setSubmitLabel(t('Save Changes')); - } - - /** - * @see Form::createElements() - */ - public function createElements(array $formData) - { - return array( - $this->createElement( - 'text', - 'name', - array( - 'required' => true, - 'label' => t('Backend Name'), - 'helptext' => t('The identifier of this backend') - ) - ), - $this->createElement( - 'select', - 'type', - array( - 'required' => true, - 'class' => 'autosubmit', - 'label' => t('Backend Type'), - 'helptext' => t('The data source used for retrieving monitoring information'), - 'multiOptions' => array( - 'ido' => 'IDO Backend', - 'statusdat' => 'Status.dat', - 'livestatus' => 'Livestatus' - ) - ) - ), - $this->createElement( - 'select', - 'resource', - array( - 'required' => true, - 'label' => t('Resource'), - 'helptext' => t('The resource to use'), - 'multiOptions' => $this->getResourcesByType( - false === isset($formData['type']) || $formData['type'] === 'ido' ? 'db' : $formData['type'] - ) - ) - ), - $this->createElement( - 'checkbox', - 'disabled', - array( - 'required' => true, - 'label' => t('Disable This Backend') - ) - ) - ); - } - - /** - * Return the backend 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']; - - if ($values['disabled'] == '0') { - unset($values['disabled']); - } - - 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); - } - - /** - * Return a list of all resources of the given type ready to be used as content for a select input - * - * @param string $type The type of resources to return - * - * @return array - */ - protected function getResourcesByType($type) - { - $backends = array(); - foreach (array_keys(ResourceFactory::getResourceConfigs($type)->toArray()) as $name) { - $backends[$name] = $name; - } - - return $backends; - } -} diff --git a/modules/monitoring/application/views/scripts/config/index.phtml b/modules/monitoring/application/views/scripts/config/index.phtml index 41d2748d5..34f47a0b4 100644 --- a/modules/monitoring/application/views/scripts/config/index.phtml +++ b/modules/monitoring/application/views/scripts/config/index.phtml @@ -1,99 +1,70 @@ -{$element}) && - get_class($this->{$element}) === 'Icinga\Exception\NotReadableError') { - $fileNotReadable[$element] = $this->{$element}->getMessage(); - } else { - $fileNotReadable[$element] = false; - } -} -?> -
- tabs->render($this); ?> +
- -

Monitoring Backends

- - messageBox)): ?> - messageBox->render() ?> - - -

- - icon('create.png'); ?> Create New Monitoring Backend - -

- - - - - - - - backends as $backendName => $config): ?> - $backendName)); - $editUrl = Url::fromPath('/monitoring/config/editbackend', array('backend' => $backendName)); - ?> - - - - - - -
Monitoring BackendRemove
- icon('edit.png'); ?> escape($backendName); ?> - (Type: escape($config['type'] === 'ido' ? 'IDO' : ucfirst($config['type'])); ?>) - - icon('remove.png'); ?> -
- -

- escape($fileNotReadable['backends']) ?> -

- - - -

Monitoring Instances

- -

- - icon('create.png'); ?> Create New Instance - -

- - - - - - - - instances as $instanceName => $config): ?> - $instanceName)); - $editUrl = Url::fromPath('/monitoring/config/editinstance', array('instance' => $instanceName)); - ?> - - - - - - -
InstanceRemove
- icon('edit.png'); ?> escape($instanceName); ?> - (Type: ) - - icon('remove.png'); ?> -
- -

- escape($fileNotReadable['instances']) ?> -

- -
+

Monitoring Backends

+

+ + icon('create.png'); ?> translate('Create New Monitoring Backend'); ?> + +

+ + + + + + +backendsConfig as $backendName => $config): ?> + + + + + + +
translate('Monitoring Backend'); ?>translate('Remove'); ?>
+ + icon('edit.png'); ?> escape($backendName); ?> + + (translate('Type: %s'), + $this->escape($config->type === 'ido' ? 'IDO' : ucfirst($config->type)) + ); ?>) + + + icon('remove.png'); ?> + +
+

Monitoring Instances

+

+ + icon('create.png'); ?> translate('Create New Instance'); ?> + +

+ + + + + + +instancesConfig as $instanceName => $config): ?> + + + + + + +
translate('Instance'); ?>translate('Remove'); ?>
+ + icon('edit.png'); ?> escape($instanceName); ?> + + (translate('Type: %s'), + $config->host !== null ? $this->translate('Remote') : $this->translate('Local') + ); ?>) + + + icon('remove.png'); ?> + +
+ \ No newline at end of file From 8846f17ae133b5d53d58dcb686d3f88cba7dbfde Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Fri, 5 Sep 2014 09:16:09 +0200 Subject: [PATCH 04/44] Make it possible to disable form identification refs #5525 --- library/Icinga/Web/Form.php | 53 +++++++++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 8 deletions(-) diff --git a/library/Icinga/Web/Form.php b/library/Icinga/Web/Form.php index 13ed535e3..4d294dd85 100644 --- a/library/Icinga/Web/Form.php +++ b/library/Icinga/Web/Form.php @@ -67,6 +67,13 @@ class Form extends Zend_Form */ protected $tokenElementName = 'CSRFToken'; + /** + * Whether this form should add a UID element being used to distinct different forms posting to the same action + * + * @var bool + */ + protected $uidDisabled = false; + /** * Name of the form identification element * @@ -236,6 +243,34 @@ class Form extends Zend_Form return $this->tokenElementName; } + /** + * Disable form identification and remove its field if already added + * + * @param bool $disabled Set true in order to disable identification for this form, otherwise false + * + * @return self + */ + public function setUidDisabled($disabled = true) + { + $this->uidDisabled = (bool) $disabled; + + if ($disabled && $this->getElement($this->uidElementName) !== null) { + $this->removeElement($this->uidElementName); + } + + return $this; + } + + /** + * Return whether identification is disabled for this form + * + * @return bool + */ + public function getUidDisabled() + { + return $this->uidDisabled; + } + /** * Set the name to use for the form identification element * @@ -398,14 +433,16 @@ class Form extends Zend_Form */ public function addFormIdentification() { - $this->addElement( - 'hidden', - $this->uidElementName, - array( - 'ignore' => true, - 'value' => $this->getName() - ) - ); + if (false === $this->uidDisabled && $this->getElement($this->uidElementName) === null) { + $this->addElement( + 'hidden', + $this->uidElementName, + array( + 'ignore' => true, + 'value' => $this->getName() + ) + ); + } return $this; } From d021747bdea87aa281ecaa595989dafaf2aea257 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Fri, 5 Sep 2014 09:17:09 +0200 Subject: [PATCH 05/44] Fix form widgets refs #5525 --- library/Icinga/Web/Widget/SortBox.php | 6 +++--- .../library/Monitoring/Web/Widget/TimelineIntervalBox.php | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/library/Icinga/Web/Widget/SortBox.php b/library/Icinga/Web/Widget/SortBox.php index 557469966..42e7110cc 100644 --- a/library/Icinga/Web/Widget/SortBox.php +++ b/library/Icinga/Web/Widget/SortBox.php @@ -119,15 +119,15 @@ class SortBox extends AbstractWidget 'label' => 'Sort By', 'multiOptions' => $this->sortFields, 'style' => 'width: 12em', - 'class' => 'autosubmit', + 'autosubmit' => true )); $form->addElement('select', 'dir', array( 'multiOptions' => array( 'asc' => 'Asc', 'desc' => 'Desc', ), - 'style' => 'width: 5em', - 'class' => 'autosubmit' + 'style' => 'width: 5em', + 'autosubmit' => true )); $sort = $form->getElement('sort')->setDecorators(array('ViewHelper')); $dir = $form->getElement('dir')->setDecorators(array('ViewHelper')); diff --git a/modules/monitoring/library/Monitoring/Web/Widget/TimelineIntervalBox.php b/modules/monitoring/library/Monitoring/Web/Widget/TimelineIntervalBox.php index 4cab3517d..4d6dbdad5 100644 --- a/modules/monitoring/library/Monitoring/Web/Widget/TimelineIntervalBox.php +++ b/modules/monitoring/library/Monitoring/Web/Widget/TimelineIntervalBox.php @@ -84,6 +84,7 @@ class TimelineIntervalBox extends AbstractWidget $form = new Form(); $form->setAttrib('class', 'inline'); $form->setMethod('GET'); + $form->setUidDisabled(); $form->setTokenDisabled(); $form->setName($this->name); $form->addElement( @@ -92,7 +93,7 @@ class TimelineIntervalBox extends AbstractWidget array( 'label' => 'Timeline Interval', 'multiOptions' => $this->values, - 'class' => 'autosubmit' + 'autosubmit' => true ) ); From 7d212658bce4f51df8f74002b171af7f7467f824 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Fri, 5 Sep 2014 09:17:54 +0200 Subject: [PATCH 06/44] Fix "Use statement with non compound name..." in TimelineController --- .../application/controllers/TimelineController.php | 7 +++---- .../monitoring/library/Monitoring/Timeline/TimeLine.php | 1 - 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/modules/monitoring/application/controllers/TimelineController.php b/modules/monitoring/application/controllers/TimelineController.php index 2f9b1339d..a950c92f7 100644 --- a/modules/monitoring/application/controllers/TimelineController.php +++ b/modules/monitoring/application/controllers/TimelineController.php @@ -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; @@ -13,7 +13,6 @@ use Icinga\Module\Monitoring\Controller; use Icinga\Module\Monitoring\Timeline\TimeLine; use Icinga\Module\Monitoring\Timeline\TimeRange; use Icinga\Module\Monitoring\Web\Widget\TimelineIntervalBox; -use Icinga\Module\Monitoring\DataView\EventHistory as EventHistoryView; class Monitoring_TimelineController extends Controller { diff --git a/modules/monitoring/library/Monitoring/Timeline/TimeLine.php b/modules/monitoring/library/Monitoring/Timeline/TimeLine.php index be3820e19..3a795df32 100644 --- a/modules/monitoring/library/Monitoring/Timeline/TimeLine.php +++ b/modules/monitoring/library/Monitoring/Timeline/TimeLine.php @@ -11,7 +11,6 @@ use Icinga\Exception\IcingaException; use IteratorAggregate; use Icinga\Data\Filter\Filter; use Icinga\Web\Hook; -use Icinga\Web\Session; use Icinga\Web\Session\SessionNamespace; use Icinga\Module\Monitoring\DataView\DataView; From fc72ddfbc8fd3ac5adfa2783847681b8f31b0a3a Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Fri, 5 Sep 2014 10:21:24 +0200 Subject: [PATCH 07/44] Adjust Preferences/GeneralForm to use handleRequest() &. Co. refs #5525 --- .../controllers/PreferenceController.php | 41 ++-- application/forms/Preference/GeneralForm.php | 171 -------------- application/forms/PreferenceForm.php | 211 ++++++++++++++++++ .../views/scripts/preference/index.phtml | 6 +- .../Controller/BasePreferenceController.php | 28 --- library/Icinga/Web/Form.php | 5 +- 6 files changed, 233 insertions(+), 229 deletions(-) delete mode 100644 application/forms/Preference/GeneralForm.php create mode 100644 application/forms/PreferenceForm.php diff --git a/application/controllers/PreferenceController.php b/application/controllers/PreferenceController.php index 0eb45dca0..bd76b2466 100644 --- a/application/controllers/PreferenceController.php +++ b/application/controllers/PreferenceController.php @@ -3,10 +3,12 @@ // {{{ICINGA_LICENSE_HEADER}}} use Icinga\Web\Controller\BasePreferenceController; -use Icinga\Web\Widget\Tab; use Icinga\Web\Url; -use Icinga\Form\Preference\GeneralForm; -use Icinga\Web\Notification; +use Icinga\Web\Widget\Tab; +use Icinga\Application\Config; +use Icinga\Form\PreferenceForm; +use Icinga\Exception\ConfigurationError; +use Icinga\User\Preferences\PreferencesStore; /** * Application wide preference controller for user preferences @@ -33,33 +35,22 @@ class PreferenceController extends BasePreferenceController } /** - * General settings for date and time + * Show form to adjust user preferences */ public function indexAction() { - $this->getTabs()->activate('general'); - - $form = new GeneralForm(); - $request = $this->getRequest(); - if ($request->isPost()) { - if ($form->isValid($request->getPost())) { - try { - $this->savePreferences($form->getPreferences()->toArray()); - Notification::success($this->translate('Preferences updated successfully')); - $this->redirectNow('preference'); - } catch (Exception $e) { - Notification::error( - sprintf( - $this->translate('Failed to persist preferences. (%s)'), - $e->getMessage() - ) - ); - } - } - } else { - $form->setPreferences($request->getUser()->getPreferences()); + $storeConfig = Config::app()->preferences; + if ($storeConfig === null) { + throw new ConfigurationError(t('You need to configure how to store preferences first.')); } + $user = $this->getRequest()->getUser(); + $form = new PreferenceForm(); + $form->setPreferences($user->getPreferences()); + $form->setStore(PreferencesStore::create($storeConfig, $user)); + $form->handleRequest(); + $this->view->form = $form; + $this->getTabs()->activate('general'); } } diff --git a/application/forms/Preference/GeneralForm.php b/application/forms/Preference/GeneralForm.php deleted file mode 100644 index b9ce5e9e2..000000000 --- a/application/forms/Preference/GeneralForm.php +++ /dev/null @@ -1,171 +0,0 @@ -setName('form_config_preferences'); - $this->setSubmitLabel(t('Save Changes')); - } - - /** - * Add a select field for setting the user's language - * - * Possible values are determined by Translator::getAvailableLocaleCodes. - * Also, a 'use browser language' checkbox is added in order to allow a user to discard his setting - * - * @param array $formData The data sent by the user - */ - protected function getLanguageElements(array $formData) - { - $languages = array(); - foreach (Translator::getAvailableLocaleCodes() as $language) { - $languages[$language] = $language; - } - - $useBrowserLanguage = isset($formData['browser_language']) ? $formData['browser_language'] == 1 : true; - $selectOptions = array( - 'label' => t('Your Current Language'), - 'required' => false === $useBrowserLanguage, - 'multiOptions' => $languages, - 'helptext' => t('Use the following language to display texts and messages'), - 'value' => substr(setlocale(LC_ALL, 0), 0, 5) - ); - if ($useBrowserLanguage) { - $selectOptions['disabled'] = 'disabled'; - } - - return array( - $this->createElement( - 'checkbox', - 'browser_language', - array( - 'required' => true, - 'class' => 'autosubmit', - 'label' => t('Use your browser\'s language suggestions'), - 'value' => $useBrowserLanguage - ) - ), - $this->createElement('select', 'language', $selectOptions) - ); - } - - /** - * Add a select field for setting the user's timezone - * - * Possible values are determined by DateTimeZone::listIdentifiers. - * Also, a 'use local timezone' checkbox is added in order to allow a user to discard his overwritten setting - * - * @param array $formData The data sent by the user - */ - protected function getTimezoneElements(array $formData) - { - $tzList = array(); - foreach (DateTimeZone::listIdentifiers() as $tz) { - $tzList[$tz] = $tz; - } - - $useLocalTimezone = isset($formData['local_timezone']) ? $formData['local_timezone'] == 1 : true; - $selectOptions = array( - 'label' => 'Your Current Timezone', - 'required' => false === $useLocalTimezone, - 'multiOptions' => $tzList, - 'helptext' => t('Use the following timezone for dates and times'), - 'value' => date_default_timezone_get() - ); - if ($useLocalTimezone) { - $selectOptions['disabled'] = 'disabled'; - } - - return array( - $this->createElement( - 'checkbox', - 'local_timezone', - array( - 'required' => true, - 'class' => 'autosubmit', - 'label' => t('Use your local timezone'), - 'value' => $useLocalTimezone, - ) - ), - $this->createElement('select', 'timezone', $selectOptions) - ); - } - - /** - * @see Form::createElements() - */ - public function createElements(array $formData) - { - $elements = array_merge($this->getLanguageElements($formData), $this->getTimezoneElements($formData)); - $elements[] = $this->createElement( - 'checkbox', - 'show_benchmark', - array( - 'label' => t('Use benchmark') - ) - ); - - return $elements; - } - - /** - * Populate the form with the given preferences - * - * @param Preferences $preferences The preferences to populate the form with - * - * @return self - */ - public function setPreferences(Preferences $preferences) - { - $defaults = array( - 'browser_language' => $preferences->get('app.language') === null, - 'local_timezone' => $preferences->get('app.timezone') === null - ); - - if ($preferences->get('app.language') !== null) { - $defaults['language'] = $preferences->get('app.language'); - } - if ($preferences->get('app.timezone') !== null) { - $defaults['timezone'] = $preferences->get('app.timezone'); - } - if ($preferences->get('app.show_benchmark')) { - $defaults['show_benchmark'] = $preferences->get('app.show_benchmark'); - } - - $this->setDefaults($defaults); - return $this; - } - - /** - * Return the configured preferences - * - * @return Preferences - */ - public function getPreferences() - { - $values = $this->getValues(); - return new Preferences( - array( - 'app.language' => $values['browser_language'] ? null : $values['language'], - 'app.timezone' => $values['local_timezone'] ? null : $values['timezone'], - 'app.show_benchmark' => $values['show_benchmark'] ? $values['show_benchmark'] : null - ) - ); - } -} diff --git a/application/forms/PreferenceForm.php b/application/forms/PreferenceForm.php new file mode 100644 index 000000000..c156cca12 --- /dev/null +++ b/application/forms/PreferenceForm.php @@ -0,0 +1,211 @@ +setName('form_config_preferences'); + $this->setSubmitLabel(t('Save Changes')); + } + + /** + * Set preferences to work with + * + * @param Preferences $preferences The preferences to work with + * + * @return self + */ + public function setPreferences(Preferences $preferences) + { + $this->preferences = $preferences; + return $this; + } + + /** + * Set the preference store to use + * + * @param PreferencesStore $store The preference store to use + * + * @return self + */ + public function setStore(PreferencesStore $store) + { + $this->store = $store; + } + + /** + * Persist preferences + * + * @return self + */ + public function save() + { + $this->store->load(); // Necessary for patching existing preferences + $this->store->save($this->preferences); + return $this; + } + + /** + * Adjust preferences and persist them + * + * @see Form::onSuccess() + */ + public function onSuccess(Request $request) + { + $webPreferences = $this->preferences->get('icingaweb', array()); + foreach ($this->getValues() as $key => $value) { + if ($value === null) { + if (isset($webPreferences[$key])) { + unset($webPreferences[$key]); + } + } else { + $webPreferences[$key] = $value; + } + } + $this->preferences->icingaweb = $webPreferences; + + // TODO: Is this even necessary in case the session is written on response? + $session = Session::getSession(); + $session->user->setPreferences($this->preferences); + $session->write(); + + try { + $this->save(); + Notification::success(t('Preferences successfully saved')); + } catch (Exception $e) { + Notification::error($e->getMessage()); + } + } + + /** + * Populate preferences + * + * @see Form::onRequest() + */ + public function onRequest(Request $request) + { + $values = $this->preferences->get('icingaweb', array()); + $values['browser_language'] = false === isset($values['language']); + $values['local_timezone'] = false === isset($values['timezone']); + $this->populate($values); + } + + /** + * @see Form::createElements() + */ + public function createElements(array $formData) + { + $languages = array(); + foreach (Translator::getAvailableLocaleCodes() as $language) { + $languages[$language] = $language; + } + + $tzList = array(); + foreach (DateTimeZone::listIdentifiers() as $tz) { + $tzList[$tz] = $tz; + } + + $this->addElement( + 'checkbox', + 'browser_language', + array( + 'ignore' => true, + 'required' => true, + 'autosubmit' => true, + 'value' => true, + 'label' => t('Use your browser\'s language suggestions') + ) + ); + + $useBrowserLanguage = isset($formData['browser_language']) ? $formData['browser_language'] == 1 : true; + $languageSelection = $this->createElement( + 'select', + 'language', + array( + 'required' => false === $useBrowserLanguage, + 'label' => t('Your Current Language'), + 'description' => t('Use the following language to display texts and messages'), + 'multiOptions' => $languages, + 'value' => substr(setlocale(LC_ALL, 0), 0, 5) + ) + ); + if ($useBrowserLanguage) { + $languageSelection->setAttrib('disabled', 'disabled'); + } + $this->addElement($languageSelection); + + $this->addElement( + 'checkbox', + 'local_timezone', + array( + 'ignore' => true, + 'required' => true, + 'autosubmit' => true, + 'value' => true, + 'label' => t('Use your local timezone') + ) + ); + + $useLocalTimezone = isset($formData['local_timezone']) ? $formData['local_timezone'] == 1 : true; + $timezoneSelection = $this->createElement( + 'select', + 'timezone', + array( + 'required' => false === $useLocalTimezone, + 'label' => t('Your Current Timezone'), + 'description' => t('Use the following timezone for dates and times'), + 'multiOptions' => $tzList, + 'value' => date_default_timezone_get() + ) + ); + if ($useLocalTimezone) { + $timezoneSelection->setAttrib('disabled', 'disabled'); + } + $this->addElement($timezoneSelection); + + $this->addElement( + 'checkbox', + 'show_benchmark', + array( + 'required' => true, + 'label' => t('Use benchmark') + ) + ); + + return $this; + } +} diff --git a/application/views/scripts/preference/index.phtml b/application/views/scripts/preference/index.phtml index 256f8623c..163381531 100644 --- a/application/views/scripts/preference/index.phtml +++ b/application/views/scripts/preference/index.phtml @@ -1,7 +1,7 @@
-tabs->render($this); ?> +
-form ?> -
+ + \ No newline at end of file diff --git a/library/Icinga/Web/Controller/BasePreferenceController.php b/library/Icinga/Web/Controller/BasePreferenceController.php index a83b8e6c0..f7d45aa5f 100644 --- a/library/Icinga/Web/Controller/BasePreferenceController.php +++ b/library/Icinga/Web/Controller/BasePreferenceController.php @@ -4,11 +4,6 @@ namespace Icinga\Web\Controller; -use Icinga\Application\Config as IcingaConfig; -use Icinga\Exception\ConfigurationError; -use Icinga\Web\Session; -use Icinga\User\Preferences\PreferencesStore; - /** * Base class for Preference Controllers * @@ -42,27 +37,4 @@ class BasePreferenceController extends ActionController parent::init(); $this->view->tabs = ControllerTabCollector::collectControllerTabs('PreferenceController'); } - - protected function savePreferences(array $preferences) - { - $session = Session::getSession(); - $currentPreferences = $session->user->getPreferences(); - foreach ($preferences as $key => $value) { - if ($value === null) { - $currentPreferences->remove($key); - } else { - $currentPreferences->{$key} = $value; - } - } - $session->write(); - - if (($preferencesConfig = IcingaConfig::app()->preferences) === null) { - throw new ConfigurationError( - 'Cannot save preferences changes since you\'ve not configured a preferences backend' - ); - } - $store = PreferencesStore::create($preferencesConfig, $session->user); - $store->load(); // Necessary for patching existing preferences - $store->save($currentPreferences); - } } diff --git a/library/Icinga/Web/Form.php b/library/Icinga/Web/Form.php index 4d294dd85..8f3a47f64 100644 --- a/library/Icinga/Web/Form.php +++ b/library/Icinga/Web/Form.php @@ -438,8 +438,9 @@ class Form extends Zend_Form 'hidden', $this->uidElementName, array( - 'ignore' => true, - 'value' => $this->getName() + 'ignore' => true, + 'value' => $this->getName(), + 'decorators' => array('ViewHelper') ) ); } From 7215e273f6ef94015bfcc77fe9c494bde5cca392 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Mon, 8 Sep 2014 09:10:59 +0200 Subject: [PATCH 08/44] Fix AddUrlForm::createElements() not returning self --- application/forms/Dashboard/AddUrlForm.php | 31 +++++++++++----------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/application/forms/Dashboard/AddUrlForm.php b/application/forms/Dashboard/AddUrlForm.php index 67452a84f..51130bb11 100644 --- a/application/forms/Dashboard/AddUrlForm.php +++ b/application/forms/Dashboard/AddUrlForm.php @@ -27,15 +27,13 @@ class AddUrlForm extends Form */ public function createElements(array $formData) { - $elements = array( - $this->createElement( - 'text', - 'url', - array( - 'required' => true, - 'label' => t('Url'), - 'helptext' => t('The url being loaded in the dashlet') - ) + $this->addElement( + 'text', + 'url', + array( + 'required' => true, + 'label' => t('Url'), + 'helptext' => t('The url being loaded in the dashlet') ) ); @@ -44,7 +42,7 @@ class AddUrlForm extends Form ((isset($formData['create_new_pane']) && $formData['create_new_pane'] != false) && (false === isset($formData['use_existing_dashboard']) || $formData['use_existing_dashboard'] != true)) ) { - $elements[] = $this->createElement( + $this->addElement( 'text', 'pane', array( @@ -53,7 +51,7 @@ class AddUrlForm extends Form 'style' => 'display: inline-block' ) ); - $elements[] = $this->createElement( // Prevent the button from being displayed again on validation errors + $this->addElement( // Prevent the button from being displayed again on validation errors 'hidden', 'create_new_pane', array( @@ -61,7 +59,7 @@ class AddUrlForm extends Form ) ); if (false === empty($paneSelectionValues)) { - $elements[] = $this->createElement( + $this->addElement( 'submit', 'use_existing_dashboard', array( @@ -72,7 +70,7 @@ class AddUrlForm extends Form ); } } else { - $elements[] = $this->createElement( + $this->addElement( 'select', 'pane', array( @@ -82,7 +80,7 @@ class AddUrlForm extends Form 'multiOptions' => $paneSelectionValues ) ); - $elements[] = $this->createElement( + $this->addElement( 'submit', 'create_new_pane', array( @@ -93,7 +91,7 @@ class AddUrlForm extends Form ); } - $elements[] = $this->createElement( + $this->addElement( 'text', 'component', array( @@ -102,7 +100,8 @@ class AddUrlForm extends Form 'helptext' => t('The title for the dashlet') ) ); - return $elements; + + return $this; } /** From 930e6e7d71bda7aa4b32464c307df2594efb0060 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Mon, 8 Sep 2014 09:24:53 +0200 Subject: [PATCH 09/44] We shouldn't require Form::createElements() to return self refs #5525 --- application/forms/Authentication/LoginForm.php | 2 -- .../forms/Config/Authentication/AutologinBackendForm.php | 2 -- application/forms/Config/Authentication/DbBackendForm.php | 2 -- .../forms/Config/Authentication/LdapBackendForm.php | 2 -- .../forms/Config/AuthenticationBackendConfigForm.php | 2 -- .../forms/Config/General/ApplicationConfigForm.php | 2 -- application/forms/Config/General/LoggingConfigForm.php | 2 -- application/forms/Config/GeneralConfigForm.php | 2 -- application/forms/Config/Resource/DbResourceForm.php | 2 -- application/forms/Config/Resource/FileResourceForm.php | 2 -- application/forms/Config/Resource/LdapResourceForm.php | 2 -- .../forms/Config/Resource/LivestatusResourceForm.php | 2 -- .../forms/Config/Resource/StatusdatResourceForm.php | 2 -- application/forms/Config/ResourceConfigForm.php | 2 -- application/forms/Dashboard/AddUrlForm.php | 2 -- application/forms/PreferenceForm.php | 2 -- library/Icinga/Web/Form.php | 8 +++----- .../application/forms/Config/BackendConfigForm.php | 2 -- .../forms/Config/Instance/LocalInstanceForm.php | 2 -- .../forms/Config/Instance/RemoteInstanceForm.php | 2 -- .../application/forms/Config/InstanceConfigForm.php | 2 -- .../application/forms/Config/SecurityConfigForm.php | 2 -- 22 files changed, 3 insertions(+), 47 deletions(-) diff --git a/application/forms/Authentication/LoginForm.php b/application/forms/Authentication/LoginForm.php index 0d9b8dedc..d878475f2 100644 --- a/application/forms/Authentication/LoginForm.php +++ b/application/forms/Authentication/LoginForm.php @@ -53,7 +53,5 @@ class LoginForm extends Form 'value' => Url::fromRequest()->getParam('redirect') ) ); - - return $this; } } diff --git a/application/forms/Config/Authentication/AutologinBackendForm.php b/application/forms/Config/Authentication/AutologinBackendForm.php index 4f4df73e3..d4e0547a9 100644 --- a/application/forms/Config/Authentication/AutologinBackendForm.php +++ b/application/forms/Config/Authentication/AutologinBackendForm.php @@ -69,8 +69,6 @@ class AutologinBackendForm extends Form 'value' => 'autologin' ) ); - - return $this; } /** diff --git a/application/forms/Config/Authentication/DbBackendForm.php b/application/forms/Config/Authentication/DbBackendForm.php index 23335f8fa..960a6d07c 100644 --- a/application/forms/Config/Authentication/DbBackendForm.php +++ b/application/forms/Config/Authentication/DbBackendForm.php @@ -77,8 +77,6 @@ class DbBackendForm extends Form 'value' => 'db' ) ); - - return $this; } /** diff --git a/application/forms/Config/Authentication/LdapBackendForm.php b/application/forms/Config/Authentication/LdapBackendForm.php index 9db773708..4e3172ad2 100644 --- a/application/forms/Config/Authentication/LdapBackendForm.php +++ b/application/forms/Config/Authentication/LdapBackendForm.php @@ -96,8 +96,6 @@ class LdapBackendForm extends Form 'value' => 'ldap' ) ); - - return $this; } /** diff --git a/application/forms/Config/AuthenticationBackendConfigForm.php b/application/forms/Config/AuthenticationBackendConfigForm.php index 9068ed25a..e81382cd4 100644 --- a/application/forms/Config/AuthenticationBackendConfigForm.php +++ b/application/forms/Config/AuthenticationBackendConfigForm.php @@ -318,7 +318,5 @@ class AuthenticationBackendConfigForm extends ConfigForm } $this->addElements($this->getBackendForm($backendType)->createElements($formData)->getElements()); - - return $this; } } diff --git a/application/forms/Config/General/ApplicationConfigForm.php b/application/forms/Config/General/ApplicationConfigForm.php index fda695886..5f592eefc 100644 --- a/application/forms/Config/General/ApplicationConfigForm.php +++ b/application/forms/Config/General/ApplicationConfigForm.php @@ -112,7 +112,5 @@ class ApplicationConfigForm extends Form ) ); } - - return $this; } } diff --git a/application/forms/Config/General/LoggingConfigForm.php b/application/forms/Config/General/LoggingConfigForm.php index 135dd9e28..33e182b5d 100644 --- a/application/forms/Config/General/LoggingConfigForm.php +++ b/application/forms/Config/General/LoggingConfigForm.php @@ -102,8 +102,6 @@ class LoggingConfigForm extends Form ) ); } - - return $this; } /** diff --git a/application/forms/Config/GeneralConfigForm.php b/application/forms/Config/GeneralConfigForm.php index ffb0a7d1c..550fe4cfb 100644 --- a/application/forms/Config/GeneralConfigForm.php +++ b/application/forms/Config/GeneralConfigForm.php @@ -33,8 +33,6 @@ class GeneralConfigForm extends ConfigForm $loggingConfigForm = new LoggingConfigForm(); $this->addElements($appConfigForm->createElements($formData)->getElements()); $this->addElements($loggingConfigForm->createElements($formData)->getElements()); - - return $this; } /** diff --git a/application/forms/Config/Resource/DbResourceForm.php b/application/forms/Config/Resource/DbResourceForm.php index 4fd7297d9..136e9e645 100644 --- a/application/forms/Config/Resource/DbResourceForm.php +++ b/application/forms/Config/Resource/DbResourceForm.php @@ -92,8 +92,6 @@ class DbResourceForm extends Form 'description' => t('The password to use for authentication') ) ); - - return $this; } /** diff --git a/application/forms/Config/Resource/FileResourceForm.php b/application/forms/Config/Resource/FileResourceForm.php index d1d33a749..2654ad949 100644 --- a/application/forms/Config/Resource/FileResourceForm.php +++ b/application/forms/Config/Resource/FileResourceForm.php @@ -44,7 +44,5 @@ class FileResourceForm extends Form 'description' => t('The regular expression by which to identify columns') ) ); - - return $this; } } diff --git a/application/forms/Config/Resource/LdapResourceForm.php b/application/forms/Config/Resource/LdapResourceForm.php index 6196f3a17..752516956 100644 --- a/application/forms/Config/Resource/LdapResourceForm.php +++ b/application/forms/Config/Resource/LdapResourceForm.php @@ -78,8 +78,6 @@ class LdapResourceForm extends Form 'description' => t('The password to use for querying the ldap server') ) ); - - return $this; } /** diff --git a/application/forms/Config/Resource/LivestatusResourceForm.php b/application/forms/Config/Resource/LivestatusResourceForm.php index 92534f220..ad0b382c2 100644 --- a/application/forms/Config/Resource/LivestatusResourceForm.php +++ b/application/forms/Config/Resource/LivestatusResourceForm.php @@ -39,8 +39,6 @@ class LivestatusResourceForm extends Form 'value' => realpath(Icinga::app()->getApplicationDir() . '/../var/rw/livestatus') ) ); - - return $this; } /** diff --git a/application/forms/Config/Resource/StatusdatResourceForm.php b/application/forms/Config/Resource/StatusdatResourceForm.php index f150056d1..15563ff39 100644 --- a/application/forms/Config/Resource/StatusdatResourceForm.php +++ b/application/forms/Config/Resource/StatusdatResourceForm.php @@ -48,7 +48,5 @@ class StatusdatResourceForm extends Form 'validators' => array(new ReadablePathValidator()) ) ); - - return $this; } } diff --git a/application/forms/Config/ResourceConfigForm.php b/application/forms/Config/ResourceConfigForm.php index d9ec4dad3..8e677cf8b 100644 --- a/application/forms/Config/ResourceConfigForm.php +++ b/application/forms/Config/ResourceConfigForm.php @@ -252,7 +252,5 @@ class ResourceConfigForm extends ConfigForm } $this->addElements($this->getResourceForm($resourceType)->createElements($formData)->getElements()); - - return $this; } } diff --git a/application/forms/Dashboard/AddUrlForm.php b/application/forms/Dashboard/AddUrlForm.php index 51130bb11..88195654d 100644 --- a/application/forms/Dashboard/AddUrlForm.php +++ b/application/forms/Dashboard/AddUrlForm.php @@ -100,8 +100,6 @@ class AddUrlForm extends Form 'helptext' => t('The title for the dashlet') ) ); - - return $this; } /** diff --git a/application/forms/PreferenceForm.php b/application/forms/PreferenceForm.php index f01f4e337..cdb6ff288 100644 --- a/application/forms/PreferenceForm.php +++ b/application/forms/PreferenceForm.php @@ -206,8 +206,6 @@ class PreferenceForm extends Form 'label' => t('Use benchmark') ) ); - - return $this; } /** diff --git a/library/Icinga/Web/Form.php b/library/Icinga/Web/Form.php index 8f3a47f64..61d75e3af 100644 --- a/library/Icinga/Web/Form.php +++ b/library/Icinga/Web/Form.php @@ -304,8 +304,8 @@ class Form extends Zend_Form public function create(array $formData = array()) { if (false === $this->created) { - $this->createElements($formData) - ->addFormIdentification() + $this->createElements($formData); + $this->addFormIdentification() ->addCsrfCounterMeasure() ->addSubmitButton(); @@ -327,12 +327,10 @@ class Form extends Zend_Form * Intended to be implemented by concrete form classes. * * @param array $formData The data sent by the user - * - * @return self */ public function createElements(array $formData) { - return $this; + } /** diff --git a/modules/monitoring/application/forms/Config/BackendConfigForm.php b/modules/monitoring/application/forms/Config/BackendConfigForm.php index 84f68b57e..e2cdf210c 100644 --- a/modules/monitoring/application/forms/Config/BackendConfigForm.php +++ b/modules/monitoring/application/forms/Config/BackendConfigForm.php @@ -238,7 +238,5 @@ class BackendConfigForm extends ConfigForm 'multiOptions' => $this->resources[$resourceType] ) ); - - return $this; } } diff --git a/modules/monitoring/application/forms/Config/Instance/LocalInstanceForm.php b/modules/monitoring/application/forms/Config/Instance/LocalInstanceForm.php index 513ba2433..6f0d37e25 100644 --- a/modules/monitoring/application/forms/Config/Instance/LocalInstanceForm.php +++ b/modules/monitoring/application/forms/Config/Instance/LocalInstanceForm.php @@ -31,7 +31,5 @@ class LocalInstanceForm extends Form 'description' => t('The file path where the icinga commandpipe can be found') ) ); - - return $this; } } diff --git a/modules/monitoring/application/forms/Config/Instance/RemoteInstanceForm.php b/modules/monitoring/application/forms/Config/Instance/RemoteInstanceForm.php index 0e78a0aec..36991425b 100644 --- a/modules/monitoring/application/forms/Config/Instance/RemoteInstanceForm.php +++ b/modules/monitoring/application/forms/Config/Instance/RemoteInstanceForm.php @@ -62,7 +62,5 @@ class RemoteInstanceForm extends Form 'description' => t('The file path where the icinga commandpipe can be found') ) ); - - return $this; } } diff --git a/modules/monitoring/application/forms/Config/InstanceConfigForm.php b/modules/monitoring/application/forms/Config/InstanceConfigForm.php index 011284a9a..6f8d04764 100644 --- a/modules/monitoring/application/forms/Config/InstanceConfigForm.php +++ b/modules/monitoring/application/forms/Config/InstanceConfigForm.php @@ -205,7 +205,5 @@ class InstanceConfigForm extends ConfigForm ); $this->addElements($this->getInstanceForm($instanceType)->createElements($formData)->getElements()); - - return $this; } } diff --git a/modules/monitoring/application/forms/Config/SecurityConfigForm.php b/modules/monitoring/application/forms/Config/SecurityConfigForm.php index 33a03328e..a164766cc 100644 --- a/modules/monitoring/application/forms/Config/SecurityConfigForm.php +++ b/modules/monitoring/application/forms/Config/SecurityConfigForm.php @@ -62,7 +62,5 @@ class SecurityConfigForm extends ConfigForm . ' Existance of those custom variables will be shown, but their values will be masked.' ) ); - - return $this; } } From 12b4865559126ce5015025968767e067d9d0aa85 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Mon, 8 Sep 2014 09:42:02 +0200 Subject: [PATCH 10/44] Fix incompatible declaration of Form::setDefaults() PHP with strict standards: Declaration of Icinga\Web\Form::setDefaults() should be compatible with that of Zend_Form::setDefaults() refs #5525 --- library/Icinga/Web/Form.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/Icinga/Web/Form.php b/library/Icinga/Web/Form.php index 61d75e3af..e4b292647 100644 --- a/library/Icinga/Web/Form.php +++ b/library/Icinga/Web/Form.php @@ -467,7 +467,7 @@ class Form extends Zend_Form * * @param array $defaults The values to populate the elements with */ - public function setDefaults(array $defaults) + public function setDefaults($defaults) { $this->create($defaults); return parent::setDefaults($defaults); From e8164c6da02b6119931a43a05600bc49817c8d4c Mon Sep 17 00:00:00 2001 From: Matthias Jentsch Date: Mon, 8 Sep 2014 10:38:02 +0200 Subject: [PATCH 11/44] Show tooltips to describe menu badges --- library/Icinga/Web/Menu/UnhandledHostMenuItemRenderer.php | 3 ++- library/Icinga/Web/Menu/UnhandledServiceMenuItemRenderer.php | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/library/Icinga/Web/Menu/UnhandledHostMenuItemRenderer.php b/library/Icinga/Web/Menu/UnhandledHostMenuItemRenderer.php index b66709422..c7e6036fb 100644 --- a/library/Icinga/Web/Menu/UnhandledHostMenuItemRenderer.php +++ b/library/Icinga/Web/Menu/UnhandledHostMenuItemRenderer.php @@ -22,7 +22,8 @@ class UnhandledHostMenuItemRenderer implements MenuItemRenderer { $badge = ''; if ($statusSummary->hosts_down_unhandled) { $badge = sprintf( - '
%s
', + '
%s
', + t(sprintf('%d unhandled host problems', $statusSummary->hosts_down_unhandled)), $statusSummary->hosts_down_unhandled ); } diff --git a/library/Icinga/Web/Menu/UnhandledServiceMenuItemRenderer.php b/library/Icinga/Web/Menu/UnhandledServiceMenuItemRenderer.php index cdac34c04..b677a4935 100644 --- a/library/Icinga/Web/Menu/UnhandledServiceMenuItemRenderer.php +++ b/library/Icinga/Web/Menu/UnhandledServiceMenuItemRenderer.php @@ -22,7 +22,8 @@ class UnhandledServiceMenuItemRenderer implements MenuItemRenderer { $badge = ''; if ($statusSummary->services_critical_unhandled) { $badge = sprintf( - '
%s
', + '
%s
', + t(sprintf('%d unhandled service problems', $statusSummary->services_critical_unhandled)), $statusSummary->services_critical_unhandled ); } From 2112d45c3cbeca088e7f200e5b6c448d4fef0481 Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Sun, 7 Sep 2014 15:39:58 +0200 Subject: [PATCH 12/44] doc/components.md: obsolete, remove We do not load any component with require.js or similar --- doc/components.md | 130 ---------------------------------------------- 1 file changed, 130 deletions(-) delete mode 100644 doc/components.md diff --git a/doc/components.md b/doc/components.md deleted file mode 100644 index a46afc2eb..000000000 --- a/doc/components.md +++ /dev/null @@ -1,130 +0,0 @@ -# Frontend components - -Frontend components are JavaScript modules that can be required directly through the HTML markup of -your view, to provide additional functionality for the user. Although its best practice to -make all features available without JavaScript, these components can be used to provide a richer -and more comfortable user experience in case JavaScript is available. - -There is a certain set of frontend components which come directly with the Icinga2-Web core application, -but it is also possible to define new components directly in Icinga2-Web modules. - - -## How do components work? - -Components are defined in JavaScript files that provide a set of functionality that will be added to the -targeted HTML node. Icinga2-Web uses [RequireJS](http://requirejs.org) to load -all frontend components, so each frontend component is in fact -[defined exactly like a RequireJS-Module](http://requirejs.org/docs/api.html#define) . - -The important difference to plain RequireJS is, that the loading and execution of these components is -done automatically through the HTML markup. The attribute *data-icinga-component* in a DIV -element will indicate that this element is a container for a frontend component and will trigger -the component loader to create a component instance for this HTML node. The component loader -keeps track of all available components and makes it possible to retrieve this instance when needed. - - -### Component names - -A component name consists of two parts: the namespace and the name of the component itself. The component -is named exactly like its JavaScript file, while the namespace is the name of the Icinga2-Web module that contains -the component. Each Icinga2-Web module can contain its own components in the folder *public/js*. - - / - - -NOTE: The namespace used for modules defined in the Icinga2-Web core application is "app". In opposition to -the modules the core application keeps its modules located in *public/js/icinga/components* -instead of *public/js*. - - -#### Example Names - - -The full name for the component *modules/monitoring/public/js/someComponent.js* in the module "monitoring" would be: - - "monitoring/someComponent" - - -The full component name for the component *public/js/icinga/components/datetime.js* in the Icinga2-Web core application -would: - - "app/datetime" - - -## Creating a component - -As described in the chapters above, components are defined exactly like RequireJS modules, but -with the additional requirement that they must always return a class constructor. The component below will -search all date pickers, set the time format and create a JavaScript date picker when there is no native one -available. - - /** - * Ensures that our date/time controls will work on every browser (natively or javascript based) - */ - define(['jquery', 'datetimepicker'], function($) { - "use strict"; - - var DateTimePicker = function(target) { - $(target).find('.datetime input') - .attr('data-format', 'yyyy-MM-dd hh:mm:ss'); - - $(target).find('.datetime') - .addClass('input-append') - .append('' + - '') - .datetimepicker(); - }; - return DateTimePicker; - }); - - -## Loading a component - -The following code will load the module *datetime*, which will ensure that there is always a datetime-picker -with right time-format available. - -
- -
- -
- -
- - -### Component ids - -When an ID is assigned to the HTML element, it will be used by the component loader to reference this -component. Otherwise an ID in the form "icinga-component-<ID>" will be created and the ID attribute in the -HTML Element will be updated accordingly. - - -### Component "target" - -The div-element with the *data-icinga-component* will be used as the "target" for the loaded component, -which means that the component will perform its actions on this HTML node. - - - -# Retrieving a component - -Sometimes it can be necessary to retrieve the instances of the components itself, for example when they implement -additional functions that can be called. The component loader is available in the Icinga object and can be used -to retrieve component instances using their ID or their full component name. - - -## By component id - - var component = Icinga.components.getById("component-id"); - component.doSomething(); - - -## By full component name - - var components = Icinga.components.getByType("app/datetime"); - // ... do something with every component of the type app/datetime - -## All components - - var components = Icinga.components.getComponents(); - // ... do something with every component From 7386ae5ef5861036e4cdfbcc9b00f17b68c389d2 Mon Sep 17 00:00:00 2001 From: Alexander Fuhr Date: Mon, 8 Sep 2014 11:28:14 +0200 Subject: [PATCH 13/44] Update Module img_ route to get image subfolders --- application/controllers/StaticController.php | 11 +++++++++-- library/Icinga/Application/Modules/Module.php | 8 ++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/application/controllers/StaticController.php b/application/controllers/StaticController.php index fec60a624..edcc57d39 100644 --- a/application/controllers/StaticController.php +++ b/application/controllers/StaticController.php @@ -61,10 +61,17 @@ class StaticController extends ActionController $module = $this->_getParam('module_name'); // TODO: This is more than dangerous, must be fixed!! $file = $this->_getParam('file'); - $basedir = Icinga::app()->getModuleManager()->getModule($module)->getBaseDir(); - $filePath = $basedir . '/public/img/' . $file; + $filePath = realpath($basedir . '/public/img/' . $file); + + if (strpos($filePath, $basedir) === false) { + throw new ActionException(sprintf( + '%s does not exist', + $filePath + ), 404); + } + if (! file_exists($filePath)) { throw new ActionException(sprintf( '%s does not exist', diff --git a/library/Icinga/Application/Modules/Module.php b/library/Icinga/Application/Modules/Module.php index c0c6b1f6f..6d66412e6 100644 --- a/library/Icinga/Application/Modules/Module.php +++ b/library/Icinga/Application/Modules/Module.php @@ -8,6 +8,7 @@ use Exception; use Zend_Config; use Zend_Controller_Router_Route_Abstract; use Zend_Controller_Router_Route as Route; +use Zend_Controller_Router_Route_Regex as RegexRoute; use Icinga\Application\ApplicationBootstrap; use Icinga\Application\Config; use Icinga\Application\Icinga; @@ -821,12 +822,15 @@ class Module ); $router->addRoute( $this->name . '_img', - new Route( - 'img/' . $this->name . '/:file', + new RegexRoute( + 'img/' . $this->name . '/(.+)', array( 'controller' => 'static', 'action' => 'img', 'module_name' => $this->name + ), + array( + 1 => 'file' ) ) ); From e8d526fcf9054e985677fc24805ae510ca16638d Mon Sep 17 00:00:00 2001 From: Alexander Fuhr Date: Mon, 8 Sep 2014 12:59:22 +0200 Subject: [PATCH 14/44] StaticController: Fix img file inclusion --- application/controllers/StaticController.php | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/application/controllers/StaticController.php b/application/controllers/StaticController.php index edcc57d39..c8b1d9b73 100644 --- a/application/controllers/StaticController.php +++ b/application/controllers/StaticController.php @@ -59,20 +59,12 @@ class StaticController extends ActionController public function imgAction() { $module = $this->_getParam('module_name'); - // TODO: This is more than dangerous, must be fixed!! $file = $this->_getParam('file'); $basedir = Icinga::app()->getModuleManager()->getModule($module)->getBaseDir(); $filePath = realpath($basedir . '/public/img/' . $file); - if (strpos($filePath, $basedir) === false) { - throw new ActionException(sprintf( - '%s does not exist', - $filePath - ), 404); - } - - if (! file_exists($filePath)) { + if (! $filePath || strpos($filePath, $basedir) !== 0) { throw new ActionException(sprintf( '%s does not exist', $filePath From f53519c54d2e3bbf58178f6c52ba500eb8a6b9d9 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Mon, 8 Sep 2014 13:31:25 +0200 Subject: [PATCH 15/44] Rename ConfigForm::setConfig() to ConfigForm::setIniConfig() We do not want to override Zend_Form::setConfig() so this renaming is required. set*Ini*Config() because ConfigForm::save() utilizes an ini-writer to persist the configuration to disk. refs #5525 --- application/controllers/ConfigController.php | 16 ++++++++-------- .../Config/AuthenticationBackendReorderForm.php | 2 +- application/forms/ConfigForm.php | 2 +- .../application/controllers/ConfigController.php | 14 +++++++------- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/application/controllers/ConfigController.php b/application/controllers/ConfigController.php index 39051011c..559d8f3f9 100644 --- a/application/controllers/ConfigController.php +++ b/application/controllers/ConfigController.php @@ -46,7 +46,7 @@ class ConfigController extends ActionController public function indexAction() { $form = new GeneralConfigForm(); - $form->setConfig(IcingaConfig::app()); + $form->setIniConfig(IcingaConfig::app()); $form->handleRequest(); $this->view->form = $form; @@ -131,7 +131,7 @@ class ConfigController extends ActionController public function authenticationAction() { $form = new AuthenticationBackendReorderForm(); - $form->setConfig(IcingaConfig::app('authentication')); + $form->setIniConfig(IcingaConfig::app('authentication')); $form->handleRequest(); $this->view->form = $form; @@ -145,7 +145,7 @@ class ConfigController extends ActionController public function createauthenticationbackendAction() { $form = new AuthenticationBackendConfigForm(); - $form->setConfig(IcingaConfig::app('authentication')); + $form->setIniConfig(IcingaConfig::app('authentication')); $form->setResourceConfig(ResourceFactory::getResourceConfigs()); $form->setRedirectUrl('config/authentication'); $form->handleRequest(); @@ -161,7 +161,7 @@ class ConfigController extends ActionController public function editauthenticationbackendAction() { $form = new AuthenticationBackendConfigForm(); - $form->setConfig(IcingaConfig::app('authentication')); + $form->setIniConfig(IcingaConfig::app('authentication')); $form->setResourceConfig(ResourceFactory::getResourceConfigs()); $form->setRedirectUrl('config/authentication'); $form->handleRequest(); @@ -179,7 +179,7 @@ class ConfigController extends ActionController $form = new ConfirmRemovalForm(array( 'onSuccess' => function ($request) { $configForm = new AuthenticationBackendConfigForm(); - $configForm->setConfig(IcingaConfig::app('authentication')); + $configForm->setIniConfig(IcingaConfig::app('authentication')); $authBackend = $request->getQuery('auth_backend'); try { @@ -222,7 +222,7 @@ class ConfigController extends ActionController public function createresourceAction() { $form = new ResourceConfigForm(); - $form->setConfig(IcingaConfig::app('resources')); + $form->setIniConfig(IcingaConfig::app('resources')); $form->setRedirectUrl('config/resource'); $form->handleRequest(); @@ -236,7 +236,7 @@ class ConfigController extends ActionController public function editresourceAction() { $form = new ResourceConfigForm(); - $form->setConfig(IcingaConfig::app('resources')); + $form->setIniConfig(IcingaConfig::app('resources')); $form->setRedirectUrl('config/resource'); $form->handleRequest(); @@ -252,7 +252,7 @@ class ConfigController extends ActionController $form = new ConfirmRemovalForm(array( 'onSuccess' => function ($request) { $configForm = new ResourceConfigForm(); - $configForm->setConfig(IcingaConfig::app('resources')); + $configForm->setIniConfig(IcingaConfig::app('resources')); $resource = $request->getQuery('resource'); try { diff --git a/application/forms/Config/AuthenticationBackendReorderForm.php b/application/forms/Config/AuthenticationBackendReorderForm.php index d4be16c30..3b5e70866 100644 --- a/application/forms/Config/AuthenticationBackendReorderForm.php +++ b/application/forms/Config/AuthenticationBackendReorderForm.php @@ -62,7 +62,7 @@ class AuthenticationBackendReorderForm extends ConfigForm protected function getConfigForm() { $form = new AuthenticationBackendConfigForm(); - $form->setConfig($this->config); + $form->setIniConfig($this->config); return $form; } } diff --git a/application/forms/ConfigForm.php b/application/forms/ConfigForm.php index 1f3692473..a354fa538 100644 --- a/application/forms/ConfigForm.php +++ b/application/forms/ConfigForm.php @@ -28,7 +28,7 @@ class ConfigForm extends Form * * @return self */ - public function setConfig(Config $config) + public function setIniConfig(Config $config) { $this->config = $config; return $this; diff --git a/modules/monitoring/application/controllers/ConfigController.php b/modules/monitoring/application/controllers/ConfigController.php index c2de49be1..de9c65b04 100644 --- a/modules/monitoring/application/controllers/ConfigController.php +++ b/modules/monitoring/application/controllers/ConfigController.php @@ -31,7 +31,7 @@ class Monitoring_ConfigController extends ModuleActionController public function editbackendAction() { $form = new BackendConfigForm(); - $form->setConfig($this->Config('backends')); + $form->setIniConfig($this->Config('backends')); $form->setResourceConfig(ResourceFactory::getResourceConfigs()); $form->setRedirectUrl('monitoring/config'); $form->handleRequest(); @@ -45,7 +45,7 @@ class Monitoring_ConfigController extends ModuleActionController public function createbackendAction() { $form = new BackendConfigForm(); - $form->setConfig($this->Config('backends')); + $form->setIniConfig($this->Config('backends')); $form->setResourceConfig(ResourceFactory::getResourceConfigs()); $form->setRedirectUrl('monitoring/config'); $form->handleRequest(); @@ -63,7 +63,7 @@ class Monitoring_ConfigController extends ModuleActionController 'onSuccess' => function ($request) use ($config) { $backendName = $request->getQuery('backend'); $configForm = new BackendConfigForm(); - $configForm->setConfig($config); + $configForm->setIniConfig($config); try { $configForm->remove($backendName); @@ -95,7 +95,7 @@ class Monitoring_ConfigController extends ModuleActionController 'onSuccess' => function ($request) use ($config) { $instanceName = $request->getQuery('instance'); $configForm = new InstanceConfigForm(); - $configForm->setConfig($config); + $configForm->setIniConfig($config); try { $configForm->remove($instanceName); @@ -123,7 +123,7 @@ class Monitoring_ConfigController extends ModuleActionController public function editinstanceAction() { $form = new InstanceConfigForm(); - $form->setConfig($this->Config('instances')); + $form->setIniConfig($this->Config('instances')); $form->setRedirectUrl('monitoring/config'); $form->handleRequest(); @@ -136,7 +136,7 @@ class Monitoring_ConfigController extends ModuleActionController public function createinstanceAction() { $form = new InstanceConfigForm(); - $form->setConfig($this->Config('instances')); + $form->setIniConfig($this->Config('instances')); $form->setRedirectUrl('monitoring/config'); $form->handleRequest(); @@ -149,7 +149,7 @@ class Monitoring_ConfigController extends ModuleActionController public function securityAction() { $form = new SecurityConfigForm(); - $form->setConfig($this->Config()); + $form->setIniConfig($this->Config()); $form->handleRequest(); $this->view->form = $form; From 545db945da06b7c6444ef1d44c816437517fcab3 Mon Sep 17 00:00:00 2001 From: Matthias Jentsch Date: Mon, 8 Sep 2014 15:21:14 +0200 Subject: [PATCH 16/44] Auto refresh menu Put the navigation into a container and reload it once every 15 seconds from a distinct menu action. Include the current path into an URL param to still be able to mark the current menu item as active. fixes #6955 --- application/controllers/LayoutController.php | 7 ++++--- .../layouts/scripts/parts/navigation.phtml | 17 +++++++++++----- application/views/scripts/layout/menu.phtml | 14 ++++++++++++- public/js/icinga/events.js | 20 +++++++++++++++---- 4 files changed, 45 insertions(+), 13 deletions(-) diff --git a/application/controllers/LayoutController.php b/application/controllers/LayoutController.php index 6c1355fc1..7d2ea9ae5 100644 --- a/application/controllers/LayoutController.php +++ b/application/controllers/LayoutController.php @@ -18,10 +18,11 @@ class LayoutController extends ActionController */ public function menuAction() { + $this->setAutorefreshInterval(15); $this->_helper->layout()->disableLayout(); - $this->view->menuRenderer = new MenuRenderer( - Menu::load(), Url::fromRequest()->without('renderLayout')->getRelativeUrl() - ); + + $url = Url::fromPath($this->getParam('url')); + $this->view->menuRenderer = new MenuRenderer(Menu::load(), $url->getRelativeUrl()); } /** diff --git a/application/layouts/scripts/parts/navigation.phtml b/application/layouts/scripts/parts/navigation.phtml index 5dedc75aa..5de8f3e40 100644 --- a/application/layouts/scripts/parts/navigation.phtml +++ b/application/layouts/scripts/parts/navigation.phtml @@ -9,13 +9,20 @@ use Icinga\Web\Widget\SearchDashboard; if (! $this->auth()->isAuthenticated()) { return; } +$dataIcingaUrl = $this->href( + 'layout/menu', + array('url' => Url::fromRequest()->without('renderLayout')->getAbsoluteUrl()) +); ?> -