diff --git a/application/controllers/ConfigController.php b/application/controllers/ConfigController.php index 4f7adf963..88ea60639 100644 --- a/application/controllers/ConfigController.php +++ b/application/controllers/ConfigController.php @@ -31,6 +31,9 @@ use \Icinga\Web\Widget\Tab; use \Icinga\Web\Url; use \Icinga\Web\Hook\Configuration\ConfigurationTabBuilder; use \Icinga\Application\Icinga; +use \Icinga\Form\Config\GeneralForm; +use \Icinga\Form\Config\LoggingForm; +use \Icinga\Config\PreservingIniWriter; /** * Application wide controller for application preferences @@ -49,18 +52,23 @@ class ConfigController extends BaseConfigController return array( 'index' => new Tab( array( - 'name' => 'index', - 'title' => 'Configuration', - 'iconCls' => 'wrench', - 'url' => Url::fromPath('/config') + "name" => "index", + "title" => "Application", + "url" => Url::fromPath("/config") ) ), - 'modules' => new Tab( + "logging" => new Tab( array( - 'name' => 'modules', - 'title' => 'Modules', - 'iconCls' => 'puzzle-piece', - 'url' => Url::fromPath('/config/moduleoverview') + "name" => "logging", + "title" => "Logging", + "url" => Url::fromPath("/config/logging") + ) + ), + "modules" => new Tab( + array( + "name" => "modules", + "title" => "Modules", + "url" => Url::fromPath("/config/moduleoverview") ) ) ); @@ -72,7 +80,26 @@ class ConfigController extends BaseConfigController */ public function indexAction() { + $form = new GeneralForm(); + $form->setConfiguration(IcingaConfig::app()); + $form->setRequest($this->_request); + if ($form->isSubmittedAndValid()) { + $cfg = IcingaConfig::app()->getConfigFile(); + $writer = new PreservingIniWriter( + array('config' => $form->getConfig(),'filename' => $cfg) + ); + print_r($writer->render());die(); + } + $this->view->form = $form; + } + public function loggingAction() + { + $form = new LoggingForm(); + $form->setConfiguration(IcingaConfig::app()); + $form->setRequest($this->_request); + + $this->view->form = $form; } /** @@ -106,5 +133,7 @@ class ConfigController extends BaseConfigController $manager->disableModule($this->_getParam('name')); $this->redirectNow('config/moduleoverview?_render=body'); } + + } // @codingStandardsIgnoreEnd diff --git a/application/forms/Config/GeneralForm.php b/application/forms/Config/GeneralForm.php new file mode 100644 index 000000000..4a416b48d --- /dev/null +++ b/application/forms/Config/GeneralForm.php @@ -0,0 +1,278 @@ + + * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 + * @author Icinga Development Team + */ +// {{{ICINGA_LICENSE_HEADER}}} + +namespace Icinga\Form\Config; +/** + * [global] +environment = development +timezone = "Europe/Berlin" +indexModule = monitoring +indexController = dashboard +moduleFolder = "/etc/icinga2-web/enabledModules" +dateFormat = "d/m/Y" +timeFormat = "g:i A" + +[logging] +; General log +enable = 1 +type = stream +verbose = 1 +target = /tmp/icinga2.log + +; For development and debug purposes: Logs additional (non critical) events to a +; seperate log +debug.enable = 1 +debug.type = stream +debug.target = /tmp/icinga2.debug.log + +; Use ini store to store preferences on local disk +[preferences] +type=ini + + */ +use \Icinga\Application\Config as IcingaConfig; +use Icinga\Application\Icinga; +use \Icinga\Web\Form; +use \Zend_Form_Element_Radio; +use \DateTimeZone; +use \Zend_Config; +use Icinga\Web\Form\Element\Note; + +/** + * Configuration form for general, application-wide settings + * + */ +class GeneralForm extends Form +{ + /** + * The configuration to use for populating this form + * + * @var IcingaConfig + */ + private $config = null; + + /** + * The base directory of the icingaweb configuration + * + * @var string + */ + private $configDir = null; + + /** + * Set the configuration to be used for this form + * + * @param IcingaConfig $cfg + */ + public function setConfiguration(IcingaConfig $cfg) + { + $this->config = $cfg; + } + + /** + * Set a specific configuration directory to use for configuration specific default paths + * + * @param string $dir + */ + public function setConfigDir($dir) + { + $this->configDir = $dir; + } + + /** + * Return the config path set for this form or the application wide config path if none is set + * + * @return string + * @see IcingaConfig::configDir + */ + public function getConfigDir() + { + return $this->configDir === null ? IcingaConfig::$configDir : $this->configDir; + } + + /** + * Add the checkbox for using the development environment to this form + * + * @param Zend_Config $cfg The "global" section of the config.ini + */ + private function addDevelopmentCheckbox(Zend_Config $cfg) + { + $env = $cfg->get('environment', 'development'); + $this->addElement( + 'checkbox', + 'environment', + array( + 'label' => 'Development mode', + 'required' => true, + 'tooltip' => 'More verbose output', + 'value' => $env === 'development' + ) + ); + $this->addElement(new Note(array( + 'name' => 'note_env', + 'value' => 'Set true to show more detailed errors and disable certain optimizations ' + . 'in order to make debugging easier.' + ))); + } + + /** + * Add a select field for setting the default timezone. + * + * Possible values are determined by DateTimeZone::listIdentifiers + * + * @param Zend_Config $cfg The "global" section of the config.ini + */ + private function addTimezoneSelection(Zend_Config $cfg) + { + $tzList = array(); + foreach(DateTimeZone::listIdentifiers() as $tz) { + $tzList[$tz] = $tz; + } + + $this->addElement( + 'select', + 'timezone', + array( + 'label' => 'Default application timezone', + 'required' => true, + 'multiOptions' => $tzList, + 'value' => $cfg->get('timezone', date_default_timezone_get()) + ) + ); + $this->addElement(new Note(array( + 'name' => 'noteTimezone', + 'value' => 'Select the timezone to be used as the default. User\'s can set their own timezone if'. + ' they like to, but this is the timezone to be used as the default setting .' + ))); + } + + /** + * Add configuration settings for module paths + * + * @param Zend_Config $cfg The "global" section of the config.ini + */ + private function addModuleSettings(Zend_Config $cfg) + { + $this->addElement( + 'text', + 'module_folder', + array( + 'label' => 'Module folder', + 'required' => true, + 'value' => $cfg->get('moduleFolder', $this->getConfigDir() . '/config/enabledModules') + ) + ); + $this->addElement(new Note(array( + 'name' => 'noteModuleFolder', + 'value' => 'Use this folder to activate modules (must be writable by your webserver)' + ))); + } + + /** + * Add text fields for the date and time format used in the application + * + * @param Zend_Config $cfg The "global" section of the config.ini + */ + private function addDateFormatSettings(Zend_Config $cfg) + { + $phpUrl = 'the official PHP documentation'; + + $this->addElement( + 'text', + 'date_format', + array( + 'label' => 'Date format', + 'required' => true, + 'value' => $cfg->get('dateFormat', 'd/m/Y') + ) + ); + $this->addElement(new Note(array( + 'name' => 'noteDateFormat', + 'value' => 'Display dates according to this format. See ' . $phpUrl . ' for possible values' + ))); + + + $this->addElement( + 'text', + 'time_format', + array( + 'label' => 'Time format', + 'required' => true, + 'value' => $cfg->get('timeFormat', 'g:i A') + ) + ); + $this->addElement(new Note(array( + 'name' => 'noteTimeFormat', + 'value' => 'Display times according to this format. See ' . $phpUrl . ' for possible values' + ))); + } + + /** + * Create the general form, using the provided configuration + * + * @see Form::create() + */ + public function create() + { + if ($this->config === null) { + $this->config = new Zend_Config(array()); + } + $global = $this->config->global; + if ($global === null) { + $global = new Zend_Config(array()); + } + + $this->addDevelopmentCheckbox($global); + $this->addTimezoneSelection($global); + $this->addModuleSettings($global); + $this->addDateFormatSettings($global); + + $this->setSubmitLabel('Save changes'); + } + + public function getConfig() + { + if ($this->config === null) { + $this->config = new Zend_Config(array()); + } + $global = $this->config->global; + if ($global === null) { + $this->config->global = new Zend_Config(array()); + } + + $values = $this->getValues(); + $cfg = clone $this->config; + $cfg->global->environment = ($values['environment'] == 1) ? 'development' : 'production'; + $cfg->global->timezone = $values['timezone']; + $cfg->global->moduleFolder = $values['module_folder']; + $cfg->global->dateFormat = $values['date_format']; + $cfg->global->timeFormat = $values['time_format']; + + return $cfg; + } + +} \ No newline at end of file diff --git a/application/forms/Config/LoggingForm.php b/application/forms/Config/LoggingForm.php new file mode 100644 index 000000000..952ae1c61 --- /dev/null +++ b/application/forms/Config/LoggingForm.php @@ -0,0 +1,217 @@ + + * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 + * @author Icinga Development Team + */ +// {{{ICINGA_LICENSE_HEADER}}} + +namespace Icinga\Form\Config; + +use \Icinga\Application\Config as IcingaConfig; +use \Icinga\Application\Icinga; +use \Icinga\Web\Form; +use \Icinga\Web\Form\Element\Note; +use \Icinga\Web\Form\Decorator\ConditionalHidden; +use \Zend_Config; +use \Zend_Form_Element_Text; + +/** + * Form class for setting the application wide logging configuration + * + */ +class LoggingForm extends Form +{ + /** + * The configuration to use for this form + * + * @var Zend_Config + */ + private $config = null; + + /** + * Set the configuration of this form + * + * If not called, default values are used instead + * + * @param Zend_Config $cfg The config.ini to set with this form + */ + public function setConfiguration(Zend_Config $cfg) + { + $this->config = $cfg; + } + + /** + * Return true if the debug log path textfield should be displayed + * + * This is the case if the "logging_use_debug" field is autosubmitted + * and true or if it is not submitted, but the configuration for debug + * logging is set to true + * + * @param Zend_Config $config The debug section of the config.ini + * + * @return bool Whether to display the debug path field or not + */ + private function shouldDisplayDebugLog(Zend_Config $config) + { + $debugParam = $this->getRequest()->getParam('logging_use_debug', null); + if ($debugParam !== null) { + return intval($debugParam) === 1; + } else { + return intval($config->get('enable', 0)) === 1; + } + + } + + private function loggingIsEnabled(Zend_Config $config) + { + $loggingRequestParam = $this->getRequest()->getParam('logging_enable', null); + + if ($loggingRequestParam !== null) { + return intval($loggingRequestParam) === 1; + } else { + return intval($config->get('enable', 0)) === 1; + } + } + + /** + * @see Form::create() + */ + public function create() + { + if ($this->config === null) { + $this->config = new Zend_Config(array()); + } + + $logging = $this->config->logging; + if ($logging === null) { + $logging = new IcingaConfig(array()); + } + + $debug = $logging->debug; + if ($debug === null) { + $debug = new IcingaConfig(array()); + } + $this->addElement( + 'checkbox', + 'logging_enable', + array( + 'label' => 'Logging enabled', + 'required' => true, + 'value' => $this->loggingIsEnabled($logging) + ) + ); + if (!$this->loggingIsEnabled($debug)) { + $this->addElement( + new Note( + array( + 'name' => 'note_logging_disabled', + 'value' => 'Logging is disabled.' + ) + ) + ); + $this->setSubmitLabel('Save changes'); + $this->enableAutoSubmit(array('logging_enable')); + + return; + } + $this->addDecorator(new ConditionalHidden()); + + $this->addElement( + 'text', + 'logging_app_path', + array( + 'label' => 'Application log path', + 'required' => true, + 'value' => $logging->get('target', '/var/log/icingaweb.log') + ) + ); + + $this->addElement(new Note( + array( + 'name' => 'note_logging_app_path', + 'value'=> 'The logfile to write the icingaweb debug logs to. The webserver must be able to write' + . 'at this location' + ) + )); + + $this->addElement( + 'checkbox', + 'logging_app_verbose', + array( + 'label' => 'Verbose logging', + 'required' => true, + 'value' => intval($logging->get('verbose', 0)) === 1 + ) + ); + + $this->addElement(new Note( + array( + 'name' => 'note_logging_app_verbose', + 'value'=> 'Check to write more verbose output to the icinga log file' + ) + )); + + $this->addElement( + 'checkbox', + 'logging_use_debug', + array( + 'label' => 'Use debug log', + 'required' => true, + 'value' => $this->shouldDisplayDebugLog($debug) + ) + ); + $this->addElement(new Note( + array( + 'name' => 'note_logging_use_debug', + 'value'=> 'Check to write a seperate debug log (Warning: This file can grow very big)' + ) + )); + + + $textLoggingDebugPath = new Zend_Form_Element_Text( + array( + 'name' => 'logging_debug_path', + 'label' => 'Debug log path', + 'required' => true, + 'condition' => $this->shouldDisplayDebugLog($debug), + 'value' => $debug->get('target', '/var/log/icingaweb.debug.log') + ) + ); + $loggingPathNote = new Note( + array( + 'name' => 'note_logging_debug_path', + 'value' => 'Set the path to the debug log', + 'condition' => $this->shouldDisplayDebugLog($debug) + ) + ); + + $this->addElement($textLoggingDebugPath); + $this->addElement($loggingPathNote); + + $this->enableAutoSubmit(array('logging_use_debug', 'logging_enable')); + + $this->setSubmitLabel('Save changes'); + } + +} \ No newline at end of file diff --git a/application/views/scripts/config/index.phtml b/application/views/scripts/config/index.phtml index ef3c458db..f0b046499 100644 --- a/application/views/scripts/config/index.phtml +++ b/application/views/scripts/config/index.phtml @@ -1,12 +1,2 @@ tabs->render($this); ?> - -

Configuration

- -
-

Dear developer

-
-

- Add shortcuts for often used configuration options so users can quickly change settings without having to - search in the tab overview -

-
\ No newline at end of file +form ?> \ No newline at end of file diff --git a/application/views/scripts/config/logging.phtml b/application/views/scripts/config/logging.phtml new file mode 100644 index 000000000..aa8ca9f49 --- /dev/null +++ b/application/views/scripts/config/logging.phtml @@ -0,0 +1,3 @@ +tabs->render($this); ?> + +form ?> \ No newline at end of file diff --git a/library/Icinga/Config/IniEditor.php b/library/Icinga/Config/IniEditor.php index afb89d44a..42dd60380 100644 --- a/library/Icinga/Config/IniEditor.php +++ b/library/Icinga/Config/IniEditor.php @@ -225,10 +225,11 @@ class IniEditor */ private function cleanUpWhitespaces() { + $i = count($this->text) - 1; for (; $i > 0; $i--) { $line = $this->text[$i]; - if ($this->isSectionDeclaration($line)) { + if ($this->isSectionDeclaration($line) && $i > 0) { $i--; $line = $this->text[$i]; /* diff --git a/library/Icinga/Web/Form/Decorator/ConditionalHidden.php b/library/Icinga/Web/Form/Decorator/ConditionalHidden.php new file mode 100644 index 000000000..7dc54a8fe --- /dev/null +++ b/library/Icinga/Web/Form/Decorator/ConditionalHidden.php @@ -0,0 +1,65 @@ + + * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 + * @author Icinga Development Team + */ +// {{{ICINGA_LICENSE_HEADER}}} + + +/** + * Decorator to hide elements using a >noscript< tag instead of + * type='hidden' or css styles. + * + * This allows to hide depending elements for browsers with javascript + * (who can then automatically refresh their pages) but show them in + * case JavaScript is disabled + */ + +namespace Icinga\Web\Form\Decorator; + +use \Zend_Form_Decorator_Abstract; + +class ConditionalHidden extends Zend_Form_Decorator_Abstract +{ + /** + * Generates a html number input + * + * @access public + * + * @param string $name The element name. + * @param string $value The default value. + * @param array $attribs Attributes which should be added to the input tag. + * + * @return string The input tag and options XHTML. + */ + public function render($content ='') + { + $attributes = $this->getElement()->getAttribs(); + $condition = isset($attributes['condition']) ? $attributes['condition'] : 1; + if ($condition != 1) { + $content = ''; + } + return $content; + } +} diff --git a/modules/monitoring/application/controllers/ConfigController.php b/modules/monitoring/application/controllers/ConfigController.php index fbc0a52f5..e92e28f8f 100644 --- a/modules/monitoring/application/controllers/ConfigController.php +++ b/modules/monitoring/application/controllers/ConfigController.php @@ -38,7 +38,6 @@ class Monitoring_ConfigController extends BaseConfigController { return array( "backends" => new Tab(array( "name" => "backends", - "iconCls" => "hdd", "title" => "Monitoring Backends", "url" => Url::fromPath("/monitoring/config/backend") ))