Adjust resource form to suit the new form builder implementation

refs #5525
This commit is contained in:
Johannes Meyer 2014-07-23 16:39:15 +02:00
parent c8d61f78e7
commit 936f65eb27
1 changed files with 337 additions and 383 deletions

View File

@ -6,350 +6,46 @@ namespace Icinga\Form\Config;
use Exception; use Exception;
use Zend_Config; use Zend_Config;
use Zend_Form_Element_Checkbox;
use Icinga\Web\Form; use Icinga\Web\Form;
use Icinga\Application\Icinga;
use Icinga\Data\ResourceFactory; use Icinga\Data\ResourceFactory;
use Icinga\Web\Form\Element\Number; use Icinga\Web\Form\Element\Number;
use Icinga\Web\Form\Decorator\HelpText; use Icinga\Web\Form\Decorator\HelpText;
use Icinga\Web\Form\Decorator\ElementWrapper;
class ResourceForm extends Form class ResourceForm extends Form
{ {
/** /**
* The resource * Initialize this form
*
* @var Zend_Config
*/ */
protected $resource; public function init()
/**
* The (new) name of the resource
*
* @var string
*/
protected $name;
/**
* The old name of the resource
*
* @var string
*/
protected $oldName;
/**
* Set the current resource name
*
* @param string $name The name to set
*/
public function setName($name)
{ {
$this->name = $name; $this->setName('form_config_resource');
} }
/** /**
* Get the current resource name * @see Form::createElemeents()
*
* @return null|string
*/ */
public function getName() public function createElements(array $formData)
{ {
$name = $this->getValue('resource_all_name'); $elements = array();
if (!$name) { $elements[] = $this->createElement(
return $this->name;
}
return $name;
}
/**
* Set the original name of the resource
*
* @param string $name The name to set
*/
public function setOldName($name)
{
$this->oldName = $name;
}
/**
* Get the resource name that was initially set
*
* @return null|string
*/
public function getOldName()
{
$oldName = $this->getValue('resource_all_name_old');
if (!$oldName) {
return $this->oldName;
}
return $oldName;
}
/**
* Set the resource configuration to edit.
*
* @param Zend_Config $resource The config to set
*/
public function setResource(Zend_Config $resource)
{
$this->resource = $resource;
}
/**
* Get the current resource configuration.
*
* @return Zend_Config
*/
public function getResource()
{
if (!isset($this->resource)) {
$this->resource = new Zend_Config(array('type' => 'db'));
}
return $this->resource;
}
protected function addDbForm()
{
$this->addElement(
'select',
'resource_db_db',
array(
'required' => true,
'label' => t('Database Type'),
'helptext' => t('The type of SQL database you want to create.'),
'value' => $this->getResource()->get('db', 'mysql'),
'multiOptions' => array(
'mysql' => 'MySQL',
'pgsql' => 'PostgreSQL'
//'oracle' => 'Oracle'
)
)
);
$this->addElement(
'text', 'text',
'resource_db_host', 'name',
array (
'required' => true,
'label' => t('Host'),
'helptext' => t('The hostname of the database.'),
'value' => $this->getResource()->get('host', 'localhost')
)
);
$this->addElement(
new Number(
array(
'name' => 'resource_db_port',
'required' => true,
'label' => t('Port'),
'helptext' => t('The port to use.'),
'value' => $this->getResource()->get('port', 3306)
)
)
);
$this->addElement(
'text',
'resource_db_dbname',
array(
'required' => true,
'label' => t('Database Name'),
'helptext' => t('The name of the database to use'),
'value' => $this->getResource()->get('dbname', '')
)
);
$this->addElement(
'text',
'resource_db_username',
array (
'required' => true,
'label' => t('Username'),
'helptext' => t('The user name to use for authentication.'),
'value' => $this->getResource()->get('username', '')
)
);
$this->addElement(
'password',
'resource_db_password',
array(
'required' => true,
'renderPassword' => true,
'label' => t('Password'),
'helptext' => t('The password to use for authentication'),
'value' => $this->getResource()->get('password', '')
)
);
}
protected function addStatusdatForm()
{
$this->addElement(
'text',
'resource_statusdat_status_file',
array(
'required' => true,
'label' => t('Filepath'),
'helptext' => t('Location of your icinga status.dat file'),
'value' => $this->getResource()->get('status_file', '/usr/local/icinga/var/status.dat')
)
);
$this->addElement(
'text',
'resource_statusdat_object_file',
array(
'required' => true,
'label' => t('Filepath'),
'helptext' => t('Location of your icinga objects.cache file'),
'value' => $this->getResource()->get('status_file', '/usr/local/icinga/var/objects.cache')
)
);
}
protected function addLivestatusForm()
{
$this->addElement(
'text',
'resource_livestatus_socket',
array(
'required' => true,
'label' => t('Socket'),
'helptext' => t('The path to your livestatus socket used for querying monitoring data'),
'value' => $this->getResource()->get('socket', '/usr/local/icinga/var/rw/livestatus')
)
);
}
protected function addLdapForm()
{
$this->addElement(
'text',
'resource_ldap_hostname',
array(
'required' => true,
'allowEmpty' => false,
'label' => t('Host'),
'helptext' => t('The hostname or address of the LDAP server to use for authentication'),
'value' => $this->getResource()->get('hostname', 'localhost')
)
);
$this->addElement(
'text',
'resource_ldap_root_dn',
array(
'required' => true,
'label' => t('Root DN'),
'helptext' => t('The path where users can be found on the ldap server'),
'value' => $this->getResource()->get('root_dn', 'ou=people,dc=icinga,dc=org')
)
);
$this->addElement(
'text',
'resource_ldap_bind_dn',
array(
'required' => true,
'label' => t('Bind DN'),
'helptext' => t('The user dn to use for querying the ldap server'),
'value' => $this->getResource()->get('bind_dn', 'cn=admin,cn=config')
)
);
$this->addElement(
'password',
'resource_ldap_bind_pw',
array(
'required' => true,
'renderPassword' => true,
'label' => t('Bind Password'),
'helptext' => t('The password to use for querying the ldap server'),
'value' => $this->getResource()->get('bind_pw', '')
)
);
}
protected function addFileForm()
{
$this->addElement(
'text',
'resource_file_filename',
array(
'required' => true,
'label' => t('Filepath'),
'helptext' => t('The filename to fetch information from'),
'value' => $this->getResource()->get('filename', '')
)
);
$this->addElement(
'text',
'resource_file_fields',
array(
'required' => true,
'label' => t('Pattern'),
'helptext' => t('The regular expression by which to identify columns'),
'value' => $this->getResource()->get('fields', '')
)
);
}
protected function addNameFields()
{
$this->addElement(
'text',
'resource_all_name',
array( array(
'required' => true, 'required' => true,
'label' => t('Resource Name'), 'label' => t('Resource Name'),
'helptext' => t('The unique name of this resource'), 'helptext' => t('The unique name of this resource')
'value' => $this->getName()
) )
); );
$elements[] = $this->createElement(
$this->addElement(
'hidden',
'resource_all_name_old',
array(
'value' => $this->getOldName()
)
);
}
/**
* Add checkbox at the beginning of the form which allows to skip connection validation
*/
protected function addForceCreationCheckbox()
{
$checkbox = new Zend_Form_Element_Checkbox(
array(
'order' => 0,
'name' => 'resource_force_creation',
'label' => t('Force Changes'),
'helptext' => t('Check this box to enforce changes without connectivity validation')
)
);
$checkbox->addDecorator(new HelpText());
$this->addElement($checkbox);
}
/**
* Add a select box for choosing the type to use for this backend
*/
protected function addTypeSelectionBox()
{
$this->addElement(
'select', 'select',
'resource_type', 'type',
array( array(
'required' => true, 'required' => true,
'class' => 'autosubmit',
'label' => t('Resource Type'), 'label' => t('Resource Type'),
'helptext' => t('The type of resource'), 'helptext' => t('The type of resource'),
'value' => $this->getResource()->type,
'multiOptions' => array( 'multiOptions' => array(
'db' => t('SQL Database'), 'db' => t('SQL Database'),
'ldap' => 'LDAP', 'ldap' => 'LDAP',
@ -359,60 +55,92 @@ class ResourceForm extends Form
) )
) )
); );
$this->enableAutoSubmit(array('resource_type'));
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());
}
} }
/** /**
* Validate this form with the Zend validation mechanism and perform a validation of the connection * @see Form::addSubmitButton()
*/
public function addSubmitButton()
{
$this->addElement(
'submit',
'btn_submit',
array(
'label' => t('Save Changes')
)
);
return $this;
}
/**
* Return whether the given values are complete/valid and check whether it is possible to connect to the resource
* *
* If validation fails, the 'resource_force_creation' checkbox is prepended to the form to allow users to * If connection validation fails, a checkbox is prepended to the form to allow users to skip it.
* skip the connection validation
* *
* @param array $data The form input to validate * @param array $data The data to validate
* *
* @return bool True when validation succeeded, false if not * @return bool Whether the validation succeeded or not
*/ */
public function isValid($data) public function isValid($data)
{ {
if (!parent::isValid($data)) { if (false === parent::isValid($data)) {
return false; return false;
} }
if (isset($data['resource_force_creation']) && $data['resource_force_creation']) {
return true; if (
} (false === isset($data['force_creation']) || false == $data['force_creation'])
if (!$this->isValidResource()) { && false === $this->isValidResource()
$this->addForceCreationCheckbox(); ) {
$this->addElement($this->getForceCreationCheckbox());
return false; return false;
} }
return true; return true;
} }
/** /**
* Test if the changed resource is a valid resource, by instantiating it and * Return whether a connection can be established with the current resource configuration values
* checking if a connection is possible
* *
* @return bool True when a connection to the resource is possible * @return bool Whether the connection validation was successful or not
*/ */
public function isValidResource() public function isValidResource()
{ {
$config = $this->getConfig(); list($name, $config) = $this->getResourceConfig();
try { try {
switch ($config->type) { switch ($config['type']) {
case 'db': case 'db':
/* /*
* It should be possible to run icingaweb without the pgsql or mysql extension or Zend-Pdo-Classes, * 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 * in case they aren't actually used. When the user tries to create a resource that depends on an
* uninstalled extension, an error should be displayed. * uninstalled extension, an error should be displayed.
*/ */
if ($config->db === 'mysql' && !ResourceFactory::mysqlAvailable()) { if ($config['db'] === 'mysql' && false === ResourceFactory::mysqlAvailable()) {
$this->addErrorMessage( $this->addErrorMessage(
t('You need to install the php extension "mysql" and the ' . t('You need to install the php extension "mysql" and the ' .
'Zend_Pdo_Mysql classes to use MySQL database resources.') 'Zend_Pdo_Mysql classes to use MySQL database resources.')
); );
return false; return false;
} }
if ($config->db === 'pgsql' && !ResourceFactory::pgsqlAvailable()) { if ($config['db'] === 'pgsql' && false === ResourceFactory::pgsqlAvailable()) {
$this->addErrorMessage( $this->addErrorMessage(
t('You need to install the php extension "pgsql" and the ' . t('You need to install the php extension "pgsql" and the ' .
'Zend_Pdo_Pgsql classes to use PostgreSQL database resources.') 'Zend_Pdo_Pgsql classes to use PostgreSQL database resources.')
@ -420,30 +148,31 @@ class ResourceForm extends Form
return false; return false;
} }
$resource = ResourceFactory::createResource($config); $resource = ResourceFactory::createResource(new Zend_Config($config));
$resource->getConnection()->getConnection(); $resource->getConnection()->getConnection();
break; break;
case 'statusdat': case 'statusdat':
if (!file_exists($config->object_file) || !file_exists($config->status_file)) { if (
false === file_exists($config['object_file'])
|| false === file_exists($config['status_file'])
) {
$this->addErrorMessage( $this->addErrorMessage(
t('Connectivity validation failed, the provided file does not exist.') t('Connectivity validation failed. At least one of the provided files does not exist.')
); );
return false; return false;
} }
break; break;
case 'livestatus': case 'livestatus':
$resource = ResourceFactory::createResource($config); $resource = ResourceFactory::createResource(new Zend_Config($config));
$resource->connect()->disconnect(); $resource->connect()->disconnect();
break; break;
case 'ldap': case 'ldap':
$resource = ResourceFactory::createResource($config); $resource = ResourceFactory::createResource(new Zend_Config($config));
$resource->connect(); $resource->connect();
break; break;
case 'file': case 'file':
if (!file_exists($config->filename)) { if (false === file_exists($config['filename'])) {
$this->addErrorMessage( $this->addErrorMessage(t('Connectivity validation failed. The provided file does not exist.'));
t('Connectivity validation failed, the provided file does not exist.')
);
return false; return false;
} }
break; break;
@ -456,51 +185,276 @@ class ResourceForm extends Form
return true; return true;
} }
public function create() /**
* 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()
{ {
$this->addNameFields(); $values = $this->getValues();
$this->addTypeSelectionBox(); $name = $values['name'];
unset($values['name']);
switch ($this->getRequest()->getParam('resource_type', $this->getResource()->type)) { unset($values['btn_submit']);
case 'db': unset($values['force_creation']);
$this->addDbForm(); unset($values[$this->getTokenElementName()]);
break; return array($name, $values);
case 'statusdat':
$this->addStatusdatForm();
break;
case 'livestatus':
$this->addLivestatusForm();
break;
case 'ldap':
$this->addLdapForm();
break;
case 'file':
$this->addFileForm();
break;
}
$this->setSubmitLabel('{{SAVE_ICON}} Save Changes');
} }
/** /**
* Return a configuration containing the backend settings entered in this form * Populate the form with the given configuration values
* *
* @return Zend_Config The updated configuration for this backend * @param string $name The name of the resource
* @param array $config The configuration values
*/ */
public function getConfig() public function setResourceConfig($name, array $config)
{ {
$values = $this->getValues(); $config['name'] = $name;
$this->populate($config);
}
$result = array('type' => $values['resource_type']); /**
foreach ($values as $key => $value) { * Return a checkbox to be displayed at the beginning of the form
if ($key !== 'resource_type' && $key !== 'resource_all_name' && $key !== 'resource_all_name_old') { * which allows the user to skip the connection validation
$configKey = explode('_', $key, 3); *
if (count($configKey) === 3) { * @return Zend_Form_Element
$result[$configKey[2]] = $value; */
} protected function getForceCreationCheckbox()
} {
} return $this->createElement(
'checkbox',
'force_creation',
array(
'order' => 0,
'label' => t('Force Changes'),
'helptext' => t('Check this box to enforce changes without connectivity validation')
)
);
}
return new Zend_Config($result); /**
* 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')
)
)
);
} }
} }