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

This commit is contained in:
Eric Lippmann 2014-09-02 17:09:36 +02:00
commit 0b1d2bf685
29 changed files with 901 additions and 1002 deletions

View File

@ -2,8 +2,7 @@
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
use Icinga\Web\Controller\BaseConfigController;
use Icinga\Web\Widget\AlertMessageBox;
use Icinga\Web\Controller\ActionController;
use Icinga\Web\Notification;
use Icinga\Application\Modules\Module;
use Icinga\Web\Widget;
@ -12,16 +11,15 @@ use Icinga\Application\Config as IcingaConfig;
use Icinga\Form\Config\GeneralConfigForm;
use Icinga\Form\Config\AuthenticationBackendReorderForm;
use Icinga\Form\Config\AuthenticationBackendConfigForm;
use Icinga\Form\Config\ResourceForm;
use Icinga\Form\Config\ResourceConfigForm;
use Icinga\Form\ConfirmRemovalForm;
use Icinga\Config\PreservingIniWriter;
use Icinga\Data\ResourceFactory;
/**
* Application wide controller for application preferences
*/
class ConfigController extends BaseConfigController
class ConfigController extends ActionController
{
public function init()
{
@ -210,14 +208,12 @@ class ConfigController extends BaseConfigController
}
/**
* Display all available resources and a link to create a new one
* Display all available resources and a link to create a new one and to remove existing ones
*/
public function resourceAction()
{
$this->view->messageBox = new AlertMessageBox(true);
$this->view->tabs->activate('resources');
$this->view->resources = IcingaConfig::app('resources', true)->toArray();
$this->view->tabs->activate('resources');
}
/**
@ -225,26 +221,12 @@ class ConfigController extends BaseConfigController
*/
public function createresourceAction()
{
$this->view->messageBox = new AlertMessageBox(true);
$form = new ResourceForm();
$request = $this->getRequest();
if ($request->isPost() && $form->isValid($request->getPost())) {
list($name, $config) = $form->getResourceConfig();
$resources = IcingaConfig::app('resources')->toArray();
if (array_key_exists($name, $resources)) {
$this->addErrorMessage(sprintf($this->translate('Resource name "%s" already in use.'), $name));
} else {
$resources[$name] = $config;
if ($this->writeConfigFile($resources, 'resources')) {
$this->addSuccessMessage(sprintf($this->translate('Resource "%s" successfully created.'), $name));
$this->redirectNow('config/resource');
}
}
}
$form = new ResourceConfigForm();
$form->setConfig(IcingaConfig::app('resources'));
$form->setRedirectUrl('config/resource');
$form->handleRequest();
$this->view->form = $form;
$this->view->messageBox->addForm($form);
$this->render('resource/create');
}
@ -253,39 +235,12 @@ class ConfigController extends BaseConfigController
*/
public function editresourceAction()
{
$this->view->messageBox = new AlertMessageBox(true);
// Fetch the resource to be edited
$resources = IcingaConfig::app('resources')->toArray();
$name = $this->getParam('resource');
if (false === array_key_exists($name, $resources)) {
$this->addErrorMessage(sprintf($this->translate('Cannot edit "%s". Resource not found.'), $name));
$this->redirectNow('config/configurationerror');
}
$form = new ResourceForm();
$request = $this->getRequest();
if ($request->isPost()) {
if ($form->isValid($request->getPost())) {
list($newName, $config) = $form->getResourceConfig();
if ($newName !== $name) {
// Resource name has changed
unset($resources[$name]); // We can safely use unset as all values are part of the form
}
$resources[$newName] = $config;
if ($this->writeConfigFile($resources, 'resources')) {
$this->addSuccessMessage(sprintf($this->translate('Resource "%s" successfully edited.'), $name));
$this->redirectNow('config/resource');
}
}
} else {
$form->setResourceConfig($name, $resources[$name]);
}
$form = new ResourceConfigForm();
$form->setConfig(IcingaConfig::app('resources'));
$form->setRedirectUrl('config/resource');
$form->handleRequest();
$this->view->form = $form;
$this->view->messageBox->addForm($form);
$this->render('resource/modify');
}
@ -294,104 +249,46 @@ class ConfigController extends BaseConfigController
*/
public function removeresourceAction()
{
$this->view->messageBox = new AlertMessageBox(true);
$form = new ConfirmRemovalForm(array(
'onSuccess' => function ($request) {
$configForm = new ResourceConfigForm();
$configForm->setConfig(IcingaConfig::app('resources'));
$resource = $request->getQuery('resource');
// Fetch the resource to be removed
$resources = IcingaConfig::app('resources')->toArray();
$name = $this->getParam('resource');
if (false === array_key_exists($name, $resources)) {
$this->addErrorMessage(sprintf($this->translate('Cannot remove "%s". Resource not found.'), $name));
$this->redirectNow('config/configurationerror');
}
try {
$configForm->remove($resource);
} catch (InvalidArgumentException $e) {
Notification::error($e->getMessage());
return;
}
if ($configForm->save()) {
Notification::success(sprintf(t('Resource "%s" has been successfully removed'), $resource));
} else {
return false;
}
}
));
$form->setRedirectUrl('config/resource');
$form->handleRequest();
// Check if selected resource is currently used for authentication
$resource = $this->getRequest()->getQuery('resource');
$authConfig = IcingaConfig::app('authentication')->toArray();
foreach ($authConfig as $backendName => $config) {
if (array_key_exists('resource', $config) && $config['resource'] === $name) {
$this->addWarningMessage(
sprintf(
$this->translate(
'The resource "%s" is currently in use by the authentication backend "%s". ' .
'Removing the resource can result in noone being able to log in any longer.'
),
$name,
$backendName
)
);
}
}
$form = new ConfirmRemovalForm();
$request = $this->getRequest();
if ($request->isPost() && $form->isValid($request->getPost())) {
unset($resources[$name]);
if ($this->writeConfigFile($resources, 'resources')) {
$this->addSuccessMessage(sprintf($this->translate('Resource "%s" successfully removed.'), $name));
$this->redirectNow('config/resource');
if (array_key_exists('resource', $config) && $config['resource'] === $resource) {
$form->addError(sprintf(
$this->translate(
'The resource "%s" is currently in use by the authentication backend "%s". ' .
'Removing the resource can result in noone being able to log in any longer.'
),
$resource,
$backendName
));
}
}
$this->view->form = $form;
$this->view->messageBox->addForm($form);
$this->render('resource/remove');
}
/**
* Redirect target only for error-states
*
* When an error is opened in the side-pane, redirecting this request to the index or the overview will look
* weird. This action returns a clear page containing only an AlertMessageBox.
*/
public function configurationerrorAction()
{
$this->view->messageBox = new AlertMessageBox(true);
$this->render('error/error', null, true);
}
/**
* Write changes to an authentication file
*
* @param array $config The configuration changes
*
* @return bool True when persisting succeeded, otherwise false
*
* @see writeConfigFile()
*/
private function writeAuthenticationFile($config) {
return $this->writeConfigFile($config, 'authentication');
}
/**
* Write changes to a configuration file $file, using the supplied writer or PreservingIniWriter if none is set
*
* @param array|Zend_Config $config The configuration to write
* @param string $file The filename to write to (without .ini)
* @param Zend_Config_Writer $writer An optional writer to use for persisting changes
*
* @return bool True when persisting succeeded, otherwise false
*/
private function writeConfigFile($config, $file, $writer = null)
{
if (is_array($config)) {
$config = new Zend_Config($config);
}
if ($writer === null) {
$writer = new PreservingIniWriter(
array(
'config' => $config,
'filename' => IcingaConfig::app($file)->getConfigFile()
)
);
}
try {
$writer->write();
return true;
} catch (Exception $exc) {
$this->view->exceptionMessage = $exc->getMessage();
$this->view->iniConfigurationString = $writer->render();
$this->view->file = $file;
$this->render('show-configuration');
return false;
}
}
}

View File

@ -32,7 +32,7 @@ class AutologinBackendForm extends Form
array(
'required' => true,
'label' => t('Backend Name'),
'helptext' => t('The name of this authentication backend'),
'description' => t('The name of this authentication backend'),
'validators' => array(
array(
'Regex',
@ -53,7 +53,7 @@ class AutologinBackendForm extends Form
array(
'required' => true,
'label' => t('Backend Domain Pattern'),
'helptext' => t('The domain pattern of this authentication backend'),
'description' => t('The domain pattern of this authentication backend'),
'value' => '/\@[^$]+$/',
'validators' => array(
new Zend_Validate_Callback(function ($value) {

View File

@ -55,7 +55,7 @@ class DbBackendForm extends Form
array(
'required' => true,
'label' => t('Backend Name'),
'helptext' => t('The name of this authentication provider'),
'description' => t('The name of this authentication provider'),
)
),
$this->createElement(
@ -64,7 +64,7 @@ class DbBackendForm extends Form
array(
'required' => true,
'label' => t('Database Connection'),
'helptext' => t('The database connection to use for authenticating with this provider'),
'description' => t('The database connection to use for authenticating with this provider'),
'multiOptions' => false === empty($this->resources)
? array_combine($this->resources, $this->resources)
: array()

View File

@ -54,7 +54,7 @@ class LdapBackendForm extends Form
array(
'required' => true,
'label' => t('Backend Name'),
'helptext' => t('The name of this authentication backend')
'description' => t('The name of this authentication backend')
)
),
$this->createElement(
@ -63,7 +63,7 @@ class LdapBackendForm extends Form
array(
'required' => true,
'label' => t('LDAP Resource'),
'helptext' => t('The resource to use for authenticating with this provider'),
'description' => t('The resource to use for authenticating with this provider'),
'multiOptions' => false === empty($this->resources)
? array_combine($this->resources, $this->resources)
: array()
@ -73,20 +73,20 @@ class LdapBackendForm extends Form
'text',
'user_class',
array(
'required' => true,
'label' => t('LDAP User Object Class'),
'helptext' => t('The object class used for storing users on the ldap server'),
'value' => 'inetOrgPerson'
'required' => true,
'label' => t('LDAP User Object Class'),
'description' => t('The object class used for storing users on the ldap server'),
'value' => 'inetOrgPerson'
)
),
$this->createElement(
'text',
'user_name_attribute',
array(
'required' => true,
'label' => t('LDAP User Name Attribute'),
'helptext' => t('The attribute name used for storing the user name on the ldap server'),
'value' => 'uid'
'required' => true,
'label' => t('LDAP User Name Attribute'),
'description' => t('The attribute name used for storing the user name on the ldap server'),
'value' => 'uid'
)
),
$this->createElement(

View File

@ -202,7 +202,7 @@ class AuthenticationBackendConfigForm extends ConfigForm
if (($el = $this->getElement('force_creation')) === null || false === $el->isChecked()) {
$backendForm = $this->getBackendForm($this->getElement('type')->getValue());
if (false === $backendForm->isValidAuthenticationBackend($this)) {
$this->addForceCreationCheckbox();
$this->addElement($this->getForceCreationCheckbox());
return false;
}
}
@ -231,11 +231,11 @@ class AuthenticationBackendConfigForm extends ConfigForm
/**
* Populate the form in case an authentication backend is being edited
*
* @see Form::onShow()
* @see Form::onRequest()
*
* @throws ConfigurationError In case the backend name is missing in the request or is invalid
*/
public function onShow(Request $request)
public function onRequest(Request $request)
{
$authBackend = $request->getQuery('auth_backend');
if ($authBackend !== null) {
@ -255,19 +255,21 @@ class AuthenticationBackendConfigForm extends ConfigForm
}
/**
* Add a checkbox to be displayed at the beginning of the form
* Return a checkbox to be displayed at the beginning of the form
* which allows the user to skip the connection validation
*
* @return Zend_Form_Element
*/
protected function addForceCreationCheckbox()
protected function getForceCreationCheckbox()
{
$this->addElement(
return $this->createElement(
'checkbox',
'force_creation',
array(
'order' => 0,
'ignore' => true,
'label' => t('Force Changes'),
'helptext' => t('Check this box to enforce changes without connectivity validation')
'order' => 0,
'ignore' => true,
'label' => t('Force Changes'),
'description' => t('Check this box to enforce changes without connectivity validation')
)
);
}
@ -297,22 +299,25 @@ class AuthenticationBackendConfigForm extends ConfigForm
$backendTypes['autologin'] = t('Autologin');
}
$typeSelection = $this->createElement(
$elements = array();
$elements[] = $this->createElement(
'select',
'type',
array(
'ignore' => true,
'required' => true,
'autosubmit' => true,
'label' => t('Backend Type'),
'helptext' => t('The type of the resource to use for this authenticaton backend'),
'multiOptions' => $backendTypes
'ignore' => true,
'required' => true,
'autosubmit' => true,
'label' => t('Backend Type'),
'description' => t('The type of the resource to use for this authenticaton backend'),
'multiOptions' => $backendTypes
)
);
return array_merge(
array($typeSelection),
$this->getBackendForm($backendType)->createElements($formData)
);
if (isset($formData['force_creation']) && $formData['force_creation']) {
// In case another error occured and the checkbox was displayed before
$elements[] = $this->getForceCreationCheckbox();
}
return array_merge($elements, $this->getBackendForm($backendType)->createElements($formData));
}
}

View File

@ -41,7 +41,7 @@ class ApplicationConfigForm extends Form
'label' => t('Default Language'),
'required' => true,
'multiOptions' => $languages,
'helptext' => t(
'description' => t(
'Select the language to use by default. Can be overwritten by a user in his preferences.'
)
)
@ -59,7 +59,7 @@ class ApplicationConfigForm extends Form
'label' => t('Default Application Timezone'),
'required' => true,
'multiOptions' => $tzList,
'helptext' => t(
'description' => t(
'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 .'
),
@ -71,9 +71,9 @@ class ApplicationConfigForm extends Form
'text',
'global_modulePath',
array(
'label' => t('Module Path'),
'required' => true,
'helptext' => t(
'label' => t('Module Path'),
'required' => true,
'description' => t(
'Contains the directories that will be searched for available modules, separated by '
. 'colons. Modules that don\'t exist in these directories can still be symlinked in '
. 'the module folder, but won\'t show up in the list of disabled modules.'

View File

@ -31,7 +31,7 @@ class LoggingConfigForm extends Form
array(
'required' => true,
'label' => t('Logging Level'),
'helptext' => t('The maximum loglevel to emit.'),
'description' => t('The maximum loglevel to emit.'),
'multiOptions' => array(
0 => t('None'),
1 => t('Error'),
@ -48,7 +48,7 @@ class LoggingConfigForm extends Form
'required' => true,
'class' => 'autosubmit',
'label' => t('Logging Type'),
'helptext' => t('The type of logging to utilize.'),
'description' => t('The type of logging to utilize.'),
'multiOptions' => array(
'syslog' => 'Syslog',
'file' => t('File')
@ -63,7 +63,7 @@ class LoggingConfigForm extends Form
array(
'required' => true,
'label' => t('Application Prefix'),
'helptext' => t('The name of the application by which to prefix syslog messages.'),
'description' => t('The name of the application by which to prefix syslog messages.'),
'value' => 'icingaweb',
'validators' => array(
array(
@ -85,7 +85,7 @@ class LoggingConfigForm extends Form
array(
'required' => true,
'label' => t('Facility'),
'helptext' => t('The Syslog facility to utilize.'),
'description' => t('The Syslog facility to utilize.'),
'multiOptions' => array(
'LOG_USER' => 'LOG_USER'
)
@ -98,7 +98,7 @@ class LoggingConfigForm extends Form
array(
'required' => true,
'label' => t('Filepath'),
'helptext' => t('The logfile to write messages to.'),
'description' => t('The logfile to write messages to.'),
'value' => $this->getDefaultLogDir(),
'validators' => array(new WritablePathValidator())
)

View File

@ -60,9 +60,9 @@ class GeneralConfigForm extends ConfigForm
}
/**
* @see Form::onShow()
* @see Form::onRequest()
*/
public function onShow(Request $request)
public function onRequest(Request $request)
{
$values = array();
foreach ($this->config as $section => $properties) {

View File

@ -0,0 +1,128 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Form\Config\Resource;
use Exception;
use Zend_Config;
use Icinga\Web\Form;
use Icinga\Web\Request;
use Icinga\Web\Form\Element\Number;
use Icinga\Data\ResourceFactory;
/**
* Form class for adding/modifying database resources
*/
class DbResourceForm extends Form
{
/**
* Initialize this form
*/
public function init()
{
$this->setName('form_config_resource_db');
}
/**
* @see Form::createElements()
*/
public function createElements(array $formData)
{
return array(
$this->createElement(
'select',
'db',
array(
'required' => true,
'label' => t('Database Type'),
'description' => t('The type of SQL database'),
'multiOptions' => array(
'mysql' => 'MySQL',
'pgsql' => 'PostgreSQL'
//'oracle' => 'Oracle'
)
)
),
$this->createElement(
'text',
'host',
array (
'required' => true,
'label' => t('Host'),
'description' => t('The hostname of the database'),
'value' => 'localhost'
)
),
new Number(
array(
'required' => true,
'name' => 'port',
'label' => t('Port'),
'description' => t('The port to use'),
'value' => 3306
)
),
$this->createElement(
'text',
'dbname',
array(
'required' => true,
'label' => t('Database Name'),
'description' => t('The name of the database to use')
)
),
$this->createElement(
'text',
'username',
array (
'required' => true,
'label' => t('Username'),
'description' => t('The user name to use for authentication')
)
),
$this->createElement(
'password',
'password',
array(
'required' => true,
'renderPassword' => true,
'label' => t('Password'),
'description' => t('The password to use for authentication')
)
)
);
}
/**
* Validate that the current configuration points to a valid resource
*
* @see Form::onSuccess()
*/
public function onSuccess(Request $request)
{
if (false === $this->isValidResource($this)) {
return false;
}
}
/**
* Validate the resource configuration by trying to connect with it
*
* @param Form $form The form to fetch the configuration values from
*
* @return bool Whether validation succeeded or not
*/
public function isValidResource(Form $form)
{
try {
$resource = ResourceFactory::createResource(new Zend_Config($form->getValues()));
$resource->getConnection()->getConnection();
} catch (Exception $e) {
$form->addError(t('Connectivity validation failed, connection to the given resource not possible.'));
return false;
}
return true;
}
}

View File

@ -0,0 +1,50 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Form\Config\Resource;
use Icinga\Web\Form;
use Icinga\Web\Form\Validator\ReadablePathValidator;
/**
* Form class for adding/modifying file resources
*/
class FileResourceForm extends Form
{
/**
* Initialize this form
*/
public function init()
{
$this->setName('form_config_resource_file');
}
/**
* @see Form::createElements()
*/
public function createElements(array $formData)
{
return array(
$this->createElement(
'text',
'filename',
array(
'required' => true,
'label' => t('Filepath'),
'description' => t('The filename to fetch information from'),
'validators' => array(new ReadablePathValidator())
)
),
$this->createElement(
'text',
'fields',
array(
'required' => true,
'label' => t('Pattern'),
'description' => t('The regular expression by which to identify columns')
)
)
);
}
}

View File

@ -0,0 +1,114 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Form\Config\Resource;
use Exception;
use Zend_Config;
use Icinga\Web\Form;
use Icinga\Web\Request;
use Icinga\Web\Form\Element\Number;
use Icinga\Data\ResourceFactory;
/**
* Form class for adding/modifying ldap resources
*/
class LdapResourceForm extends Form
{
/**
* Initialize this form
*/
public function init()
{
$this->setName('form_config_resource_ldap');
}
/**
* @see Form::createElements()
*/
public function createElements(array $formData)
{
return array(
$this->createElement(
'text',
'hostname',
array(
'required' => true,
'label' => t('Host'),
'description' => t('The hostname or address of the LDAP server to use for authentication'),
'value' => 'localhost'
)
),
new Number(
array(
'required' => true,
'name' => 'port',
'label' => t('Port'),
'description' => t('The port of the LDAP server to use for authentication'),
'value' => 389
)
),
$this->createElement(
'text',
'root_dn',
array(
'required' => true,
'label' => t('Root DN'),
'description' => t('The path where users can be found on the ldap server')
)
),
$this->createElement(
'text',
'bind_dn',
array(
'required' => true,
'label' => t('Bind DN'),
'description' => t('The user dn to use for querying the ldap server')
)
),
$this->createElement(
'password',
'bind_pw',
array(
'required' => true,
'renderPassword' => true,
'label' => t('Bind Password'),
'description' => t('The password to use for querying the ldap server')
)
)
);
}
/**
* Validate that the current configuration points to a valid resource
*
* @see Form::onSuccess()
*/
public function onSuccess(Request $request)
{
if (false === $this->isValidResource($this)) {
return false;
}
}
/**
* Validate the resource configuration by trying to connect with it
*
* @param Form $form The form to fetch the configuration values from
*
* @return bool Whether validation succeeded or not
*/
public function isValidResource(Form $form)
{
try {
$resource = ResourceFactory::createResource(new Zend_Config($form->getValues()));
$resource->connect();
} catch (Exception $e) {
$form->addError(t('Connectivity validation failed, connection to the given resource not possible.'));
return false;
}
return true;
}
}

View File

@ -0,0 +1,77 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Form\Config\Resource;
use Exception;
use Zend_Config;
use Icinga\Web\Form;
use Icinga\Web\Request;
use Icinga\Application\Icinga;
use Icinga\Data\ResourceFactory;
/**
* Form class for adding/modifying livestatus resources
*/
class LivestatusResourceForm extends Form
{
/**
* Initialize this form
*/
public function init()
{
$this->setName('form_config_resource_livestatus');
}
/**
* @see Form::createElements()
*/
public function createElements(array $formData)
{
return array(
$this->createElement(
'text',
'socket',
array(
'required' => true,
'label' => t('Socket'),
'description' => t('The path to your livestatus socket used for querying monitoring data'),
'value' => realpath(Icinga::app()->getApplicationDir() . '/../var/rw/livestatus')
)
)
);
}
/**
* Validate that the current configuration points to a valid resource
*
* @see Form::onSuccess()
*/
public function onSuccess(Request $request)
{
if (false === $this->isValidResource($this)) {
return false;
}
}
/**
* Validate the resource configuration by trying to connect with it
*
* @param Form $form The form to fetch the configuration values from
*
* @return bool Whether validation succeeded or not
*/
public function isValidResource(Form $form)
{
try {
$resource = ResourceFactory::createResource(new Zend_Config($form->getValues()));
$resource->connect()->disconnect();
} catch (Exception $e) {
$form->addError(t('Connectivity validation failed, connection to the given resource not possible.'));
return false;
}
return true;
}
}

View File

@ -0,0 +1,54 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Form\Config\Resource;
use Icinga\Web\Form;
use Icinga\Application\Icinga;
use Icinga\Web\Form\Validator\ReadablePathValidator;
/**
* Form class for adding/modifying statusdat resources
*/
class StatusdatResourceForm extends Form
{
/**
* Initialize this form
*/
public function init()
{
$this->setName('form_config_resource_statusdat');
}
/**
* @see Form::createElements()
*/
public function createElements(array $formData)
{
return array(
$this->createElement(
'text',
'status_file',
array(
'required' => true,
'label' => t('Filepath'),
'description' => t('Location of your icinga status.dat file'),
'value' => realpath(Icinga::app()->getApplicationDir() . '/../var/status.dat'),
'validators' => array(new ReadablePathValidator())
)
),
$this->createElement(
'text',
'object_file',
array(
'required' => true,
'label' => t('Filepath'),
'description' => t('Location of your icinga objects.cache file'),
'value' => realpath(Icinga::app()->getApplicationDir() . '/../var/objects.cache'),
'validators' => array(new ReadablePathValidator())
)
)
);
}
}

View File

@ -0,0 +1,258 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Form\Config;
use InvalidArgumentException;
use Icinga\Web\Request;
use Icinga\Web\Notification;
use Icinga\Form\ConfigForm;
use Icinga\Form\Config\Resource\DbResourceForm;
use Icinga\Form\Config\Resource\FileResourceForm;
use Icinga\Form\Config\Resource\LdapResourceForm;
use Icinga\Form\Config\Resource\LivestatusResourceForm;
use Icinga\Form\Config\Resource\StatusdatResourceForm;
use Icinga\Application\Platform;
use Icinga\Exception\ConfigurationError;
class ResourceConfigForm extends ConfigForm
{
/**
* Initialize this form
*/
public function init()
{
$this->setName('form_config_resource');
$this->setSubmitLabel(t('Save Changes'));
}
/**
* Return a form object for the given resource type
*
* @param string $type The resource type for which to return a form
*
* @return Form
*/
public function getResourceForm($type)
{
if ($type === 'db') {
return new DbResourceForm();
} elseif ($type === 'ldap') {
return new LdapResourceForm();
} elseif ($type === 'livestatus') {
return new LivestatusResourceForm();
} elseif ($type === 'statusdat') {
return new StatusdatResourceForm();
} elseif ($type === 'file') {
return new FileResourceForm();
} else {
throw new InvalidArgumentException(sprintf(t('Invalid resource type "%s" provided'), $type));
}
}
/**
* Add a particular resource
*
* The backend to add is identified by the array-key `name'.
*
* @param array $values The values to extend the configuration with
*
* @return self
*
* @thrwos InvalidArgumentException In case the resource does already exist
*/
public function add(array $values)
{
$name = isset($values['name']) ? $values['name'] : '';
if (! $name) {
throw new InvalidArgumentException(t('Resource name missing'));
} elseif ($this->config->{$name} !== null) {
throw new InvalidArgumentException(t('Resource already exists'));
}
unset($values['name']);
$this->config->{$name} = $values;
return $this;
}
/**
* Edit a particular resource
*
* @param string $name The name of the resource to edit
* @param array $values The values to edit the configuration with
*
* @return array The edited configuration
*
* @throws InvalidArgumentException In case the resource does not exist
*/
public function edit($name, array $values)
{
if (! $name) {
throw new InvalidArgumentException(t('Old resource name missing'));
} elseif (! ($newName = isset($values['name']) ? $values['name'] : '')) {
throw new InvalidArgumentException(t('New resource name missing'));
} elseif (($resourceConfig = $this->config->get($name)) === null) {
throw new InvalidArgumentException(t('Unknown resource provided'));
}
unset($values['name']);
unset($this->config->{$name});
$this->config->{$newName} = array_merge($resourceConfig->toArray(), $values);
return $this->config->{$newName};
}
/**
* Remove a particular resource
*
* @param string $name The name of the resource to remove
*
* @return array The removed resource configuration
*
* @throws InvalidArgumentException In case the resource does not exist
*/
public function remove($name)
{
if (! $name) {
throw new InvalidArgumentException(t('Resource name missing'));
} elseif (($resourceConfig = $this->config->get($name)) === null) {
throw new InvalidArgumentException(t('Unknown resource provided'));
}
unset($this->config->{$name});
return $resourceConfig;
}
/**
* Add or edit a resource and save the configuration
*
* Performs a connectivity validation using the submitted values. A checkbox is
* added to the form to skip the check if it fails and redirection is aborted.
*
* @see Form::onSuccess()
*/
public function onSuccess(Request $request)
{
if (($el = $this->getElement('force_creation')) === null || false === $el->isChecked()) {
$resourceForm = $this->getResourceForm($this->getElement('type')->getValue());
if (method_exists($resourceForm, 'isValidResource') && false === $resourceForm->isValidResource($this)) {
$this->addElement($this->getForceCreationCheckbox());
return false;
}
}
$resource = $request->getQuery('resource');
try {
if ($resource === null) { // create new resource
$this->add($this->getValues());
$message = t('Resource "%s" has been successfully created');
} else { // edit existing resource
$this->edit($resource, $this->getValues());
$message = t('Resource "%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 resource 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)
{
$resource = $request->getQuery('resource');
if ($resource !== null) {
if ($resource === '') {
throw new ConfigurationError(t('Resource name missing'));
} elseif (false === isset($this->config->{$resource})) {
throw new ConfigurationError(t('Unknown resource provided'));
}
$configValues = $this->config->{$resource}->toArray();
$configValues['name'] = $resource;
$this->populate($configValues);
}
}
/**
* Return a checkbox to be displayed at the beginning of the form
* which allows the user to skip the connection validation
*
* @return Zend_Form_Element
*/
protected function getForceCreationCheckbox()
{
return $this->createElement(
'checkbox',
'force_creation',
array(
'order' => 0,
'ignore' => true,
'label' => t('Force Changes'),
'description' => t('Check this box to enforce changes without connectivity validation')
)
);
}
/**
* @see Form::createElemeents()
*/
public function createElements(array $formData)
{
$resourceType = isset($formData['type']) ? $formData['type'] : 'db';
$resourceTypes = array(
'file' => t('File'),
'statusdat' => 'Status.dat',
'livestatus' => 'Livestatus',
);
if ($resourceType === 'ldap' || Platform::extensionLoaded('ldap')) {
$resourceTypes['ldap'] = 'LDAP';
}
if ($resourceType === 'db' || Platform::extensionLoaded('mysql') || Platform::extensionLoaded('pgsql')) {
$resourceTypes['db'] = t('SQL Database');
}
$elements = array(
$this->createElement(
'text',
'name',
array(
'required' => true,
'label' => t('Resource Name'),
'description' => t('The unique name of this resource')
)
),
$this->createElement(
'select',
'type',
array(
'required' => true,
'autosubmit' => true,
'label' => t('Resource Type'),
'description' => t('The type of resource'),
'multiOptions' => $resourceTypes,
'value' => $resourceType
)
)
);
if (isset($formData['force_creation']) && $formData['force_creation']) {
// In case another error occured and the checkbox was displayed before
$elements[] = $this->getForceCreationCheckbox();
}
return array_merge($elements, $this->getResourceForm($resourceType)->createElements($formData));
}
}

View File

@ -1,444 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Form\Config;
use Exception;
use Icinga\Application\Platform;
use Zend_Config;
use Icinga\Web\Form;
use Icinga\Application\Icinga;
use Icinga\Data\ResourceFactory;
use Icinga\Web\Form\Element\Number;
use Icinga\Web\Form\Decorator\HelpText;
use Icinga\Web\Form\Decorator\ElementWrapper;
class ResourceForm extends Form
{
/**
* Initialize this form
*/
public function init()
{
$this->setName('form_config_resource');
$this->setSubmitLabel(t('Save Changes'));
}
/**
* @see Form::createElemeents()
*/
public function createElements(array $formData)
{
$elements = array();
$elements[] = $this->createElement(
'text',
'name',
array(
'required' => true,
'label' => t('Resource Name'),
'helptext' => t('The unique name of this resource')
)
);
$elements[] = $this->createElement(
'select',
'type',
array(
'required' => true,
'class' => 'autosubmit',
'label' => t('Resource Type'),
'helptext' => t('The type of resource'),
'multiOptions' => array(
'db' => t('SQL Database'),
'ldap' => 'LDAP',
'statusdat' => 'Status.dat',
'livestatus' => 'Livestatus',
'file' => t('File')
)
)
);
if (isset($formData['force_creation']) && $formData['force_creation']) {
// In case the resource name already exists and the checkbox was displayed before
$elements[] = $this->getForceCreationCheckbox();
}
if (false === isset($formData['type']) || $formData['type'] === 'db') {
return array_merge($elements, $this->getDbElements());
} elseif ($formData['type'] === 'statusdat') {
return array_merge($elements, $this->getStatusdatElements());
} elseif ($formData['type'] === 'livestatus') {
return array_merge($elements, $this->getLivestatusElements());
} elseif ($formData['type'] === 'ldap') {
return array_merge($elements, $this->getLdapElements());
} elseif ($formData['type'] === 'file') {
return array_merge($elements, $this->getFileElements());
}
}
/**
* Return whether the given values are complete/valid and check whether it is possible to connect to the resource
*
* If connection validation fails, a checkbox is prepended to the form to allow users to skip it.
*
* @param array $data The data to validate
*
* @return bool Whether the validation succeeded or not
*/
public function isValid($data)
{
if (false === parent::isValid($data)) {
return false;
}
if (
(false === isset($data['force_creation']) || false == $data['force_creation'])
&& false === $this->isValidResource()
) {
$this->addElement($this->getForceCreationCheckbox());
return false;
}
return true;
}
/**
* Return whether a connection can be established with the current resource configuration values
*
* @return bool Whether the connection validation was successful or not
*/
public function isValidResource()
{
list($name, $config) = $this->getResourceConfig();
try {
switch ($config['type']) {
case 'db':
/*
* It should be possible to run icingaweb without the pgsql or mysql extension or Zend-Pdo-Classes,
* in case they aren't actually used. When the user tries to create a resource that depends on an
* uninstalled extension, an error should be displayed.
*/
if ($config['db'] === 'mysql' && false === Platform::extensionLoaded('mysql')) {
$this->addErrorMessage(
t('You need to install the php extension "mysql" and the ' .
'Zend_Pdo_Mysql classes to use MySQL database resources.')
);
return false;
}
if ($config['db'] === 'pgsql' && false === Platform::extensionLoaded('pgsql')) {
$this->addErrorMessage(
t('You need to install the php extension "pgsql" and the ' .
'Zend_Pdo_Pgsql classes to use PostgreSQL database resources.')
);
return false;
}
$resource = ResourceFactory::createResource(new Zend_Config($config));
$resource->getConnection()->getConnection();
break;
case 'statusdat':
if (
false === file_exists($config['object_file'])
|| false === file_exists($config['status_file'])
) {
$this->addErrorMessage(
t('Connectivity validation failed. At least one of the provided files does not exist.')
);
return false;
}
break;
case 'livestatus':
$resource = ResourceFactory::createResource(new Zend_Config($config));
$resource->connect()->disconnect();
break;
case 'ldap':
$resource = ResourceFactory::createResource(new Zend_Config($config));
$resource->connect();
break;
case 'file':
if (false === file_exists($config['filename'])) {
$this->addErrorMessage(t('Connectivity validation failed. The provided file does not exist.'));
return false;
}
break;
}
} catch (Exception $e) {
$this->addErrorMessage(t('Connectivity validation failed, connection to the given resource not possible.'));
return false;
}
return true;
}
/**
* Return the resource configuration values and its name
*
* The first value is the name and the second one the values as array.
*
* @return array
*/
public function getResourceConfig()
{
$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 resource
* @param array $config The configuration values
*/
public function setResourceConfig($name, array $config)
{
$config['name'] = $name;
$this->populate($config);
}
/**
* Return a checkbox to be displayed at the beginning of the form
* which allows the user to skip the connection validation
*
* @return Zend_Form_Element
*/
protected function getForceCreationCheckbox()
{
return $this->createElement(
'checkbox',
'force_creation',
array(
'order' => 0,
'ignore' => true,
'label' => t('Force Changes'),
'helptext' => t('Check this box to enforce changes without connectivity validation')
)
);
}
/**
* Return all required elements to define a resource of type "db"
*
* @return array
*/
protected function getDbElements()
{
return array(
$this->createElement(
'select',
'db',
array(
'required' => true,
'label' => t('Database Type'),
'helptext' => t('The type of SQL database'),
'multiOptions' => array(
'mysql' => 'MySQL',
'pgsql' => 'PostgreSQL'
//'oracle' => 'Oracle'
)
)
),
$this->createElement(
'text',
'host',
array (
'required' => true,
'label' => t('Host'),
'helptext' => t('The hostname of the database'),
'value' => 'localhost'
)
),
new Number(
array(
'required' => true,
'name' => 'port',
'label' => t('Port'),
'helptext' => t('The port to use'),
'value' => 3306,
'decorators' => array( // The order is important!
'ViewHelper',
'Errors',
new ElementWrapper(),
new HelpText()
)
)
),
$this->createElement(
'text',
'dbname',
array(
'required' => true,
'label' => t('Database Name'),
'helptext' => t('The name of the database to use')
)
),
$this->createElement(
'text',
'username',
array (
'required' => true,
'label' => t('Username'),
'helptext' => t('The user name to use for authentication')
)
),
$this->createElement(
'password',
'password',
array(
'required' => true,
'renderPassword' => true,
'label' => t('Password'),
'helptext' => t('The password to use for authentication')
)
)
);
}
/**
* Return all required elements to define a resource of type "statusdat"
*
* @return array
*/
protected function getStatusdatElements()
{
return array(
$this->createElement(
'text',
'status_file',
array(
'required' => true,
'label' => t('Filepath'),
'helptext' => t('Location of your icinga status.dat file'),
'value' => realpath(Icinga::app()->getApplicationDir() . '/../var/status.dat')
)
),
$this->createElement(
'text',
'object_file',
array(
'required' => true,
'label' => t('Filepath'),
'helptext' => t('Location of your icinga objects.cache file'),
'value' => realpath(Icinga::app()->getApplicationDir() . '/../var/objects.cache')
)
)
);
}
/**
* Return all required elements to define a resource of type "livestatus"
*
* @return array
*/
protected function getLivestatusElements()
{
return array(
$this->createElement(
'text',
'socket',
array(
'required' => true,
'label' => t('Socket'),
'helptext' => t('The path to your livestatus socket used for querying monitoring data'),
'value' => realpath(Icinga::app()->getApplicationDir() . '/../var/rw/livestatus')
)
)
);
}
/**
* Return all required elements to define a resource of type "ldap"
*
* @return array
*/
protected function getLdapElements()
{
return array(
$this->createElement(
'text',
'hostname',
array(
'required' => true,
'allowEmpty' => false,
'label' => t('Host'),
'helptext' => t('The hostname or address of the LDAP server to use for authentication'),
'value' => 'localhost'
)
),
new Number(
array(
'required' => true,
'name' => 'port',
'label' => t('Port'),
'helptext' => t('The port of the LDAP server to use for authentication'),
'value' => 389,
'decorators' => array( // The order is important!
'ViewHelper',
'Errors',
new ElementWrapper(),
new HelpText()
)
)
),
$this->createElement(
'text',
'root_dn',
array(
'required' => true,
'label' => t('Root DN'),
'helptext' => t('The path where users can be found on the ldap server')
)
),
$this->createElement(
'text',
'bind_dn',
array(
'required' => true,
'label' => t('Bind DN'),
'helptext' => t('The user dn to use for querying the ldap server')
)
),
$this->createElement(
'password',
'bind_pw',
array(
'required' => true,
'renderPassword' => true,
'label' => t('Bind Password'),
'helptext' => t('The password to use for querying the ldap server')
)
)
);
}
/**
* Return all required elements to define a resource of type "file"
*
* @return array
*/
protected function getFileElements()
{
return array(
$this->createElement(
'text',
'filename',
array(
'required' => true,
'label' => t('Filepath'),
'helptext' => t('The filename to fetch information from')
)
),
$this->createElement(
'text',
'fields',
array(
'required' => true,
'label' => t('Pattern'),
'helptext' => t('The regular expression by which to identify columns')
)
)
);
}
}

View File

@ -486,7 +486,7 @@ msgstr "Die Objekt-Klasse welche benutzt wird, um Benutzer auf diesem LDAP-Serve
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:182
msgid "The password to use for authentication"
msgstr "Das Kennwort welche zur Authentifizierung benutzt werden soll"
msgstr "Das Kennwort welches zur Authentifizierung benutzt werden soll"
#: /usr/local/src/bugfix.master/application/forms/Config/ResourceForm.php:270
msgid "The password to use for querying the ldap server"

View File

@ -2,29 +2,41 @@
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
use \Zend_View_Helper_FormElement;
/**
* Helper to generate a number input
* Render number input controls
*/
class Zend_View_Helper_FormNumber extends \Zend_View_Helper_FormText
class Zend_View_Helper_FormNumber extends Zend_View_Helper_FormElement
{
/**
* Generates a html number input
* Render the number input control
*
* @access public
* @param string $name
* @param int $value
* @param array $attribs
*
* @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.
* @return string The rendered number input control
*/
public function formNumber($name, $value = null, $attribs = null)
{
return '<input type="number"'
. ' name="' . $this->view->escape($name) . '"'
. ' value="' . $this->view->escape($value) . '"'
. ' id="' . $this->view->escape($name) . '"'
. $this->_htmlAttribs($attribs)
. $this->getClosingBracket();
$info = $this->_getInfo($name, $value, $attribs);
extract($info); // name, id, value, attribs, options, listsep, disable
/** @var string $id */
/** @var bool $disable */
$disabled = '';
if ($disable) {
$disabled = ' disabled="disabled"';
}
$html5 = sprintf(
'<input type="number" name="%s" id="%s" value="%s"%s%s%s',
$this->view->escape($name),
$this->view->escape($id),
$this->view->escape($value),
$disabled,
$this->_htmlAttribs($attribs),
$this->getClosingBracket()
);
return $html5;
}
}

View File

@ -2,10 +2,9 @@
<?= $tabs; ?>
</div>
<div class="content" data-base-target="_next">
<?= $messageBox; ?>
<p>
<a href="<?= $this->href('/config/createresource') ?>">
<?= $this->icon('create.png'); ?> <?= $this->translate('Create a new resource'); ?>
<a href="<?= $this->href('/config/createresource'); ?>">
<?= $this->icon('create.png'); ?> <?= $this->translate('Create A New Resource'); ?>
</a>
</p>
<table class="action">
@ -17,12 +16,12 @@
<?php foreach ($this->resources as $name => $resource): ?>
<tr>
<td>
<a href="<?= $this->href('config/editresource', array('resource' => $name)) ?>">
<?= $this->icon('edit.png') ?> <?= $this->escape($name); ?>
<a href="<?= $this->href('config/editresource', array('resource' => $name)); ?>">
<?= $this->icon('edit.png'); ?> <?= $this->escape($name); ?>
</a>
</td>
<td style="text-align: center">
<a href="<?= $this->href('config/removeresource', array('resource' => $name)) ?>">
<a href="<?= $this->href('config/removeresource', array('resource' => $name)); ?>">
<?= $this->icon('remove.png'); ?>
</a>
</td>

View File

@ -1,4 +1,3 @@
<?= $messageBox; ?>
<h4><?= $this->translate('Create a new resource'); ?></h4>
<p><?= $this->translate('Resources are entities that provide data to Icingaweb.'); ?></p>
<h4><?= $this->translate('Create A New Resource'); ?></h4>
<p><?= $this->translate('Resources are entities that provide data to Icinga Web 2.'); ?></p>
<?= $form; ?>

View File

@ -1,3 +1,2 @@
<h4><?= $this->translate('Edit Existing Resource'); ?></h4>
<?= $messageBox; ?>
<?= $form; ?>

View File

@ -1,3 +1,2 @@
<h4><?= $this->translate('Remove Existing Resource'); ?></h4>
<?= $messageBox; ?>
<?= $form; ?>

View File

@ -11,7 +11,4 @@
<hr />
<pre><?= $this->escape($stackTrace) ?></pre>
<?php endif ?>
<?php if (isset($this->messageBox)) : ?>
<?= $this->messageBox->render(); ?>
<? endif ?>
</div>

View File

@ -7,7 +7,6 @@ namespace Icinga;
use DateTimeZone;
use InvalidArgumentException;
use Icinga\User\Preferences;
use Icinga\User\Message;
/**
* This class represents an authorized user
@ -98,13 +97,6 @@ class User
*/
protected $preferences;
/**
* Queued notifications for this user.
*
* @var array()
*/
protected $messages;
/**
* Creates a user object given the provided information
*
@ -382,38 +374,6 @@ class User
return new DateTimeZone($tz);
}
/**
* Add a message that can be accessed from future requests, to this user.
*
* This function does NOT automatically write to the session, messages will not be persisted until you do.
*
* @param Message $msg The message
*/
public function addMessage(Message $msg)
{
$this->messages[] = $msg;
}
/**
* Get all currently pending messages
*
* @return array The messages
*/
public function getMessages()
{
return isset($this->messages) ? $this->messages : array();
}
/**
* Remove all messages from this user
*
* This function does NOT automatically write the session, messages will not be persisted until you do.
*/
public function clearMessages()
{
$this->messages = null;
}
/**
* Set additional remote user information
*

View File

@ -1,59 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\User;
use Zend_Log;
/**
* Class Message
*
* A Message with an additional logging level to indicate the type.
*
* @package Icinga\User
*/
class Message
{
/**
* The content of this message
*
* @var string
*/
private $message;
/**
* The logging-level of this message
*/
private $level;
/**
* Create a new Message
*
* @param string $message The message content
* @param $level The status of the message
* * Zend_Log::INFO
* * Zend_Log::ERR
*/
public function __construct($message, $level = Zend_Log::INFO)
{
$this->message = $message;
$this->level = $level;
}
/**
* @return string
*/
public function getMessage()
{
return $this->message;
}
/**
* @return The
*/
public function getLevel()
{
return $this->level;
}
}

View File

@ -1,75 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Web\Controller;
use Zend_Log;
use Icinga\Web\Session;
use Icinga\User\Message;
use Icinga\Authentication\Manager as AuthenticationManager;
/**
* Base class for Configuration Controllers
*
* Module preferences use this class to make sure they are automatically
* added to the application's configuration dialog. If you create a subclass of
* BasePreferenceController and overwrite @see init(), make sure you call
* parent::init(), otherwise you won't have the $tabs property in your view.
*/
class BaseConfigController extends ActionController
{
/**
* Send a message with the logging level Zend_Log::INFO to the current user and
* commit the changes to the underlying session.
*
* @param $msg The message content
*/
protected function addSuccessMessage($msg)
{
AuthenticationManager::getInstance()->getUser()->addMessage(
new Message($msg, Zend_Log::INFO)
);
Session::getSession()->write();
}
/**
* Send a message with the logging level Zend_Log::ERR to the current user and
* commit the changes to the underlying session.
*
* @param $msg The message content
*/
protected function addErrorMessage($msg)
{
AuthenticationManager::getInstance()->getUser()->addMessage(
new Message($msg, Zend_Log::ERR)
);
Session::getSession()->write();
}
/**
* Send a message with the logging level Zend_Log::WARN to the current user and
* commit the changes to the underlying session.
*
* @param $msg The message content
*/
protected function addWarningMessage($msg)
{
AuthenticationManager::getInstance()->getUser()->addMessage(
new Message($msg, Zend_Log::WARN)
);
Session::getSession()->write();
}
/*
* Return an array of tabs provided by this configuration controller.
*
* Those tabs will automatically be added to the application's configuration dialog
*
* @return array
*/
public static function createProvidedTabs()
{
return array();
}
}

View File

@ -8,9 +8,7 @@ use LogicException;
use Zend_Form;
use Zend_View_Interface;
use Icinga\Application\Icinga;
use Icinga\Web\Form\Decorator\HelpText;
use Icinga\Web\Form\Decorator\NoScriptApply;
use Icinga\Web\Form\Decorator\ElementWrapper;
use Icinga\Web\Form\Element\CsrfCounterMeasure;
/**
@ -99,6 +97,7 @@ class Form extends Zend_Form
if ($this->onSuccess !== null && false === is_callable($this->onSuccess)) {
throw new LogicException('The option `onSuccess\' is not callable');
}
if (! isset($options['elementDecorators'])) {
$options['elementDecorators'] = array(
'ViewHelper',
@ -108,6 +107,7 @@ class Form extends Zend_Form
array('HtmlTag', array('tag' => 'div'))
);
}
parent::__construct($options);
}
@ -321,7 +321,7 @@ class Form extends Zend_Form
*
* @param Request $request The current request
*/
public function onShow(Request $request)
public function onRequest(Request $request)
{
}
@ -372,6 +372,7 @@ class Form extends Zend_Form
if (is_array($options) && ! isset($options['disableLoadDefaultDecorators'])) {
$options['disableLoadDefaultDecorators'] = true;
}
$el = parent::createElement($type, $name, $options);
if ($el && $el->getAttrib('autosubmit')) {
$el->addDecorator(new NoScriptApply()); // Non-JS environments
@ -386,6 +387,7 @@ class Form extends Zend_Form
$el->setAttrib('class', $class); // JS environments
unset($el->autosubmit);
}
return $el;
}
@ -439,7 +441,7 @@ class Form extends Zend_Form
* Process the given request using this form
*
* Redirects to the url set with setRedirectUrl() upon success. See onSuccess()
* and onShow() wherewith you can customize the processing logic.
* and onRequest() wherewith you can customize the processing logic.
*
* @param Request $request The request to be processed
*
@ -465,7 +467,7 @@ class Form extends Zend_Form
$this->isValidPartial($formData);
}
} else {
$this->onShow($request);
$this->onRequest($request);
}
return $request;
@ -555,6 +557,7 @@ class Form extends Zend_Form
if ($this->loadDefaultDecoratorsIsDisabled()) {
return $this;
}
$decorators = $this->getDecorators();
if (empty($decorators)) {
if ($this->viewScript) {
@ -563,11 +566,13 @@ class Form extends Zend_Form
'form' => $this
));
} else {
$this
$this->addDecorator('FormErrors', array('onlyCustomFormErrors' => true))
->addDecorator('FormElements')
//->addDecorator('HtmlTag', array('tag' => 'dl', 'class' => 'zend_form'))
->addDecorator('Form');
}
}
return $this;
}

View File

@ -4,38 +4,37 @@
namespace Icinga\Web\Form\Element;
use Zend_Form_Element_Xhtml;
use Zend_Form_Element;
/**
* Number form element
* A number input control
*/
class Number extends Zend_Form_Element_Xhtml
class Number extends Zend_Form_Element
{
/**
* Default form view helper to use for rendering
* Disable default decorators
*
* \Icinga\Web\Form sets default decorators for elements.
*
* @var bool
*
* @see \Icinga\Web\Form::__construct() For default element decorators.
*/
protected $_disableLoadDefaultDecorators = true;
/**
* Form view helper to use for rendering
*
* @var string
*/
public $helper = "formNumber";
public $helper = 'formNumber';
/**
* Check whether $value is of type integer
*
* @param string $value The value to check
* @param mixed $context Context to use
*
* @return bool
* (non-PHPDoc)
* @see \Zend_Form_Element::init() For the method documentation.
*/
public function isValid($value, $context = null)
public function init()
{
if (parent::isValid($value, $context)) {
if (is_numeric($value)) {
return true;
}
$this->addError(t('Please enter a number.'));
}
return false;
$this->addValidator('Int');
}
}

View File

@ -0,0 +1,58 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Web\Form\Validator;
use Zend_Validate_Abstract;
/**
* Validator that interprets the value as a filepath and checks if it's readable
*
* This validator should be preferred due to Zend_Validate_File_Exists is
* getting confused if there is another element in the form called `name'.
*/
class ReadablePathValidator extends Zend_Validate_Abstract
{
/**
* The messages to write on different error states
*
* @var array
*
* @see Zend_Validate_Abstract::$_messageTemplates
*/
protected $_messageTemplates;
/**
* Initialize this validator
*/
public function __construct()
{
$this->_messageTemplates = array(
'NOT_READABLE' => t('Path is not readable'),
'DOES_NOT_EXIST' => t('Path does not exist')
);
}
/**
* Check whether the given value is a readable filepath
*
* @param string $value The value submitted in the form
* @param mixed $context The context of the form
*
* @return bool Whether the value was successfully validated
*/
public function isValid($value, $context = null)
{
if (false === file_exists($value)) {
$this->_error('DOES_NOT_EXIST');
return false;
}
if (false === is_readable($value)) {
$this->_error('NOT_READABLE');
}
return true;
}
}

View File

@ -1,133 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Web\Widget;
use Zend_Log;
use Zend_Form;
use Zend_View_Abstract;
use Icinga\User;
use Icinga\User\Message;
use Icinga\Web\Session;
use Icinga\Authentication\Manager as AuthenticationManager;
/**
* Displays a set of alert messages to the user.
*
* The messages are fetched automatically from the current AuthenticationManager,
* but this is done lazily when render() is called, to ensure that messages will
* always be displayed before they are cleared.
*/
class AlertMessageBox extends AbstractWidget
{
/**
* Remove all messages from the current user, return them and commit
* changes to the underlying session.
*
* @return array The messages
*/
protected function getAndClearMessages()
{
$messages = $this->user->getMessages();
$this->user->clearMessages();
Session::getSession()->write();
return $messages;
}
/**
* The displayed alert messages
*
* @var array
*/
private $messages = array();
/**
* The user to fetch the messages from
*
* @var User
*/
private $user;
/**
* The available states.
*
* @var array
*/
private $states = array(
Zend_Log::INFO => array(
'state' => 'alert-success',
'icon' => 'success.png'
),
Zend_Log::NOTICE => array(
'state' => 'alert-info',
'icon' => 'info.png'
),
Zend_Log::WARN => array(
'state' => 'alert-warning',
'icon' => 'warning.png'
),
Zend_Log::ERR => array(
'state' => 'alert-danger',
'icon' => 'error.png'
)
);
/**
* Create a new AlertBox
*
* @param boolean showUserMessages If the current user messages should be displayed
* in this AlertMessageBox. Defaults to false
*/
public function __construct($showUserMessages = false)
{
if ($showUserMessages) {
$this->user = AuthenticationManager::getInstance()->getUser();
}
}
/**
* Add a new error
*
* @param $error
*/
public function addError($error)
{
$this->messages[] = new Message($error, Zend_Log::ERR);
}
/**
* Add the error messages of the given Zend_Form
*/
public function addForm(Zend_Form $form)
{
foreach ($form->getErrorMessages() as $error) {
$this->addError($error);
}
}
/**
* Output the HTML of the AlertBox
*
* @return string
*/
public function render(Zend_View_Abstract $view = null)
{
$html = '';
if (isset($this->user)) {
$this->messages = array_merge($this->messages, $this->getAndClearMessages());
}
foreach ($this->messages as $message) {
$level = $message->getLevel();
if (!array_key_exists($level, $this->states)) {
continue;
}
$alert = $this->states[$level];
$html .= '<div class="alert ' . $alert['state']. '">' .
$this->view()->icon($alert['icon']) .
'<strong>' . htmlspecialchars($message->getMessage()) . '</strong>' .
'</div>';
}
return $html;
}
}