diff --git a/application/forms/IcingaDependencyForm.php b/application/forms/IcingaDependencyForm.php index 05448bafd..56597f91a 100644 --- a/application/forms/IcingaDependencyForm.php +++ b/application/forms/IcingaDependencyForm.php @@ -5,6 +5,7 @@ use Icinga\Module\Director\Data\Db\DbObject; use Icinga\Module\Director\Web\Form\DirectorObjectForm; use Icinga\Module\Director\Objects\IcingaDependency; +use Zend_Validate_Callback; class IcingaDependencyForm extends DirectorObjectForm { @@ -196,34 +197,79 @@ protected function addObjectsElement() $parentHost = '$' . $dependency->get('parent_host_var') . '$'; } } + + $parentHostDescription = $this->translate('Optional. The parent host.'); + $applyTo = $this->getSentOrObjectValue('apply_to'); + $parentHostValidator = new Zend_Validate_Callback(function ($value) use ($applyTo) { + if ($applyTo === 'host' && $this->isCustomVar($value)) { + return explode('.', trim($value, '$'))[0] === 'host'; + } + + return true; + }); + + $parentHostValidator->setMessage( + $this->translate('The parent host cannot be a service custom variable for a host dependency'), + Zend_Validate_Callback::INVALID_VALUE + ); + + if ($applyTo === 'service') { + $additionalDescription = $this->translate( + 'You might want to refer to Host or Service Custom Variables via $host|service.vars.varname$' + ); + } else { + $additionalDescription = $this->translate( + 'You might want to refer to Host Custom Variables via $host.vars.varname$' + ); + } + + $parentHostDescription .= ' ' . $additionalDescription; + $this->addElement('text', 'parent_host', [ - 'label' => $this->translate('Parent Host'), - 'description' => $this->translate( - 'The parent host. You might want to refer Host Custom Variables' - . ' via $host.vars.varname$' - ), - 'class' => "autosubmit director-suggest", + 'label' => $this->translate('Parent Host'), + 'description' => $parentHostDescription, + 'class' => "autosubmit director-suggest", 'data-suggestion-context' => 'hostnames', - 'order' => 10, - 'required' => $this->isObject(), - 'value' => $parentHost + 'order' => 10, + 'required' => $this->isObject(), + 'value' => $parentHost, + 'validators' => [$parentHostValidator] ]); $sentParent = $this->getSentOrObjectValue('parent_host'); if (!empty($sentParent) || $dependency->isApplyRule()) { $parentService = $dependency->get('parent_service'); + if ($parentService === null) { + $parentServiceVar = $dependency->get('parent_service_by_name'); + if ($parentServiceVar) { + $parentService = '$' . $parentServiceVar . '$'; + } + } + + $parentServiceDescription = $this->translate( + 'Optional. The parent service. If omitted this dependency' + . ' object is treated as host dependency.' + ); + + $parentServiceDescription .= ' ' . $additionalDescription; + + $parentServiceValidator = clone $parentHostValidator; + + $parentServiceValidator->setMessage( + $this->translate('The parent service cannot be a service custom variable for a host dependency'), + Zend_Validate_Callback::INVALID_VALUE + ); + $this->addElement('text', 'parent_service', [ - 'label' => $this->translate('Parent Service'), - 'description' => $this->translate( - 'Optional. The parent service. If omitted this dependency' - . ' object is treated as host dependency.' - ), - 'class' => "autosubmit director-suggest", - 'data-suggestion-context' => 'servicenames', - 'data-suggestion-for-host' => $sentParent, - 'order' => 20, - 'value' => $parentService - ]); + 'label' => $this->translate('Parent Service'), + 'description' => $parentServiceDescription, + 'class' => "autosubmit director-suggest", + 'data-suggestion-context' => 'servicenames', + 'data-suggestion-for-host' => $sentParent, + 'order' => 20, + 'value' => $parentService, + 'validators' => [$parentServiceValidator] + ]); } // If configuring Object, allow selection of child host and/or service, @@ -290,11 +336,22 @@ public function createApplyRuleFor(IcingaDependency $dependency) protected function handleProperties(DbObject $object, &$values) { if ($this->hasBeenSent()) { - if (isset($values['parent_host']) - && $this->isCustomVar($values['parent_host']) - ) { - $values['parent_host_var'] = \trim($values['parent_host'], '$'); - $values['parent_host'] = ''; + if (isset($values['parent_host'])) { + if ($this->isCustomVar($values['parent_host'])) { + $values['parent_host_var'] = \trim($values['parent_host'], '$'); + $values['parent_host'] = ''; + } else { + $values['parent_host_var'] = ''; + } + } + + if (isset($values['parent_service'])) { + if ($this->isCustomVar($values['parent_service'])) { + $values['parent_service_by_name'] = trim($values['parent_service'], '$'); + $values['parent_service'] = ''; + } else { + $values['parent_service_by_name'] = ''; + } } } @@ -303,7 +360,6 @@ protected function handleProperties(DbObject $object, &$values) protected function isCustomVar($string) { - return \preg_match('/^\$(?:host)\.vars\..+\$$/', $string); - // Eventually: return \preg_match('/^\$(?:host|service)\.vars\..+\$$/', $string); + return preg_match('/^\$(?:host|service)\.vars\..+\$$/', $string); } } diff --git a/library/Director/Objects/IcingaDependency.php b/library/Director/Objects/IcingaDependency.php index a2b767a69..abd92e625 100644 --- a/library/Director/Objects/IcingaDependency.php +++ b/library/Director/Objects/IcingaDependency.php @@ -83,6 +83,18 @@ public function parentHostIsVar() return $this->get('parent_host_var') !== null; } + /** + * Check if the given string is a custom variable + * + * @param $string string + * + * @return false|int + */ + protected function isCustomVar(string $string) + { + return preg_match('/^(?:host|service)\.vars\..+$/', $string); + } + /** * @return string * @throws ConfigurationError @@ -440,9 +452,16 @@ public function renderParent_service_id() public function renderParent_service_by_name() { // @codingStandardsIgnoreEnd + $var = $this->get('parent_service_by_name'); + if ($this->isCustomVar($var)) { + return c::renderKeyValue( + 'parent_service_name', + $var + ); + } return c::renderKeyValue( 'parent_service_name', - c::renderString($this->get('parent_service_by_name')) + c::renderString($var) ); } @@ -593,8 +612,12 @@ protected function getRelatedProperty($key) $related = parent::getRelatedProperty($key); // handle special case for plain string parent service on Dependency // Apply rules - if ($related === null && $key === 'parent_service' - && null !== $this->get('parent_service_by_name') + if ($related === null + && $key === 'parent_service' + && ( + $this->get('parent_service_by_name') + && ! $this->isCustomVar($this->get('parent_service_by_name')) + ) ) { return $this->get('parent_service_by_name'); }