diff --git a/application/forms/IcingaObjectFieldForm.php b/application/forms/IcingaObjectFieldForm.php index 7fa93896..d07d9de7 100644 --- a/application/forms/IcingaObjectFieldForm.php +++ b/application/forms/IcingaObjectFieldForm.php @@ -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(); } } diff --git a/library/Director/Objects/IcingaCommandField.php b/library/Director/Objects/IcingaCommandField.php index 6077347e..086cb560 100644 --- a/library/Director/Objects/IcingaCommandField.php +++ b/library/Director/Objects/IcingaCommandField.php @@ -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, ); } diff --git a/library/Director/Objects/IcingaHostField.php b/library/Director/Objects/IcingaHostField.php index fdf1a6ab..b68c9d43 100644 --- a/library/Director/Objects/IcingaHostField.php +++ b/library/Director/Objects/IcingaHostField.php @@ -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, ); } diff --git a/library/Director/Objects/IcingaNotificationField.php b/library/Director/Objects/IcingaNotificationField.php index 7e3e912e..d51f9e6a 100644 --- a/library/Director/Objects/IcingaNotificationField.php +++ b/library/Director/Objects/IcingaNotificationField.php @@ -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, ); } diff --git a/library/Director/Objects/IcingaObjectField.php b/library/Director/Objects/IcingaObjectField.php new file mode 100644 index 00000000..39d8e31b --- /dev/null +++ b/library/Director/Objects/IcingaObjectField.php @@ -0,0 +1,28 @@ +toQueryString(); + } + + return $this->reallySet('var_filter', $value); + } +} diff --git a/library/Director/Objects/IcingaServiceField.php b/library/Director/Objects/IcingaServiceField.php index af55dc46..c43ec2d1 100644 --- a/library/Director/Objects/IcingaServiceField.php +++ b/library/Director/Objects/IcingaServiceField.php @@ -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, ); } diff --git a/library/Director/Objects/IcingaUserField.php b/library/Director/Objects/IcingaUserField.php index ab7ec59b..4a6432c8 100644 --- a/library/Director/Objects/IcingaUserField.php +++ b/library/Director/Objects/IcingaUserField.php @@ -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, ); } diff --git a/library/Director/Web/Form/IcingaObjectFieldLoader.php b/library/Director/Web/Form/IcingaObjectFieldLoader.php index 9e6d5858..ab13f598 100644 --- a/library/Director/Web/Form/IcingaObjectFieldLoader.php +++ b/library/Director/Web/Form/IcingaObjectFieldLoader.php @@ -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'), diff --git a/schema/mysql-migrations/upgrade_125.sql b/schema/mysql-migrations/upgrade_125.sql new file mode 100644 index 00000000..b1ffea10 --- /dev/null +++ b/schema/mysql-migrations/upgrade_125.sql @@ -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()); diff --git a/schema/mysql.sql b/schema/mysql.sql index 4dd1c8ea..adb65376 100644 --- a/schema/mysql.sql +++ b/schema/mysql.sql @@ -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()); diff --git a/schema/pgsql-migrations/upgrade_125.sql b/schema/pgsql-migrations/upgrade_125.sql new file mode 100644 index 00000000..b1ffea10 --- /dev/null +++ b/schema/pgsql-migrations/upgrade_125.sql @@ -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()); diff --git a/schema/pgsql.sql b/schema/pgsql.sql index ccb801e0..7fb59353 100644 --- a/schema/pgsql.sql +++ b/schema/pgsql.sql @@ -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());