Merge branch 'feature/conditional-fields-13253'

This commit is contained in:
Thomas Gelf 2016-12-14 17:43:10 +01:00
commit af0df901f4
12 changed files with 225 additions and 45 deletions

View File

@ -2,9 +2,12 @@
namespace Icinga\Module\Director\Forms;
use Icinga\Module\Director\Objects\IcingaHost;
use Icinga\Module\Director\Objects\IcingaObject;
use Icinga\Module\Director\Objects\DirectorDatafield;
use Icinga\Module\Director\Objects\IcingaService;
use Icinga\Module\Director\Web\Form\DirectorObjectForm;
use Icinga\Module\Director\Web\Form\IcingaObjectFieldLoader;
class IcingaObjectFieldForm extends DirectorObjectForm
{
@ -20,8 +23,9 @@ class IcingaObjectFieldForm extends DirectorObjectForm
public function setup()
{
$type = $this->icingaObject->getShortTableName();
$this->addHidden($type . '_id', $this->icingaObject->get('id'));
$object = $this->icingaObject;
$type = $object->getShortTableName();
$this->addHidden($type . '_id', $object->get('id'));
$this->addHtmlHint(
'Custom data fields allow you to easily fill custom variables with'
@ -48,8 +52,8 @@ class IcingaObjectFieldForm extends DirectorObjectForm
$argumentVars = array();
$argumentVarDescriptions = array();
if ($this->icingaObject->supportsArguments()) {
foreach ($this->icingaObject->arguments() as $arg) {
if ($object->supportsArguments()) {
foreach ($object->arguments() as $arg) {
if ($arg->argument_format === 'string') {
$val = $arg->argument_value;
// TODO: create var::extractMacros or so
@ -131,13 +135,48 @@ class IcingaObjectFieldForm extends DirectorObjectForm
)
));
$filterFields = array();
$prefix = null;
if ($object instanceof IcingaHost) {
$prefix = 'host.vars.';
} elseif ($object instanceof IcingaService) {
$prefix = 'service.vars.';
}
if ($prefix) {
$loader = new IcingaObjectFieldLoader($object);
$fields = $loader->getFields();
foreach ($fields as $varName => $field) {
$filterFields[$prefix . $field->varname] = $field->caption;
}
$this->addFilterElement('var_filter', array(
'description' => $this->translate(
'You might want to show this field only when certain conditions are met.'
. ' Otherwise it will not be available and values eventually set before'
. ' will be cleared once stored'
),
'columns' => $filterFields,
));
$this->addDisplayGroup(array($this->getElement('var_filter')), 'field_filter', array(
'decorators' => array(
'FormElements',
array('HtmlTag', array('tag' => 'dl')),
'Fieldset',
),
'order' => 30,
'legend' => $this->translate('Show based on filter')
));
}
$this->setButtons();
}
protected function onRequest()
{
parent::onRequest();
if ($this->getSentValue('delete') === $this->translate('Delete')) {
$this->object()->delete();
$this->setSuccessUrl($this->getSuccessUrl()->without('field_id'));
@ -154,13 +193,14 @@ class IcingaObjectFieldForm extends DirectorObjectForm
'varname' => trim($fieldId, '$'),
'caption' => $this->getValue('caption'),
'description' => $this->getValue('description'),
'datatype' => 'Icinga\Module\Director\DataType\DataTypeString'
'datatype' => 'Icinga\Module\Director\DataType\DataTypeString',
));
$field->store($this->getDb());
$this->setElementValue('datafield_id', $field->get('id'));
$this->object()->set('datafield_id', $field->get('id'));
}
$this->object()->set('var_filter', $this->getValue('var_filter'));
return parent::onSuccess();
}
}

View File

@ -2,17 +2,16 @@
namespace Icinga\Module\Director\Objects;
use Icinga\Module\Director\Data\Db\DbObject;
class IcingaCommandField extends DbObject
class IcingaCommandField extends IcingaObjectField
{
protected $keyName = array('command_id', 'datafield_id');
protected $table = 'icinga_command_field';
protected $defaultProperties = array(
'command_id' => null,
'datafield_id' => null,
'is_required' => null
'command_id' => null,
'datafield_id' => null,
'is_required' => null,
'var_filter' => null,
);
}

View File

@ -2,17 +2,16 @@
namespace Icinga\Module\Director\Objects;
use Icinga\Module\Director\Data\Db\DbObject;
class IcingaHostField extends DbObject
class IcingaHostField extends IcingaObjectField
{
protected $keyName = array('host_id', 'datafield_id');
protected $table = 'icinga_host_field';
protected $defaultProperties = array(
'host_id' => null,
'datafield_id' => null,
'is_required' => null
'host_id' => null,
'datafield_id' => null,
'is_required' => null,
'var_filter' => null,
);
}

View File

@ -2,9 +2,7 @@
namespace Icinga\Module\Director\Objects;
use Icinga\Module\Director\Data\Db\DbObject;
class IcingaNotificationField extends DbObject
class IcingaNotificationField extends IcingaObjectField
{
protected $keyName = array('notification_id', 'datafield_id');
@ -13,6 +11,7 @@ class IcingaNotificationField extends DbObject
protected $defaultProperties = array(
'notification_id' => null,
'datafield_id' => null,
'is_required' => null
'is_required' => null,
'var_filter' => null,
);
}

View File

@ -0,0 +1,28 @@
<?php
namespace Icinga\Module\Director\Objects;
use Icinga\Data\Filter\Filter;
use Icinga\Module\Director\Data\Db\DbObject;
abstract class IcingaObjectField extends DbObject
{
/**
*
* @param Filter|string $filter
*
* @throws ProgrammingError
*
* @return self
* @codingStandardsIgnoreStart
*/
protected function setVar_filter($value)
{
// @codingStandardsIgnoreEnd
if ($value instanceof Filter) {
$value = $value->toQueryString();
}
return $this->reallySet('var_filter', $value);
}
}

View File

@ -2,17 +2,16 @@
namespace Icinga\Module\Director\Objects;
use Icinga\Module\Director\Data\Db\DbObject;
class IcingaServiceField extends DbObject
class IcingaServiceField extends IcingaObjectField
{
protected $keyName = array('service_id', 'datafield_id');
protected $table = 'icinga_service_field';
protected $defaultProperties = array(
'service_id' => null,
'datafield_id' => null,
'is_required' => null
'service_id' => null,
'datafield_id' => null,
'is_required' => null,
'var_filter' => null,
);
}

View File

@ -2,17 +2,16 @@
namespace Icinga\Module\Director\Objects;
use Icinga\Module\Director\Data\Db\DbObject;
class IcingaUserField extends DbObject
class IcingaUserField extends IcingaObjectField
{
protected $keyName = array('user_id', 'datafield_id');
protected $table = 'icinga_user_field';
protected $defaultProperties = array(
'user_id' => null,
'datafield_id' => null,
'is_required' => null
'user_id' => null,
'datafield_id' => null,
'is_required' => null,
'var_filter' => null,
);
}

View File

@ -3,9 +3,13 @@
namespace Icinga\Module\Director\Web\Form;
use Exception;
use Icinga\Data\Filter\Filter;
use Icinga\Data\Filter\FilterExpression;
use Icinga\Exception\IcingaException;
use Icinga\Module\Director\Objects\IcingaHost;
use Icinga\Module\Director\Objects\IcingaObject;
use Icinga\Module\Director\Objects\DirectorDatafield;
use Icinga\Module\Director\Objects\IcingaService;
use stdClass;
use Zend_Form_Element as ZfElement;
@ -179,7 +183,11 @@ class IcingaObjectFieldLoader
*/
protected function attachFieldsToForm(DirectorObjectForm $form)
{
$elements = $this->getElements($form);
if ($this->fields === null) {
return;
}
$elements = $this->removeFilteredFields($this->getElements($form));
foreach ($elements as $element) {
$form->addElement($element);
}
@ -194,6 +202,68 @@ class IcingaObjectFieldLoader
}
}
/**
* @param ZfElement[] $elements
* @return ZfElement[]
*/
protected function removeFilteredFields(array $elements)
{
$filters = array();
foreach ($this->fields as $key => $field) {
if ($filter = $field->var_filter) {
$filters[$key] = Filter::fromQueryString($filter);
}
}
$kill = array();
$columns = array();
$object = $this->object;
$object->invalidateResolveCache();
$vars = $object::fromPlainObject($object->toPlainObject(true))->vars()->flatten();
$prefixedVars = (object) array();
if ($object instanceof IcingaHost) {
$prefix = 'host.vars.';
} elseif ($object instanceof IcingaService) {
$prefix = 'service.vars.';
} else {
return $elements;
}
foreach ($vars as $k => $v) {
$prefixedVars->{$prefix . $k} = $v;
}
foreach ($filters as $key => $filter) {
/** @var $filter FilterChain|FilterExpression */
foreach ($filter->listFilteredColumns() as $column) {
$column = substr($column, strlen($prefix));
$columns[$column] = $column;
}
if (! $filter->matches($prefixedVars)) {
$kill[] = $key;
}
}
foreach ($kill as $key) {
unset($elements[$key]);
}
foreach ($columns as $col) {
if (array_key_exists($col, $elements)) {
$el = $elements[$col];
$existingClass = $el->getAttrib('class');
if (strlen($existingClass)) {
$el->setAttrib('class', $existingClass . ' autosubmit');
} else {
$el->setAttrib('class', 'autosubmit');
}
}
}
return $elements;
}
protected function getElementVarName($name)
{
if (array_key_exists($name, $this->nameMap)) {
@ -351,14 +421,15 @@ class IcingaObjectFieldLoader
$query = $db->select()->from(
array('df' => 'director_datafield'),
array(
'object_id' => $idColumn,
'is_required' => 'f.is_required',
'id' => 'df.id',
'varname' => 'df.varname',
'caption' => 'df.caption',
'description' => 'df.description',
'datatype' => 'df.datatype',
'format' => 'df.format',
'object_id' => $idColumn,
'var_filter' => 'f.var_filter',
'is_required' => 'f.is_required',
'id' => 'df.id',
'varname' => 'df.varname',
'caption' => 'df.caption',
'description' => 'df.description',
'datatype' => 'df.datatype',
'format' => 'df.format',
)
)->join(
array('f' => $object->getTableName() . '_field'),

View File

@ -0,0 +1,18 @@
ALTER TABLE icinga_command_field
ADD COLUMN var_filter TEXT DEFAULT NULL;
ALTER TABLE icinga_host_field
ADD COLUMN var_filter TEXT DEFAULT NULL;
ALTER TABLE icinga_notification_field
ADD COLUMN var_filter TEXT DEFAULT NULL;
ALTER TABLE icinga_service_field
ADD COLUMN var_filter TEXT DEFAULT NULL;
ALTER TABLE icinga_user_field
ADD COLUMN var_filter TEXT DEFAULT NULL;
INSERT INTO director_schema_migration
(schema_version, migration_time)
VALUES (125, NOW());

View File

@ -337,6 +337,7 @@ CREATE TABLE icinga_command_field (
command_id INT(10) UNSIGNED NOT NULL,
datafield_id INT(10) UNSIGNED NOT NULL,
is_required ENUM('y', 'n') NOT NULL,
var_filter TEXT DEFAULT NULL,
PRIMARY KEY (command_id, datafield_id),
CONSTRAINT icinga_command_field_command
FOREIGN KEY command_id (command_id)
@ -502,6 +503,7 @@ CREATE TABLE icinga_host_field (
host_id INT(10) UNSIGNED NOT NULL COMMENT 'Makes only sense for templates',
datafield_id INT(10) UNSIGNED NOT NULL,
is_required ENUM('y', 'n') NOT NULL,
var_filter TEXT DEFAULT NULL,
PRIMARY KEY (host_id, datafield_id),
CONSTRAINT icinga_host_field_host
FOREIGN KEY host(host_id)
@ -653,6 +655,7 @@ CREATE TABLE icinga_service_field (
service_id INT(10) UNSIGNED NOT NULL COMMENT 'Makes only sense for templates',
datafield_id INT(10) UNSIGNED NOT NULL,
is_required ENUM('y', 'n') NOT NULL,
var_filter TEXT DEFAULT NULL,
PRIMARY KEY (service_id, datafield_id),
CONSTRAINT icinga_service_field_service
FOREIGN KEY service(service_id)
@ -921,6 +924,7 @@ CREATE TABLE icinga_user_field (
user_id INT(10) UNSIGNED NOT NULL COMMENT 'Makes only sense for templates',
datafield_id INT(10) UNSIGNED NOT NULL,
is_required ENUM('y', 'n') NOT NULL,
var_filter TEXT DEFAULT NULL,
PRIMARY KEY (user_id, datafield_id),
CONSTRAINT icinga_user_field_user
FOREIGN KEY user(user_id)
@ -1056,6 +1060,7 @@ CREATE TABLE icinga_notification_field (
notification_id INT(10) UNSIGNED NOT NULL COMMENT 'Makes only sense for templates',
datafield_id INT(10) UNSIGNED NOT NULL,
is_required ENUM('y', 'n') NOT NULL,
var_filter TEXT DEFAULT NULL,
PRIMARY KEY (notification_id, datafield_id),
CONSTRAINT icinga_notification_field_notification
FOREIGN KEY notification (notification_id)
@ -1365,4 +1370,4 @@ CREATE TABLE sync_run (
INSERT INTO director_schema_migration
(schema_version, migration_time)
VALUES (124, NOW());
VALUES (125, NOW());

View File

@ -0,0 +1,18 @@
ALTER TABLE icinga_command_field
ADD COLUMN var_filter TEXT DEFAULT NULL;
ALTER TABLE icinga_host_field
ADD COLUMN var_filter TEXT DEFAULT NULL;
ALTER TABLE icinga_notification_field
ADD COLUMN var_filter TEXT DEFAULT NULL;
ALTER TABLE icinga_service_field
ADD COLUMN var_filter TEXT DEFAULT NULL;
ALTER TABLE icinga_user_field
ADD COLUMN var_filter TEXT DEFAULT NULL;
INSERT INTO director_schema_migration
(schema_version, migration_time)
VALUES (125, NOW());

View File

@ -443,6 +443,7 @@ CREATE TABLE icinga_command_field (
command_id integer NOT NULL,
datafield_id integer NOT NULL,
is_required enum_boolean NOT NULL,
var_filter TEXT DEFAULT NULL,
PRIMARY KEY (command_id, datafield_id),
CONSTRAINT icinga_command_field_command
FOREIGN KEY (command_id)
@ -635,6 +636,7 @@ CREATE TABLE icinga_host_field (
host_id integer NOT NULL,
datafield_id integer NOT NULL,
is_required enum_boolean NOT NULL,
var_filter TEXT DEFAULT NULL,
PRIMARY KEY (host_id, datafield_id),
CONSTRAINT icinga_host_field_host
FOREIGN KEY (host_id)
@ -812,6 +814,7 @@ CREATE TABLE icinga_service_field (
service_id integer NOT NULL,
datafield_id integer NOT NULL,
is_required enum_boolean NOT NULL,
var_filter TEXT DEFAULT NULL,
PRIMARY KEY (service_id, datafield_id),
CONSTRAINT icinga_service_field_service
FOREIGN KEY (service_id)
@ -1121,6 +1124,7 @@ CREATE TABLE icinga_user_field (
user_id integer NOT NULL,
datafield_id integer NOT NULL,
is_required enum_boolean NOT NULL,
var_filter TEXT DEFAULT NULL,
PRIMARY KEY (user_id, datafield_id),
CONSTRAINT icinga_user_field_user
FOREIGN KEY (user_id)
@ -1552,6 +1556,7 @@ CREATE TABLE icinga_notification_field (
notification_id integer NOT NULL,
datafield_id integer NOT NULL,
is_required enum_boolean NOT NULL,
var_filter TEXT DEFAULT NULL,
PRIMARY KEY (notification_id, datafield_id),
CONSTRAINT icinga_notification_field_notification
FOREIGN KEY (notification_id)
@ -1593,4 +1598,4 @@ CREATE UNIQUE INDEX notification_inheritance ON icinga_notification_inheritance
INSERT INTO director_schema_migration
(schema_version, migration_time)
VALUES (124, NOW());
VALUES (125, NOW());