diff --git a/application/forms/AddNodeForm.php b/application/forms/AddNodeForm.php index 691b59d..a01aee2 100644 --- a/application/forms/AddNodeForm.php +++ b/application/forms/AddNodeForm.php @@ -210,7 +210,7 @@ class AddNodeForm extends QuickForm $this->addServiceOverrideCheckbox(); if ($this->getSentValue('service_override') === '1') { - $this->addServiceOverrideElements(); + $this->addServiceOverrideElement(); } } else { $this->setSubmitLabel($this->translate('Next')); @@ -268,23 +268,12 @@ class AddNodeForm extends QuickForm ]); } - protected function addServiceOverrideElements() + protected function addServiceOverrideElement() { - $elements = []; - foreach ($this->enumServiceStateList() as $state => $stateName) { - if ($state === 0) { - continue; - } - $this->addElement('select', $stateName, [ - 'label' => $this->translate($stateName), - 'ignore' => true, - 'multiOptions' => $this->optionalEnum($this->enumServiceStateList()), - ]); - $elements[] = $stateName; - } - - $this->addSimpleDisplayGroup($elements, 'override_group', [ - 'legend' => $this->translate('State Overrides') + $this->addElement('stateOverrides', 'stateOverrides', [ + 'required' => true, + 'label' => $this->translate('State Overrides'), + 'states' => $this->enumServiceStateList() ]); } @@ -439,21 +428,6 @@ class AddNodeForm extends QuickForm return $serviceStateList; } - protected function statesToString() - { - $stateString = null; - foreach ($this->enumServiceStateList() as $state => $stateName) { - if ($this->getValue($stateName) !== null && $this->getValue($stateName) !== '') { - if ($stateString !== null) { - $stateString .= ','; - } - $stateString .= $state . '-' . $this->getValue($stateName); - } - } - - return $stateString; - } - protected function hasProcesses() { return count($this->enumProcesses()) > 0; @@ -528,15 +502,15 @@ class AddNodeForm extends QuickForm $changes = ProcessChanges::construct($this->bp, $this->session); switch ($this->getValue('node_type')) { case 'service': - if ($this->statesToString() !== null) { - $services = []; - foreach ($this->getValue('children') as $service) { - $services[] = $service . ':' . $this->statesToString(); - } - $changes->addChildrenToNode($services, $this->parent); - } else { - $changes->addChildrenToNode($this->getValue('children'), $this->parent); + $properties = $this->getValues(); + unset($properties['children']); + + $services = []; + foreach ($this->getValue('children') as $service) { + $services[$service] = $properties; } + + $changes->addChildrenToNode($services, $this->parent); break; case 'host': case 'process': diff --git a/application/forms/EditNodeForm.php b/application/forms/EditNodeForm.php index 438ad59..2d60d88 100644 --- a/application/forms/EditNodeForm.php +++ b/application/forms/EditNodeForm.php @@ -36,8 +36,6 @@ class EditNodeForm extends QuickForm protected $host; - protected $statesOverride = []; - /** @var SessionNamespace */ protected $session; @@ -45,8 +43,7 @@ class EditNodeForm extends QuickForm { $this->host = substr($this->getNode()->getName(), 0, strpos($this->getNode()->getName(), ';')); if ($this->isService()) { - $this->service = $this->getNode()->getShortName(); - $this->statesOverride = $this->getNode()->getStatesOverride(); + $this->service = substr($this->getNode()->getName(), strpos($this->getNode()->getName(), ';') + 1); } $view = $this->getView(); @@ -159,6 +156,7 @@ class EditNodeForm extends QuickForm if ($this->hasParentNode()) { $this->addElement('hidden', 'node_type', [ 'disabled' => true, + 'ignore' => true, 'decorators' => ['ViewHelper'], 'value' => $monitoredNodeType ]); @@ -194,14 +192,14 @@ class EditNodeForm extends QuickForm if ($this->getSentValue('hosts') === null) { $this->addServicesElement($this->host); $this->addServiceOverrideCheckbox(); - if (!empty($this->statesOverride) || $this->getSentValue('service_override') === '1') { - $this->addServiceOverrideElements(); + if (! empty($this->node->getStateOverrides()) || $this->getSentValue('service_override') === '1') { + $this->addServiceOverrideElement(); } } elseif ($host = $this->getSentValue('hosts')) { $this->addServicesElement($host); $this->addServiceOverrideCheckbox(); if ($this->getSentValue('service_override') === '1') { - $this->addServiceOverrideElements(); + $this->addServiceOverrideElement(); } } else { $this->setSubmitLabel($this->translate('Next')); @@ -225,23 +223,11 @@ class EditNodeForm extends QuickForm { $this->addElement('select', 'children', array( 'required' => true, - 'value' => $this->service, + 'value' => $this->getNode()->getName(), 'multiOptions' => $this->enumServiceList($host), 'label' => $this->translate('Service'), 'description' => $this->translate('The service for this business process node'), - 'validators' => [ - ['Callback', true, [ - 'callback' => function ($value) { - if ($this->node->getShortName() === $value) { - return true; - } - return ! $this->parent->hasMatchingChild($value); - }, - 'messages' => [ - 'callbackValue' => $this->translate('%value% is already defined in this process') - ] - ]] - ] + 'validators' => [[new NoDuplicateChildrenValidator($this, $this->bp, $this->parent), true]] )); } @@ -250,30 +236,19 @@ class EditNodeForm extends QuickForm $this->addElement('checkbox', 'service_override', [ 'ignore' => true, 'class' => 'autosubmit', - 'value' => ! empty($this->statesOverride) ? '1' : null, + 'value' => ! empty($this->node->getStateOverrides()), 'label' => $this->translate('Override Service State'), 'description' => $this->translate('Enable service state overrides') ]); } - protected function addServiceOverrideElements() + protected function addServiceOverrideElement() { - $elements = []; - foreach ($this->enumServiceStateList() as $state => $stateName) { - if ($state == 0) { - continue; - } - $this->addElement('select', $stateName, [ - 'label' => $this->translate($stateName), - 'value' => isset($this->statesOverride[$state]) ? $this->statesOverride[$state] : null, - 'ignore' => true, - 'multiOptions' => $this->optionalEnum($this->enumServiceStateList()), - ]); - $elements[] = $stateName; - } - - $this->addSimpleDisplayGroup($elements, 'override_group', [ - 'legend' => $this->translate('State Overrides') + $this->addElement('stateOverrides', 'stateOverrides', [ + 'required' => true, + 'states' => $this->enumServiceStateList(), + 'value' => $this->node->getStateOverrides(), + 'label' => $this->translate('State Overrides') ]); } @@ -409,21 +384,6 @@ class EditNodeForm extends QuickForm return $serviceStateList; } - protected function statesToString() - { - $stateString = null; - foreach ($this->enumServiceStateList() as $state => $stateName) { - if ($this->getValue($stateName) !== null && $this->getValue($stateName) !== '') { - if ($stateString !== null) { - $stateString .= ','; - } - $stateString .= $state . '-' . $this->getValue($stateName); - } - } - - return $stateString; - } - protected function hasProcesses() { return count($this->enumProcesses()) > 0; @@ -489,14 +449,10 @@ class EditNodeForm extends QuickForm switch ($this->getValue('node_type')) { case 'service': - if ($this->statesToString() !== null) { - $changes->addChildrenToNode( - $this->getValue('children') . ':' . $this->statesToString(), - $this->parent - ); - } else { - $changes->addChildrenToNode($this->getValue('children'), $this->parent); - } + $properties = $this->getValues(); + unset($properties['children']); + $services = [$this->getValue('children') => $properties]; + $changes->addChildrenToNode($services, $this->parent); break; case 'host': case 'process': diff --git a/application/views/helpers/FormStateOverrides.php b/application/views/helpers/FormStateOverrides.php new file mode 100644 index 0000000..74ed2f4 --- /dev/null +++ b/application/views/helpers/FormStateOverrides.php @@ -0,0 +1,40 @@ + $label) { + if ($state === 0) { + continue; + } + + $chosen = $state; + if (isset($value[$state])) { + $chosen = $value[$state]; + } + + $options = [$state => t('Keep actual state')] + $states; + + $html .= ''; + } + + return $html; + } +} diff --git a/library/Businessprocess/BpConfig.php b/library/Businessprocess/BpConfig.php index 96a0a7d..c49d262 100644 --- a/library/Businessprocess/BpConfig.php +++ b/library/Businessprocess/BpConfig.php @@ -460,21 +460,16 @@ class BpConfig return array_key_exists($name, $this->root_nodes); } - public function createService($host, $service, $statesOverride = null) + public function createService($host, $service) { $node = new ServiceNode( (object) array( 'hostname' => $host, - 'service' => $service, - 'statesOverride'=> $statesOverride + 'service' => $service ) ); $node->setBpConfig($this); - if (isset($statesOverride)) { - $this->nodes[$host . ';' . $service . ':' . $statesOverride] = $node; - } else { - $this->nodes[$host . ';' . $service] = $node; - } + $this->nodes[$host . ';' . $service] = $node; $this->hosts[$host] = true; return $node; } @@ -662,19 +657,6 @@ class BpConfig ); } - public function getMatchingNodeNams($name) - { - $matching = []; - - foreach ($this->nodes as $nodeName => $node) { - if ($name === $node->getShortName()) { - $matching[] = $nodeName; - } - } - - return $matching; - } - /** * @return BpNode */ diff --git a/library/Businessprocess/BpNode.php b/library/Businessprocess/BpNode.php index b6f3721..9aeaab8 100644 --- a/library/Businessprocess/BpNode.php +++ b/library/Businessprocess/BpNode.php @@ -142,11 +142,6 @@ class BpNode extends Node return in_array($name, $this->getChildNames()); } - public function hasMatchingChild($name) - { - return in_array($name, $this->getChildShortNames()); - } - public function removeChild($name) { if (($key = array_search($name, $this->getChildNames())) !== false) { @@ -503,20 +498,6 @@ class BpNode extends Node return $this->children; } - protected function getChildShortNames() - { - $ChidrenShortNames = array(); - - foreach ($this->getChildren() as $child) { - $name = $child->getShortName(); - array_push($ChidrenShortNames, $name); - } - - return $ChidrenShortNames; - } - - - /** * Reorder this node's children, in case manual order is not applied */ diff --git a/library/Businessprocess/Modification/NodeAddChildrenAction.php b/library/Businessprocess/Modification/NodeAddChildrenAction.php index 4b9988b..8f9c5e0 100644 --- a/library/Businessprocess/Modification/NodeAddChildrenAction.php +++ b/library/Businessprocess/Modification/NodeAddChildrenAction.php @@ -31,19 +31,26 @@ class NodeAddChildrenAction extends NodeAction { $node = $config->getBpNode($this->getNodeName()); - foreach ($this->children as $name) { + foreach ($this->children as $name => $properties) { + if (is_int($name)) { + // TODO: This may be removed once host nodes also have properties + $name = $properties; + } + if (! $config->hasNode($name) || $config->getNode($name)->getBpConfig()->getName() !== $config->getName()) { if (strpos($name, ';') !== false) { - if (strpos($name, ':') !== false) { - list($host, $service, $statesOverride) = preg_split('~[;:]~', $name, 3); - $config->createService($host, $service, $statesOverride); - } else { - list($host, $service) = preg_split('/;/', $name, 2); + list($host, $service) = preg_split('/;/', $name, 2); - if ($service === 'Hoststatus') { - $config->createHost($host); - } else { - $config->createService($host, $service); + if ($service === 'Hoststatus') { + $child = $config->createHost($host); + } else { + $child = $config->createService($host, $service); + } + + if (is_array($properties) && !empty($properties)) { + foreach ($properties as $key => $value) { + $func = 'set' . ucfirst($key); + $child->$func($value); } } } elseif ($name[0] === '@' && strpos($name, ':') !== false) { diff --git a/library/Businessprocess/Node.php b/library/Businessprocess/Node.php index 5c8f0dd..bec3346 100644 --- a/library/Businessprocess/Node.php +++ b/library/Businessprocess/Node.php @@ -46,7 +46,7 @@ abstract class Node self::NODE_EMPTY => 0 ); - protected $stateOverride = []; + protected $stateOverrides = []; /** @var string Alias of the node */ protected $alias; @@ -199,26 +199,16 @@ abstract class Node return $this; } - protected function setStateOverride($state, $oveRrideState) + public function setStateOverrides(array $overrides) { - $this->stateOverride[(int) $state] = (int) $oveRrideState; + $this->stateOverrides = $overrides; + + return $this; } - public function setStatesOverride($statesOverrideString) + public function getStateOverrides() { - $overrides = explode(',', $statesOverrideString); - - foreach ($overrides as $overrideState) { - if (strpos($overrideState, '-') !== false) { - list($key, $value) = explode('-', $overrideState); - $this->setStateOverride($key, $value); - } - } - } - - public function getStatesOverride() - { - return $this->stateOverride; + return $this->stateOverrides; } /** @@ -270,8 +260,8 @@ abstract class Node ); } - if (isset($this->stateOverride[$this->state])) { - return $this->stateOverride[$this->state]; + if (isset($this->stateOverrides[$this->state])) { + return $this->stateOverrides[$this->state]; } else { return $this->state; } @@ -406,11 +396,6 @@ abstract class Node return $this; } - public function getShortName() - { - return $this->name; - } - public function hasParents() { return count($this->parents) > 0; diff --git a/library/Businessprocess/Renderer/TreeRenderer.php b/library/Businessprocess/Renderer/TreeRenderer.php index 6b3e4fe..3d58075 100644 --- a/library/Businessprocess/Renderer/TreeRenderer.php +++ b/library/Businessprocess/Renderer/TreeRenderer.php @@ -154,7 +154,7 @@ class TreeRenderer extends Renderer { $statesOverrights = []; - $states = $node->getStatesOverride(); + $states = $node->getStateOverrides(); foreach ($states as $originalState => $overrideState) { $statesOverrights[] = (new StateBall(strtolower($node->getStateName($originalState))))->addAttributes([ 'title' => sprintf( @@ -290,7 +290,7 @@ class TreeRenderer extends Renderer 'class' => 'left-side', ]); - if (!empty($node->getStatesOverride())) { + if (! empty($node->getStateOverrides())) { $leftAlign->add($this->getNodeStateOverride($node)); } diff --git a/library/Businessprocess/ServiceNode.php b/library/Businessprocess/ServiceNode.php index fc308f6..6160bce 100644 --- a/library/Businessprocess/ServiceNode.php +++ b/library/Businessprocess/ServiceNode.php @@ -19,12 +19,7 @@ class ServiceNode extends MonitoredNode public function __construct($object) { - if (isset($object->statesOverride)) { - $this->name = $object->hostname . ';' . $object->service . ':' . $object->statesOverride; - $this->setStatesOverride($object->statesOverride); - } else { - $this->name = $object->hostname . ';' . $object->service; - } + $this->name = $object->hostname . ';' . $object->service; $this->hostname = $object->hostname; $this->service = $object->service; if (isset($object->state)) { @@ -72,11 +67,6 @@ class ServiceNode extends MonitoredNode { return $this->getHostAlias() . ': ' . $this->alias; } - - public function getShortName() - { - return $this->hostname . ';' . $this->service; - } public function getUrl() { diff --git a/library/Businessprocess/State/MonitoringState.php b/library/Businessprocess/State/MonitoringState.php index beea0af..d317528 100644 --- a/library/Businessprocess/State/MonitoringState.php +++ b/library/Businessprocess/State/MonitoringState.php @@ -122,27 +122,24 @@ class MonitoringState $key .= ';Hoststatus'; } - $nodesNames = $config->getMatchingNodeNams($key); - foreach ($nodesNames as $nodeName) { - // We fetch more states than we need, so skip unknown ones - if (! $config->hasNode($nodeName)) { - return; - } + // We fetch more states than we need, so skip unknown ones + if (! $config->hasNode($key)) { + return; + } - $node = $config->getNode($nodeName); + $node = $config->getNode($key); - if ($row->state !== null) { - $node->setState($row->state)->setMissing(false); - } - if ($row->last_state_change !== null) { - $node->setLastStateChange($row->last_state_change); - } - if ((int) $row->in_downtime === 1) { - $node->setDowntime(true); - } - if ((int) $row->ack === 1) { - $node->setAck(true); - } + if ($row->state !== null) { + $node->setState($row->state)->setMissing(false); + } + if ($row->last_state_change !== null) { + $node->setLastStateChange($row->last_state_change); + } + if ((int) $row->in_downtime === 1) { + $node->setDowntime(true); + } + if ((int) $row->ack === 1) { + $node->setAck(true); } $node->setAlias($row->display_name); diff --git a/library/Businessprocess/Storage/LegacyConfigParser.php b/library/Businessprocess/Storage/LegacyConfigParser.php index fcf382c..1afc256 100644 --- a/library/Businessprocess/Storage/LegacyConfigParser.php +++ b/library/Businessprocess/Storage/LegacyConfigParser.php @@ -233,6 +233,24 @@ class LegacyConfigParser $bp->getBpNode($name)->setInfoUrl($url); } + protected function parseStateOverrides(&$line, BpConfig $bp) + { + // state_overrides !|n-n[,n-n]!|n-n[,n-n] + $segments = preg_split('~\s*!\s*~', substr($line, 16)); + $node = $bp->getNode(array_shift($segments)); + foreach ($segments as $overrideDef) { + list($childName, $overrides) = preg_split('~\s*\|\s*~', $overrideDef, 2); + + $stateOverrides = []; + foreach (preg_split('~\s*,\s*~', $overrides) as $override) { + list($from, $to) = preg_split('~\s*-\s*~', $override, 2); + $stateOverrides[(int) $from] = (int) $to; + } + + $node->getChildByName($childName)->setStateOverrides($stateOverrides); + } + } + protected function parseExtraLine(&$line, $typeLength, BpConfig $bp) { $type = substr($line, 0, $typeLength); @@ -251,6 +269,9 @@ class LegacyConfigParser case 'info_url': $this->parseInfoUrl($line, $bp); break; + case 'state_overrides': + $this->parseStateOverrides($line, $bp); + break; case 'template': // compat, ignoring for now break; @@ -282,9 +303,9 @@ class LegacyConfigParser return; } - // Space found in the first 14 cols? Might be a line with extra information + // Space found in the first 16 cols? Might be a line with extra information $pos = strpos($line, ' '); - if ($pos !== false && $pos < 14) { + if ($pos !== false && $pos < 16) { if ($this->parseExtraLine($line, $pos, $bp)) { return; } @@ -335,17 +356,11 @@ class LegacyConfigParser if ($bp->hasNode($val)) { $node->addChild($bp->getNode($val)); } else { - if (strpos($val, ':') !== false) { - list($host, $service, $statesOverride) = preg_split('~[;:]~', $val, 3); - $node->addChild($bp->createService($host, $service, $statesOverride)); + list($host, $service) = preg_split('~;~', $val, 2); + if ($service === 'Hoststatus') { + $node->addChild($bp->createHost($host)); } else { - list($host, $service) = preg_split('~;~', $val, 2); - - if ($service === 'Hoststatus') { - $node->addChild($bp->createHost($host)); - } else { - $node->addChild($bp->createService($host, $service)); - } + $node->addChild($bp->createService($host, $service)); } } } elseif ($val[0] === '@') { diff --git a/library/Businessprocess/Storage/LegacyConfigRenderer.php b/library/Businessprocess/Storage/LegacyConfigRenderer.php index 77a1d13..eba26bc 100644 --- a/library/Businessprocess/Storage/LegacyConfigRenderer.php +++ b/library/Businessprocess/Storage/LegacyConfigRenderer.php @@ -158,6 +158,7 @@ class LegacyConfigRenderer public static function renderSingleBpNode(BpNode $node) { return static::renderExpression($node) + . static::renderStateOverrides($node) . static::renderDisplay($node) . static::renderInfoUrl($node); } @@ -214,6 +215,27 @@ class LegacyConfigRenderer } } + public static function renderStateOverrides(BpNode $node) + { + $stateOverrides = ''; + foreach ($node->getChildren() as $child) { + $overrides = []; + foreach ($child->getStateOverrides() as $from => $to) { + $overrides[] = sprintf('%d-%d', $from, $to); + } + + if (! empty($overrides)) { + $stateOverrides .= '!' . $child->getName() . '|' . join(',', $overrides); + } + } + + if (! $stateOverrides) { + return ''; + } + + return 'state_overrides ' . $node->getName() . $stateOverrides . "\n"; + } + /** * @param BpNode $node * @return string diff --git a/library/Businessprocess/Web/Form/Element/StateOverrides.php b/library/Businessprocess/Web/Form/Element/StateOverrides.php new file mode 100644 index 0000000..49cb233 --- /dev/null +++ b/library/Businessprocess/Web/Form/Element/StateOverrides.php @@ -0,0 +1,52 @@ +states = $states; + + return $this; + } + + /** + * Get the overridable states + * + * @return array + */ + public function getStates() + { + return $this->states; + } + + public function init() + { + $this->setIsArray(true); + } + + public function setValue($value) + { + $cleanedValue = []; + foreach ($value as $from => $to) { + if ((int) $from !== (int) $to) { + $cleanedValue[$from] = $to; + } + } + + return parent::setValue($cleanedValue); + } +} diff --git a/library/Businessprocess/Web/Form/Validator/NoDuplicateChildrenValidator.php b/library/Businessprocess/Web/Form/Validator/NoDuplicateChildrenValidator.php index ecdd345..9676de0 100644 --- a/library/Businessprocess/Web/Form/Validator/NoDuplicateChildrenValidator.php +++ b/library/Businessprocess/Web/Form/Validator/NoDuplicateChildrenValidator.php @@ -43,7 +43,7 @@ class NoDuplicateChildrenValidator extends Zend_Validate_Abstract } elseif ($this->form instanceof EditNodeForm && $this->form->getNode()->getName() === $value) { $found = false; } else { - $found = $this->parent->hasMatchingChild($value); + $found = $this->parent->hasChild($value); } if (! $found) { diff --git a/public/css/module.less b/public/css/module.less index 2da19a2..8d1dcf6 100644 --- a/public/css/module.less +++ b/public/css/module.less @@ -962,37 +962,27 @@ form dt label { } } -fieldset.collapsed { - dd, dt, ul, div { - display: none; - } - } +#stateOverrides-element { + display: inline-table; + table-layout: fixed; + border-spacing: .5em; + padding: 0; -fieldset { - margin-top: 15px; - padding: 0 0 1.5em 0; - border: none; + label { + display: table-row; - legend { - margin: 0em 0 0.5em 0; - font-size: 1em; - box-shadow: 0 3px 4px -4px rgba(0,0,0,0.2); - font-weight: bold; - width: 100%; - padding-left: 0.5em; - line-height: 2em; - user-select: none; - - &:hover { - border-color: @text-color; - } - } - dd, dt, ul, div { - display: none; + span, select { + display: table-cell; } - margin-bottom: 0.2em; - padding-bottom: 0; + span { + width: 10em; + } + + select { + width: 26em; + } + } } form fieldset {