diff --git a/application/forms/IcingaMultiEditForm.php b/application/forms/IcingaMultiEditForm.php
index 35d8638e..3de689ab 100644
--- a/application/forms/IcingaMultiEditForm.php
+++ b/application/forms/IcingaMultiEditForm.php
@@ -2,41 +2,59 @@
namespace Icinga\Module\Director\Forms;
-use Icinga\Module\Director\Web\Form\QuickForm;
+use Icinga\Module\Director\Web\Form\IcingaObjectFieldLoader;
+use Icinga\Module\Director\Web\Form\DirectorObjectForm;
+use Zend_Form_Element as ZfElement;
-class IcingaMultiEditForm extends QuickForm
+class IcingaMultiEditForm extends DirectorObjectForm
{
private $objects;
- private $object;
-
- private $db;
+ private $elementGroupMap;
public function setObjects($objects)
{
$this->objects = $objects;
+ $this->object = current($this->objects);
+ $this->db = $this->object()->getConnection();
return $this;
}
public function setup()
{
- $this->addImportsElements();//->setButtons();
+ $object = $this->object;
+ $this->addImportsElement();
+ // $this->addDisabledElement();
+
+ $loader = new IcingaObjectFieldLoader($object);
+ $loader->addFieldsToForm($this);
+
+ $this->makeVariants($this->getElement('imports'));
+ // $this->makeVariants($this->getElement('disabled'));
+ foreach ($this->getElements() as $el) {
+ $name =$el->getName();
+ if (substr($name, 0, 4) === 'var_') {
+ $this->makeVariants($el);
+ }
+ }
+
+ $this->setButtons();
+ }
+
+ /**
+ * No default objects behaviour
+ */
+ protected function onRequest()
+ {
}
public function onSuccess()
{
-/*
-echo '
';
-print_r($this->getVariants('imports'));
-print_r($this->getValues());
-echo '
';
-*/
foreach ($this->getValues() as $key => $value) {
$parts = preg_split('/_/', $key);
$objectsSum = array_pop($parts);
$valueSum = array_pop($parts);
$property = implode('_', $parts);
-//printf("Got %s: %s -> %s
", $property, $valueSum, $objectsSum);
$found = false;
foreach ($this->getVariants($property) as $json => $objects) {
@@ -49,6 +67,9 @@ echo '';
}
$found = true;
+ if (substr($property, 0, 4) === 'var_') {
+ $property = 'vars.' . substr($property, 4);
+ }
foreach ($this->getObjects($objects) as $object) {
$object->$property = $value;
@@ -65,24 +86,80 @@ echo '';
}
if ($modified === 0) {
- $this->setSuccessMessage($this->translate('No object has been modified'));
+ $msg = $this->translate('No object has been modified');
} elseif ($modified === 1) {
- $this->setSuccessMessage($this->translate('One object has been modified'));
+ $msg = $this->translate('One object has been modified');
} else {
- $this->setSuccessMessage(
- sprintf(
- $this->translate('%d objects have been modified'),
- $modified
- )
+ $msg = sprintf(
+ $this->translate('%d objects have been modified'),
+ $modified
);
}
- parent::onSuccess();
+ $this->redirectOnSuccess($msg);
+ }
+
+ protected function getDisplayGroupForElement(ZfElement $element)
+ {
+ if ($this->elementGroupMap === null) {
+ $this->resolveDisplayGroups();
+ }
+
+ $name = $element->getName();
+ if (array_key_exists($name, $this->elementGroupMap)) {
+ return $this->getDisplayGroup($this->elementGroupMap[$name]);
+ } else {
+ return null;
+ }
+ }
+
+ protected function resolveDisplayGroups()
+ {
+ $this->elementGroupMap = array();
+
+ foreach ($this->getDisplayGroups() as $group) {
+ $groupName = $group->getName();
+ foreach ($group->getElements() as $name => $e) {
+ $this->elementGroupMap[$name] = $groupName;
+ }
+ }
+ }
+
+ protected function makeVariants(ZfElement $element)
+ {
+ if (! $element) {
+ return $this;
+ }
+
+ $key = $element->getName();
+ $this->removeElement($key);
+ $label = $element->getLabel();
+ $group = $this->getDisplayGroupForElement($element);
+ $description = $element->getDescription();
+
+ foreach ($this->getVariants($key) as $json => $objects) {
+ $value = json_decode($json);
+ $checksum = sha1($json) . '_' . sha1(json_encode($objects));
+
+ $v = clone($element);
+ $v->setName($key . '_' . $checksum);
+ $v->setDescription($description . '. ' . $this->descriptionForObjects($objects));
+ $v->setLabel($label . $this->labelCount($objects));
+ $v->setValue($value);
+ if ($group) {
+ $group->addElement($v);
+ }
+ $this->addElement($v);
+ }
}
protected function getVariants($key)
{
$variants = array();
+ if (substr($key, 0, 4) === 'var_') {
+ $key = 'vars.' . substr($key, 4);
+ }
+
foreach ($this->objects as $name => $object) {
$value = json_encode($object->$key);
if (! array_key_exists($value, $variants)) {
@@ -113,41 +190,6 @@ echo '';
return ' (' . count($list) . ')';
}
- protected function addImportsElements()
- {
- $enum = $this->enumTemplates();
- if (empty($enum)) {
- return $this;
- }
-
- foreach ($this->getVariants('imports') as $json => $objects) {
- $value = json_decode($json);
- $checksum = sha1($json) . '_' . sha1(json_encode($objects));
- $this->addElement('extensibleSet', 'imports_' . $checksum, array(
- 'label' => $this->translate('Imports') . $this->labelCount($objects),
- 'description' => $this->translate(
- 'Importable templates, add as many as you want. Please note that order'
- . ' matters when importing properties from multiple templates: last one'
- . ' wins'
- ) . '. ' . $this->descriptionForObjects($objects),
- 'required' => !$this->object()->isTemplate(),
- 'multiOptions' => $this->optionallyAddFromEnum($enum),
- 'value' => $value,
- 'sorted' => true,
- 'class' => 'autosubmit'
- ));
- }
-
- return $this;
- }
-
- public function optionallyAddFromEnum($enum)
- {
- return array(
- null => $this->translate('- click to add more -')
- ) + $enum;
- }
-
protected function enumTemplates()
{
$object = $this->object();
@@ -182,13 +224,4 @@ echo '';
return $res;
}
-
- protected function object()
- {
- if ($this->object === null) {
- $this->object = current($this->objects);
- }
-
- return $this->object;
- }
}
diff --git a/library/Director/Web/Form/DirectorObjectForm.php b/library/Director/Web/Form/DirectorObjectForm.php
index 69b505bc..5ad71c06 100644
--- a/library/Director/Web/Form/DirectorObjectForm.php
+++ b/library/Director/Web/Form/DirectorObjectForm.php
@@ -257,7 +257,11 @@ abstract class DirectorObjectForm extends QuickForm
protected function handleCustomVars($object, & $values)
{
if ($this->assertResolvedImports()) {
- IcingaObjectFieldLoader::addFieldsToForm($this, $object, $values);
+ $loader = new IcingaObjectFieldLoader($object);
+ $loader->addFieldsToForm($this);
+ if ($values) {
+ $loader->setValues($values, 'var_');
+ }
}
}
diff --git a/library/Director/Web/Form/IcingaObjectFieldLoader.php b/library/Director/Web/Form/IcingaObjectFieldLoader.php
index 5076dac5..640c2417 100644
--- a/library/Director/Web/Form/IcingaObjectFieldLoader.php
+++ b/library/Director/Web/Form/IcingaObjectFieldLoader.php
@@ -2,10 +2,11 @@
namespace Icinga\Module\Director\Web\Form;
+use stdClass;
use Icinga\Module\Director\Objects\IcingaObject;
use Icinga\Module\Director\Objects\IcingaServiceSet;
use Icinga\Module\Director\Objects\DirectorDatafield;
-use stdClass;
+use Zend_Form_Element as ZfElement;
class IcingaObjectFieldLoader
{
@@ -13,95 +14,172 @@ class IcingaObjectFieldLoader
protected $object;
- protected function __construct(DirectorObjectForm $form, IcingaObject $object)
+ protected $fields;
+
+ protected $elements;
+
+ public function __construct(IcingaObject $object)
{
- $this->form = $form;
$this->object = $object;
}
- public static function addFieldsToForm(DirectorObjectForm $form, IcingaObject $object, & $values)
+ public function addFieldsToForm(QuickForm $form)
{
- if (! $object->supportsCustomVars()) {
- return $form;
+ if ($this->object->supportsCustomVars()) {
+ $this->attachFieldsToForm($form);
}
- $loader = new static($form, $object);
- $loader->addFields();
- if ($values !== null) {
- $loader->setValues($loader->stripKeyPrefix($values, 'var_'));
- }
-
- return $form;
+ return $this;
}
- protected function stripKeyPrefix($array, $prefix)
+ /**
+ * Set a list of values
+ *
+ * Works in a failsafe way, when a field does not exist the value will be
+ * silently ignored
+ *
+ * @param Array $values key/value pairs with variable names and their value
+ * @param String $prefix An optional prefix that would be stripped from keys
+ *
+ * @return self
+ */
+ public function setValues($values, $prefix = null)
{
- $new = array();
- $len = strlen($prefix);
- foreach ($array as $key => $value) {
- if (substr($key, 0, $len) === $prefix) {
- $new[substr($key, $len)] = $value;
- }
+ if ($prefix !== null) {
+ $len = strlen($prefix);
}
-
- return $new;
- }
-
- protected function setValues($values)
- {
$vars = $this->object->vars();
- $form = $this->form;
foreach ($values as $key => $value) {
- if ($el = $form->getElement('var_' . $key)) {
- if ($value === '' || $value === null) {
+ if ($prefix) {
+ if (substr($key, 0, $len) === $prefix) {
+ $key = substr($key, $len);
+ } else {
continue;
}
+ }
+
+ if ($el = $this->getElement($key)) {
$el->setValue($value);
- $vars->set($key, $el->getValue());
+ $value = $el->getValue();
+
+ if ($value === '') {
+ $value = null;
+ }
+
+ $vars->set($key, $value);
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get the fields for our object
+ *
+ * @return DirectorDatafield[]
+ */
+ public function getFields()
+ {
+ if ($this->fields === null) {
+ $this->fields = $this->prepareObjectFields($this->object);
+ }
+
+ return $this->fields;
+ }
+
+ /**
+ * Get the form elements for our fields
+ *
+ * @param QuickForm $form Optional
+ *
+ * @return ZfElement[]
+ */
+ public function getElements(QuickForm $form = null)
+ {
+ if ($this->elements === null) {
+ $this->elements = $this->createElements($form);
+ $this->setValuesFromObject($this->object);
+ }
+
+ return $this->elements;
+ }
+
+ /**
+ * Attach our form fields to the given form
+ *
+ * This will also create a 'Custom properties' display group
+ */
+ protected function attachFieldsToForm(QuickForm $form)
+ {
+ $elements = $this->getElements($form);
+
+ if (! empty($elements)) {
+ $form->addElementsToGroup(
+ $elements,
+ 'custom_fields',
+ 50,
+ $form->translate('Custom properties')
+ );
+ }
+ }
+
+ /**
+ * Get the form element for a specific field by it's variable name
+ *
+ * @return ZfElement|null
+ */
+ protected function getElement($name)
+ {
+ $elements = $this->getElements();
+ if (array_key_exists($name, $elements)) {
+ return $this->elements[$name];
+ }
+
+ return null;
+ }
+
+ /**
+ * Get the form elements based on the given form
+ *
+ * @return ZfElement[]
+ */
+ protected function createElements(QuickForm $form)
+ {
+ $elements = array();
+
+ foreach ($this->getFields() as $name => $field) {
+ $elements[$name] = $field->getFormElement($form);
+ }
+
+ return $elements;
+ }
+
+ protected function setValuesFromObject(IcingaObject $object)
+ {
+ foreach ($object->getVars() as $k => $v) {
+ if ($v !== null && $el = $this->getElement($k)) {
+ $el->setValue($v);
}
}
}
- protected function addFields()
+ protected function mergeFields($listOfFields)
{
- $object = $this->object;
- if ($object instanceof IcingaServiceSet) {
- } else {
- $this->attachFields(
- $this->prepareObjectFields($object)
- );
- }
-
- $this->setValues($object->getVars());
- }
-
- protected function attachFields($fields)
- {
- $form = $this->form;
- $elements = array();
- foreach ($fields as $field) {
- $elements[] = $field->getFormElement($form);
- }
-
- if (empty($elements)) {
- return $this;
- }
-
- return $form->addElementsToGroup(
- $elements,
- 'custom_fields',
- 50,
- $form->translate('Custom properties')
- );
+ // TODO: Merge field for different object, mostly sets
}
+ /**
+ * Create the fields for our object
+ *
+ *
+ * @return DirectorDatafield[]
+ */
protected function prepareObjectFields($object)
{
$fields = $this->loadResolvedFieldsForObject($object);
-
- if ($object->hasProperty('command_id')) {
- $command = $object->getResolvedRelated('command');
+ if ($object->hasRelation('check_command')) {
+ $command = $object->getResolvedRelated('check_command');
if ($command) {
$cmdFields = $this->loadResolvedFieldsForObject($command);
foreach ($cmdFields as $varname => $field) {
@@ -115,11 +193,14 @@ class IcingaObjectFieldLoader
return $fields;
}
- protected function mergeFields($listOfFields)
- {
- // TODO: Merge field for different object, mostly sets
- }
-
+ /**
+ * Create the fields for our object
+ *
+ * Follows the inheritance logic, resolves all fields and keeps the most
+ * specific ones. Returns a list of fields indexed by variable name
+ *
+ * @return DirectorDatafield[]
+ */
protected function loadResolvedFieldsForObject($object)
{
$result = $this->loadDataFieldsForObjects(
@@ -139,11 +220,16 @@ class IcingaObjectFieldLoader
return $fields;
}
- protected function getDb()
- {
- return $this->form->getDb();
- }
-
+ /**
+ * Fetches fields for a given List of objects from the database
+ *
+ * Gives a list indexed by object id, with each entry being a list of that
+ * objects DirectorDatafield instances indexed by variable name
+ *
+ * @param IcingaObject[] $objectList List of objects
+ *
+ * @return Array
+ */
protected function loadDataFieldsForObjects($objectList)
{
$ids = array();
@@ -163,7 +249,7 @@ class IcingaObjectFieldLoader
$db = $connection->getDbAdapter();
$idColumn = 'f.' . $object->getShortTableName() . '_id';
-
+
$query = $db->select()->from(
array('df' => 'director_datafield'),
array(
@@ -193,7 +279,7 @@ class IcingaObjectFieldLoader
if (! array_key_exists($id, $result)) {
$result[$id] = new stdClass;
}
-
+
$result[$id]->{$r->varname} = DirectorDatafield::fromDbRow(
$r,
$connection