diff options
Diffstat (limited to 'application/forms/DirectorDatafieldForm.php')
-rw-r--r-- | application/forms/DirectorDatafieldForm.php | 301 |
1 files changed, 301 insertions, 0 deletions
diff --git a/application/forms/DirectorDatafieldForm.php b/application/forms/DirectorDatafieldForm.php new file mode 100644 index 0000000..a306bd7 --- /dev/null +++ b/application/forms/DirectorDatafieldForm.php @@ -0,0 +1,301 @@ +<?php + +namespace Icinga\Module\Director\Forms; + +use Icinga\Exception\ConfigurationError; +use Icinga\Module\Director\CustomVariable\CustomVariables; +use Icinga\Module\Director\Hook\DataTypeHook; +use Icinga\Module\Director\Web\Form\DirectorObjectForm; +use Icinga\Application\Hook; +use Exception; + +class DirectorDatafieldForm extends DirectorObjectForm +{ + protected $objectName = 'Data field'; + + protected $listUrl = 'director/data/fields'; + + protected function onRequest() + { + if ($this->hasBeenSent()) { + if ($this->shouldBeDeleted()) { + $varname = $this->getSentValue('varname'); + if ($cnt = CustomVariables::countAll($varname, $this->getDb())) { + $this->askForVariableDeletion($varname, $cnt); + } + } elseif ($this->shouldBeRenamed()) { + $varname = $this->object()->getOriginalProperty('varname'); + if ($cnt = CustomVariables::countAll($varname, $this->getDb())) { + $this->askForVariableRename( + $varname, + $this->getSentValue('varname'), + $cnt + ); + } + } + } + + parent::onRequest(); + } + + protected function askForVariableDeletion($varname, $cnt) + { + $msg = $this->translate( + 'Leaving custom variables in place while removing the related field is' + . ' perfectly legal and might be a desired operation. This way you can' + . ' no longer modify related custom variables in the Director GUI, but' + . ' the variables themselves will stay there and continue to be deployed.' + . ' When you re-add a field for the same variable later on, everything' + . ' will continue to work as before' + ); + + $this->addBoolean('wipe_vars', array( + 'label' => $this->translate('Wipe related vars'), + 'description' => sprintf($msg, $this->getSentValue('varname')), + 'required' => true, + )); + + if ($wipe = $this->getSentValue('wipe_vars')) { + if ($wipe === 'y') { + CustomVariables::deleteAll($varname, $this->getDb()); + } + } else { + $this->abortDeletion(); + $this->addError( + sprintf( + $this->translate('Also wipe all "%s" custom variables from %d objects?'), + $varname, + $cnt + ) + ); + $this->getElement('wipe_vars')->addError( + sprintf( + $this->translate( + 'There are %d objects with a related property. Should I also' + . ' remove the "%s" property from them?' + ), + $cnt, + $varname + ) + ); + } + } + + protected function askForVariableRename($oldname, $newname, $cnt) + { + $msg = $this->translate( + 'Leaving custom variables in place while renaming the related field is' + . ' perfectly legal and might be a desired operation. This way you can' + . ' no longer modify related custom variables in the Director GUI, but' + . ' the variables themselves will stay there and continue to be deployed.' + . ' When you re-add a field for the same variable later on, everything' + . ' will continue to work as before' + ); + + $this->addBoolean('rename_vars', array( + 'label' => $this->translate('Rename related vars'), + 'description' => sprintf($msg, $this->getSentValue('varname')), + 'required' => true, + )); + + if ($wipe = $this->getSentValue('rename_vars')) { + if ($wipe === 'y') { + CustomVariables::renameAll($oldname, $newname, $this->getDb()); + } + } else { + $this->abortDeletion(); + $this->addError( + sprintf( + $this->translate('Also rename all "%s" custom variables to "%s" on %d objects?'), + $oldname, + $newname, + $cnt + ) + ); + $this->getElement('rename_vars')->addError( + sprintf( + $this->translate( + 'There are %d objects with a related property. Should I also' + . ' rename the "%s" property to "%s" on them?' + ), + $cnt, + $oldname, + $newname + ) + ); + } + } + + public function setup() + { + $this->addHtmlHint( + $this->translate( + 'Data fields allow you to customize input controls for Icinga custom' + . ' variables. Once you defined them here, you can provide them through' + . ' your defined templates. This gives you a granular control over what' + . ' properties your users should be allowed to configure in which way.' + ) + ); + + $this->addElement('text', 'varname', array( + 'label' => $this->translate('Field name'), + 'description' => $this->translate( + 'The unique name of the field. This will be the name of the custom' + . ' variable in the rendered Icinga configuration.' + ), + 'required' => true, + )); + + $this->addElement('text', 'caption', array( + 'label' => $this->translate('Caption'), + 'required' => true, + 'description' => $this->translate( + 'The caption which should be displayed to your users when this field' + . ' is shown' + ) + )); + + $this->addElement('textarea', 'description', array( + 'label' => $this->translate('Description'), + 'description' => $this->translate( + 'An extended description for this field. Will be shown as soon as a' + . ' user puts the focus on this field' + ), + 'rows' => '3', + )); + + $this->addElement('select', 'category_id', [ + 'label' => $this->translate('Data Field Category'), + 'multiOptions' => $this->optionalEnum($this->enumCategpories()), + ]); + + $error = false; + try { + $types = $this->enumDataTypes(); + } catch (Exception $e) { + $error = $e->getMessage(); + $types = $this->optionalEnum(array()); + } + + $this->addElement('select', 'datatype', array( + 'label' => $this->translate('Data type'), + 'description' => $this->translate('Field type'), + 'required' => true, + 'multiOptions' => $types, + 'class' => 'autosubmit', + )); + if ($error) { + $this->getElement('datatype')->addError($error); + } + + $object = $this->object(); + try { + if ($class = $this->getSentValue('datatype')) { + if ($class && array_key_exists($class, $types)) { + $this->addSettings($class); + } + } elseif ($class = $object->get('datatype')) { + $this->addSettings($class); + } + + // TODO: next line looks like obsolete duplicate code to me + $this->addSettings(); + } catch (Exception $e) { + $this->getElement('datatype')->addError($e->getMessage()); + } + + foreach ($object->getSettings() as $key => $val) { + if ($el = $this->getElement($key)) { + $el->setValue($val); + } + } + + $this->setButtons(); + } + + public function shouldBeRenamed() + { + $object = $this->object(); + return $object->hasBeenLoadedFromDb() + && $object->getOriginalProperty('varname') !== $this->getSentValue('varname'); + } + + protected function addSettings($class = null) + { + if ($class === null) { + $class = $this->getValue('datatype'); + } + + if ($class !== null) { + if (! class_exists($class)) { + throw new ConfigurationError( + 'The hooked class "%s" for this data field does no longer exist', + $class + ); + } + + $class::addSettingsFormFields($this); + } + } + + protected function clearOutdatedSettings() + { + $names = array(); + $object = $this->object(); + $global = array('varname', 'description', 'caption', 'datatype'); + + /** @var \Zend_Form_Element $el */ + foreach ($this->getElements() as $el) { + if ($el->getIgnore()) { + continue; + } + + $name = $el->getName(); + if (in_array($name, $global)) { + continue; + } + + $names[$name] = $name; + } + + + foreach ($object->getSettings() as $setting => $value) { + if (! array_key_exists($setting, $names)) { + unset($object->$setting); + } + } + } + + public function onSuccess() + { + $this->clearOutdatedSettings(); + + if ($class = $this->getValue('datatype')) { + if (array_key_exists($class, $this->enumDataTypes())) { + $this->addHidden('format', $class::getFormat()); + } + } + + parent::onSuccess(); + } + + protected function enumDataTypes() + { + $hooks = Hook::all('Director\\DataType'); + $enum = array(null => '- please choose -'); + /** @var DataTypeHook $hook */ + foreach ($hooks as $hook) { + $enum[get_class($hook)] = $hook->getName(); + } + + return $enum; + } + + protected function enumCategpories() + { + $db = $this->getDb()->getDbAdapter(); + return $db->fetchPairs( + $db->select()->from('director_datafield_category', ['id', 'category_name']) + ); + } +} |