diff --git a/application/forms/AddEscalationForm.php b/application/forms/AddEscalationForm.php deleted file mode 100644 index 44e2ba6ca..000000000 --- a/application/forms/AddEscalationForm.php +++ /dev/null @@ -1,42 +0,0 @@ - ['add-escalation-form', 'icinga-form', 'icinga-controls'], - 'name' => 'add-escalation-form' - ]; - - - protected function assemble() - { - $this->add($this->createCsrfCounterMeasure(Session::getSession()->getId())); - $this->add($this->createUidElement()); - - - $this->addElement( - 'submitButton', - 'add', - [ - 'class' => ['add-button', 'control-button', 'spinner'], - 'label' => new Icon('plus'), - 'title' => $this->translate('Add a new escalation') - ] - ); - } -} diff --git a/application/forms/AddFilterForm.php b/application/forms/AddFilterForm.php deleted file mode 100644 index aee6ded69..000000000 --- a/application/forms/AddFilterForm.php +++ /dev/null @@ -1,42 +0,0 @@ - ['add-filter-form', 'icinga-form', 'icinga-controls'], - 'name' => 'add-filter-form' - ]; - - - protected function assemble() - { - $this->add($this->createCsrfCounterMeasure(Session::getSession()->getId())); - $this->add($this->createUidElement()); - - - $this->addElement( - 'submitButton', - 'add', - [ - 'class' => ['add-button', 'control-button', 'spinner'], - 'label' => new Icon('plus'), - 'title' => $this->translate('Add filter') - ] - ); - } -} diff --git a/application/forms/BaseEscalationForm.php b/application/forms/BaseEscalationForm.php deleted file mode 100644 index d4dab933b..000000000 --- a/application/forms/BaseEscalationForm.php +++ /dev/null @@ -1,89 +0,0 @@ - ['escalation-form', 'icinga-form', 'icinga-controls']]; - - /** @var int The count of existing conditions/recipients */ - protected $count; - - /** @var bool Whether the `add` button is pressed */ - protected $isAddPressed; - - /** @var ValidHtml[] */ - protected $options; - - /** @var ?int The counter of removed option */ - protected $removedOptionNumber; - - public function __construct(int $count) - { - $this->count = $count; - } - - public function hasBeenSubmitted() - { - return false; - } - - abstract protected function assembleElements(): void; - - protected function createAddButton(): FormElement - { - $addButton = $this->createElement( - 'submitButton', - 'add', - [ - 'class' => ['add-button', 'control-button', 'spinner'], - 'label' => new Icon('plus'), - 'title' => $this->translate('Add more'), - 'formnovalidate' => true - ] - ); - - $this->registerElement($addButton); - - return $addButton; - } - - protected function assemble() - { - $this->add($this->createCsrfCounterMeasure(Session::getSession()->getId())); - $this->add($this->createUidElement()); - - $addButton = $this->createAddButton(); - - $button = $this->getPressedSubmitElement(); - if ($button && $button->getName() === 'add') { - $this->isAddPressed = true; - } - - if ($this->count || $this->isAddPressed) { - $this->assembleElements(); - } - - $this->add($addButton); - } - - public function isAddButtonPressed(): ?bool - { - return $this->isAddPressed; - } -} diff --git a/application/forms/EscalationConditionForm.php b/application/forms/EscalationConditionForm.php deleted file mode 100644 index 96b6b51d5..000000000 --- a/application/forms/EscalationConditionForm.php +++ /dev/null @@ -1,286 +0,0 @@ -addAttributes(['class' => 'escalation-condition-form']); - - parent::__construct($count ?? 0); - } - - protected function assembleElements(): void - { - $end = $this->count; - if ($this->isAddPressed) { - $end++; - } - - foreach (range(1, $end) as $count) { - $col = $this->createElement( - 'select', - 'column' . $count, - [ - 'class' => ['autosubmit', 'left-operand'], - 'options' => [ - '' => sprintf(' - %s - ', $this->translate('Please choose')), - 'incident_severity' => $this->translate('Incident Severity'), - 'incident_age' => $this->translate('Incident Age') - ], - 'disabledOptions' => [''], - 'required' => true - ] - ); - - $operators = ['=', '>', '>=', '<', '<=', '!=']; - $op = $this->createElement( - 'select', - 'operator' . $count, - [ - 'class' => ['class' => 'operator-input', 'autosubmit'], - 'options' => array_combine($operators, $operators), - 'required' => true - ] - ); - - switch ($this->getPopulatedValue('column' . $count)) { - case 'incident_severity': - $val = $this->createElement( - 'select', - 'value' . $count, - [ - 'class' => ['autosubmit', 'right-operand'], - 'options' => [ - 'ok' => $this->translate('Ok', 'notification.severity'), - 'debug' => $this->translate('Debug', 'notification.severity'), - 'info' => $this->translate('Information', 'notification.severity'), - 'notice' => $this->translate('Notice', 'notification.severity'), - 'warning' => $this->translate('Warning', 'notification.severity'), - 'err' => $this->translate('Error', 'notification.severity'), - 'crit' => $this->translate('Critical', 'notification.severity'), - 'alert' => $this->translate('Alert', 'notification.severity'), - 'emerg' => $this->translate('Emergency', 'notification.severity') - ] - ] - ); - - if ( - $this->getPopulatedValue('type' . $count) !== 'incident_severity' - && $this->getPopulatedValue('type' . $count) !== null - ) { - $this->clearPopulatedValue('type' . $count); - $this->clearPopulatedValue('value' . $count); - } - - $this->addElement('hidden', 'type' . $count, [ - 'ignore' => true, - 'value' => 'incident_severity' - ]); - - break; - case 'incident_age': - $val = $this->createElement( - 'text', - 'value' . $count, - [ - 'required' => true, - 'class' => ['autosubmit', 'right-operand'], - 'validators' => [new CallbackValidator(function ($value, $validator) { - if (! preg_match('~^\d+(?:\.?\d*)?[hms]{1}$~', $value)) { - $validator->addMessage($this->translate( - 'Only numbers with optional fractions (separated by a dot)' - . ' and one of these suffixes are allowed: h, m, s' - )); - - return false; - } - - return true; - })] - ] - ); - - if ( - $this->getPopulatedValue('type' . $count) !== 'incident_age' - && $this->getPopulatedValue('type' . $count) !== null - ) { - $this->clearPopulatedValue('type' . $count); - $this->clearPopulatedValue('value' . $count); - } - - $this->addElement('hidden', 'type' . $count, [ - 'ignore' => true, - 'value' => 'incident_age' - ]); - - break; - default: - $val = $this->createElement('text', 'value' . $count, [ - 'class' => 'right-operand', - 'placeholder' => $this->translate('Please make a decision'), - 'disabled' => true - ]); - } - - $this->registerElement($col); - $this->registerElement($op); - $this->registerElement($val); - - (new EventRuleDecorator())->decorate($val); - - $this->options[$count] = Html::tag( - 'li', - ['class' => 'option'], - [$col, $op, $val, $this->createRemoveButton($count)] - ); - } - - $this->handleRemove(); - - $this->add(Html::tag('ul', ['class' => 'options'], $this->options)); - } - - public function getValues() - { - $filter = Filter::any(); - - if ($this->count > 0) { // if count is 0, loop runs in reverse direction - foreach (range(1, $this->count) as $count) { - if ($this->removedOptionNumber === $count) { - continue; // removed option - } - - $chosenType = $this->getValue('column' . $count, 'placeholder'); - - $filterStr = $chosenType - . $this->getValue('operator' . $count) - . ($this->getValue('value' . $count) ?? ($chosenType === 'incident_severity' ? 'ok' : '')); - - $filter->add(QueryString::parse($filterStr)); - } - } - - if ($this->isAddPressed) { - $filter->add(QueryString::parse('placeholder=')); - } - - return (new FilterRenderer($filter)) - ->render(); - } - - public function populate($values) - { - foreach ($values as $key => $condition) { - if (! is_int($key)) { - // csrf token and uid - continue; - } - - $count = $key + 1; - if (empty($condition)) { // when other conditions are removed and only 1 pending with no values - $values['column' . $count] = null; - $values['operator' . $count] = null; - $values['value' . $count] = null; - - continue; - } - - $filter = QueryString::parse($condition); - - $values['column' . $count] = $filter->getColumn() === 'placeholder' ? null : $filter->getColumn(); - $values['operator' . $count] = QueryString::getRuleSymbol($filter); - $values['value' . $count] = $filter->getValue(); - } - - return parent::populate($values); - } - - protected function createRemoveButton(int $count): ?FormElement - { - if ($this->deleteRemoveButton && $this->count === 1 && ! $this->isAddPressed) { - return null; - } - - $removeButton = $this->createElement( - 'submitButton', - 'remove_' . $count, - [ - 'class' => ['remove-button', 'control-button', 'spinner'], - 'label' => new Icon('minus'), - 'title' => $this->translate('Remove'), - 'formnovalidate' => true - ] - ); - - $this->registerElement($removeButton); - - return $removeButton; - } - - protected function handleRemove(): void - { - $button = $this->getPressedSubmitElement(); - - if ($button && $button->getName() !== 'add') { - [$name, $toRemove] = explode('_', $button->getName(), 2); - $toRemove = (int) $toRemove; - $this->removedOptionNumber = $toRemove; - $optionCount = count($this->options); - - for ($i = $toRemove; $i < $optionCount; $i++) { - $nextCount = $i + 1; - $this->getElement('column' . $nextCount)->setName('column' . $i); - $this->getElement('operator' . $nextCount)->setName('operator' . $i); - $this->getElement('value' . $nextCount)->setName('value' . $i); - - $this->getElement('remove_' . $nextCount)->setName('remove_' . $i); - } - - unset($this->options[$toRemove]); - - if ($this->deleteRemoveButton && count($this->options) === 1) { - $key = array_key_last($this->options); - $this->options[$key]->remove($this->getElement('remove_' . $key)); - } - } - - if (empty($this->options)) { - $this->addAttributes(['class' => 'count-zero-escalation-condition-form']); - } else { - $this->getAttributes() - ->remove('class', 'count-zero-escalation-condition-form'); - } - } - - /** - * Whether to delete the remove button - * - * @param bool $delete - * - * @return $this - */ - public function deleteRemoveButton(bool $delete = true): self - { - $this->deleteRemoveButton = $delete; - - return $this; - } -} diff --git a/application/forms/EscalationRecipientForm.php b/application/forms/EscalationRecipientForm.php deleted file mode 100644 index 006d71a86..000000000 --- a/application/forms/EscalationRecipientForm.php +++ /dev/null @@ -1,232 +0,0 @@ -addAttributes(['class' => 'escalation-recipient-form']); - - parent::__construct($count ?? 1); - } - - protected function fetchOptions(): array - { - $options = []; - foreach (Contact::on(Database::get()) as $contact) { - $options['Contacts']['contact_' . $contact->id] = $contact->full_name; - } - - foreach (Contactgroup::on(Database::get()) as $contactgroup) { - $options['Contact Groups']['contactgroup_' . $contactgroup->id] = $contactgroup->name; - } - - foreach (Schedule::on(Database::get()) as $schedule) { - $options['Schedules']['schedule_' . $schedule->id] = $schedule->name; - } - - return $options; - } - - protected function assembleElements(): void - { - $end = $this->count; - if ($this->isAddPressed) { - $end++; - } - - foreach (range(1, $end) as $count) { - $escalationRecipientId = $this->createElement( - 'hidden', - 'id' . $count - ); - - $this->registerElement($escalationRecipientId); - - $col = $this->createElement( - 'select', - 'column' . $count, - [ - 'class' => ['autosubmit', 'left-operand'], - 'options' => [ - '' => sprintf(' - %s - ', $this->translate('Please choose')) - ] + $this->fetchOptions(), - 'disabledOptions' => [''], - 'required' => true - ] - ); - - $this->registerElement($col); - - $options = ['' => sprintf(' - %s - ', $this->translate('Please choose'))]; - $options += Channel::fetchChannelNames(Database::get()); - - $val = $this->createElement( - 'select', - 'value' . $count, - [ - 'class' => ['autosubmit', 'right-operand'], - 'options' => $options, - 'disabledOptions' => [''] - ] - ); - - if ($this->getValue('column' . $count) !== null) { - $recipient = explode('_', $this->getValue('column' . $count)); - if ($recipient[0] === 'contact') { - $options[''] = $this->translate('Default User Channel'); - - $val->setOptions($options); - - $val->setDisabledOptions([]); - - if ($this->getPopulatedValue('value' . $count, '') === '') { - $val->addAttributes(['class' => 'default-channel']); - } - } - } else { - $val = $this->createElement('text', 'value' . $count, [ - 'class' => 'right-operand', - 'placeholder' => $this->translate('Please make a decision'), - 'disabled' => true - ]); - } - - $this->registerElement($val); - - $this->options[$count] = Html::tag( - 'li', - ['class' => 'option'], - [$col, $val, $this->createRemoveButton($count)] - ); - } - - $this->handleRemove(); - - $this->add(Html::tag('ul', ['class' => 'options'], $this->options)); - } - - public function getValues() - { - $end = $this->count; - if ($this->isAddPressed) { - $end++; - } - - $values = []; - foreach (range(1, $end) as $count) { - if ($this->removedOptionNumber === $count) { - continue; // removed option - } - - $value = []; - $value['channel_id'] = $this->getValue('value' . $count); - $value['id'] = $this->getValue('id' . $count); - - $columnName = $this->getValue('column' . $count); - - if ($columnName === null) { - $values[] = $value; - continue; - } - - [$columnName, $id] = explode('_', $columnName, 2); - - $value[$columnName . '_id'] = $id; - - $values[] = $value; - } - - return $values; - } - - public function populate($values) - { - /** @var int $key */ - foreach ($values as $key => $condition) { - if (is_array($condition)) { - $count = 0; - foreach ($condition as $elementName => $elementValue) { - if ($elementValue === null) { - continue; - } - - $count = $key + 1; - $selectedOption = str_replace('id', $elementValue, $elementName, $replaced); - if ($replaced && $elementName !== 'channel_id') { - $values['column' . $count] = $selectedOption; - } elseif ($elementName === 'channel_id') { - $values['value' . $count] = $elementValue; - } - } - - if (isset($condition['id'])) { - $values['id' . $count] = $condition['id']; - } - } - } - - return parent::populate($values); - } - - protected function createRemoveButton(int $count): ?FormElement - { - if ($this->count === 1 && ! $this->isAddPressed) { - return null; - } - - $removeButton = $this->createElement( - 'submitButton', - 'remove_' . $count, - [ - 'class' => ['remove-button', 'control-button', 'spinner'], - 'label' => new Icon('minus'), - 'title' => $this->translate('Remove'), - 'formnovalidate' => true - ] - ); - - $this->registerElement($removeButton); - - return $removeButton; - } - - protected function handleRemove(): void - { - $button = $this->getPressedSubmitElement(); - - if ($button && $button->getName() !== 'add') { - [$name, $toRemove] = explode('_', $button->getName(), 2); - $toRemove = (int) $toRemove; - $this->removedOptionNumber = $toRemove; - $optionCount = count($this->options); - - for ($i = $toRemove; $i < $optionCount; $i++) { - $nextCount = $i + 1; - $this->getElement('column' . $nextCount)->setName('column' . $i); - $this->getElement('value' . $nextCount)->setName('value' . $i); - - $this->getElement('remove_' . $nextCount)->setName('remove_' . $i); - } - - unset($this->options[$toRemove]); - - if (count($this->options) === 1) { - $key = array_key_last($this->options); - $this->options[$key]->remove($this->getElement('remove_' . $key)); - } - } - } -} diff --git a/application/forms/RemoveEscalationForm.php b/application/forms/RemoveEscalationForm.php deleted file mode 100644 index 4bc9cb798..000000000 --- a/application/forms/RemoveEscalationForm.php +++ /dev/null @@ -1,70 +0,0 @@ - ['remove-escalation-form', 'icinga-form', 'icinga-controls'], - ]; - - /** @var bool */ - private $disableRemoveButtton; - - protected function assemble() - { - $this->add($this->createCsrfCounterMeasure(Session::getSession()->getId())); - $this->add($this->createUidElement()); - - $this->addElement( - 'submitButton', - 'remove', - [ - 'class' => ['remove-button', 'control-button', 'spinner'], - 'label' => new Icon('minus') - ] - ); - - $this->getElement('remove') - ->getAttributes() - ->registerAttributeCallback('disabled', function () { - return $this->disableRemoveButtton; - }) - ->registerAttributeCallback('title', function () { - if ($this->disableRemoveButtton) { - return $this->translate( - 'There exist active incidents for this escalation and hence cannot be removed' - ); - } - - return $this->translate('Remove escalation'); - }); - } - - /** - * Method to set disabled state of remove button - * - * @param bool $state - * - * @return $this - */ - public function setRemoveButtonDisabled(bool $state = false) - { - $this->disableRemoveButtton = $state; - - return $this; - } -} diff --git a/application/forms/SaveEventRuleForm.php b/application/forms/SaveEventRuleForm.php deleted file mode 100644 index f7bd7aa0f..000000000 --- a/application/forms/SaveEventRuleForm.php +++ /dev/null @@ -1,481 +0,0 @@ - ['icinga-controls', 'save-event-rule'], - 'name' => 'save-event-rule' - ]; - - /** @var bool Whether to disable the submit button */ - protected $disableSubmitButton = false; - - /** @var string The label to use on the submit button */ - protected $submitLabel; - - /** @var bool Whether to show a button to delete the rule */ - protected $showRemoveButton = false; - - /** @var bool Whether to show a button to dismiss cached changes */ - protected $showDismissChangesButton = false; - - /** @var bool Whether to disable the remove button */ - protected $disableRemoveButton = false; - - /** - * Create a new SaveEventRuleForm - */ - public function __construct() - { - $this->on(self::ON_SENT, function () { - if ($this->hasBeenRemoved()) { - $this->emit(self::ON_REMOVE, [$this]); - } - }); - } - - public function hasBeenSubmitted(): bool - { - return $this->hasBeenSent() && $this->getPressedSubmitElement() !== null; - } - - /** - * Set whether to enable or disable the submit button - * - * @param bool $state - * - * @return $this - */ - public function setSubmitButtonDisabled(bool $state = true): self - { - $this->disableSubmitButton = $state; - - return $this; - } - - /** - * Set whether to enable or disable the remove button - * - * @param bool $state - * - * @return $this - */ - public function setRemoveButtonDisabled(bool $state = true): self - { - $this->disableRemoveButton = $state; - - return $this; - } - - /** - * Set the submit label - * - * @param string $label - * - * @return $this - */ - public function setSubmitLabel(string $label): self - { - $this->submitLabel = $label; - - return $this; - } - - /** - * Get the submit label - * - * @return string - */ - public function getSubmitLabel(): string - { - return $this->submitLabel ?? t('Add Event Rule'); - } - - /** - * Set whether to show a button to delete the rule - * - * @param bool $state - * - * @return $this - */ - public function setShowRemoveButton(bool $state = true): self - { - $this->showRemoveButton = $state; - - return $this; - } - - /** - * Set whether to show a button to dismiss cached changes - * - * @param bool $state - * - * @return $this - */ - public function setShowDismissChangesButton(bool $state = true): self - { - $this->showDismissChangesButton = $state; - - return $this; - } - - /** - * Get whether the user pushed the remove button - * - * @return bool - */ - private function hasBeenRemoved(): bool - { - $btn = $this->getPressedSubmitElement(); - $csrf = $this->getElement('CSRFToken'); - - return $csrf !== null && $csrf->isValid() && $btn !== null && $btn->getName() === 'remove'; - } - - public function isValidEvent($event) - { - if ($event === self::ON_REMOVE) { - return true; - } - - return parent::isValidEvent($event); - } - - protected function assemble() - { - $this->addElement($this->createUidElement()); - $this->addElement($this->createCsrfCounterMeasure(Session::getSession()->getId())); - - $this->addElement('submit', 'submit', [ - 'label' => $this->getSubmitLabel(), - 'class' => 'btn-primary' - ]); - - $this->getElement('submit') - ->getAttributes() - ->registerAttributeCallback('disabled', function () { - return $this->disableSubmitButton; - }); - - $additionalButtons = []; - if ($this->showRemoveButton) { - $removeBtn = $this->createElement('submit', 'remove', [ - 'label' => $this->translate('Delete Event Rule'), - 'class' => 'btn-remove', - 'formnovalidate' => true - ]); - $this->registerElement($removeBtn); - - $this->getElement('remove') - ->getAttributes() - ->registerAttributeCallback('disabled', function () { - return $this->disableRemoveButton; - }) - ->registerAttributeCallback('title', function () { - if ($this->disableRemoveButton) { - return $this->translate( - 'There exist active incidents for this event rule and hence cannot be deleted' - ); - } - }); - - $additionalButtons[] = $removeBtn; - } - - if ($this->showDismissChangesButton) { - $clearCacheBtn = $this->createElement('submit', 'discard_changes', [ - 'label' => $this->translate('Discard Changes'), - 'class' => 'btn-discard-changes', - 'formnovalidate' => true - ]); - $this->registerElement($clearCacheBtn); - $additionalButtons[] = $clearCacheBtn; - } - - $this->getElement('submit')->prependWrapper((new HtmlDocument())->setHtmlContent(...$additionalButtons)); - } - - /** - * Add a new event rule with the given configuration - * - * @param array $config - * - * @return int The id of the new event rule - */ - public function addRule(array $config): int - { - if (! isset($config['name'])) { - throw new Exception('Name of the event rule is not set'); - } - - $db = Database::get(); - - $db->beginTransaction(); - - $db->insert('rule', [ - 'name' => $config['name'], - 'timeperiod_id' => $config['timeperiod_id'] ?? null, - 'object_filter' => $config['object_filter'] ?? null, - 'is_active' => $config['is_active'] ?? 'n' - ]); - $ruleId = $db->lastInsertId(); - - foreach ($config['rule_escalation'] ?? [] as $position => $escalationConfig) { - $db->insert('rule_escalation', [ - 'rule_id' => $ruleId, - 'position' => $position, - 'condition' => $escalationConfig['condition'] ?? null, - 'name' => $escalationConfig['name'] ?? null, - 'fallback_for' => $escalationConfig['fallback_for'] ?? null - ]); - $escalationId = $db->lastInsertId(); - - foreach ($escalationConfig['recipient'] ?? [] as $recipientConfig) { - $data = [ - 'rule_escalation_id' => $escalationId, - 'channel_id' => $recipientConfig['channel_id'] - ]; - - switch (true) { - case isset($recipientConfig['contact_id']): - $data['contact_id'] = $recipientConfig['contact_id']; - break; - case isset($recipientConfig['contactgroup_id']): - $data['contactgroup_id'] = $recipientConfig['contactgroup_id']; - break; - case isset($recipientConfig['schedule_id']): - $data['schedule_id'] = $recipientConfig['schedule_id']; - break; - } - - $db->insert('rule_escalation_recipient', $data); - } - } - - $db->commitTransaction(); - - return $ruleId; - } - - /** - * Insert to or update Escalations and its recipients in Db - * - * @param $ruleId - * @param array $escalations - * @param Connection $db - * @param bool $insert - * - * @return void - */ - private function insertOrUpdateEscalations($ruleId, array $escalations, Connection $db, bool $insert = false): void - { - foreach ($escalations as $position => $escalationConfig) { - if ($insert) { - $db->insert('rule_escalation', [ - 'rule_id' => $ruleId, - 'position' => $position, - 'condition' => $escalationConfig['condition'] ?? null, - 'name' => $escalationConfig['name'] ?? null, - 'fallback_for' => $escalationConfig['fallback_for'] ?? null - ]); - - $escalationId = $db->lastInsertId(); - } else { - $escalationId = $escalationConfig['id']; - - $db->update('rule_escalation', [ - 'position' => $position, - 'condition' => $escalationConfig['condition'] ?? null, - 'name' => $escalationConfig['name'] ?? null, - 'fallback_for' => $escalationConfig['fallback_for'] ?? null - ], ['id = ?' => $escalationId, 'rule_id = ?' => $ruleId]); - $recipientsToRemove = []; - - $recipients = RuleEscalationRecipient::on($db) - ->columns('id') - ->filter(Filter::equal('rule_escalation_id', $escalationId)); - - foreach ($recipients as $recipient) { - $recipientId = $recipient->id; - $recipientInCache = array_filter( - $escalationConfig['recipient'], - function (array $element) use ($recipientId) { - return (int) $element['id'] === $recipientId; - } - ); - - if (empty($recipientInCache)) { - // Recipients to remove from Db not in cache - $recipientsToRemove[] = $recipientId; - } - } - - if (! empty($recipientsToRemove)) { - $db->delete('rule_escalation_recipient', ['id IN (?)' => $recipientsToRemove]); - } - } - - foreach ($escalationConfig['recipient'] ?? [] as $recipientConfig) { - $data = [ - 'rule_escalation_id' => $escalationId, - 'channel_id' => $recipientConfig['channel_id'] - ]; - - switch (true) { - case isset($recipientConfig['contact_id']): - $data['contact_id'] = $recipientConfig['contact_id']; - $data['contactgroup_id'] = null; - $data['schedule_id'] = null; - break; - case isset($recipientConfig['contactgroup_id']): - $data['contact_id'] = null; - $data['contactgroup_id'] = $recipientConfig['contactgroup_id']; - $data['schedule_id'] = null; - break; - case isset($recipientConfig['schedule_id']): - $data['contact_id'] = null; - $data['contactgroup_id'] = null; - $data['schedule_id'] = $recipientConfig['schedule_id']; - break; - } - - if (! isset($recipientConfig['id'])) { - $db->insert('rule_escalation_recipient', $data); - } else { - $db->update('rule_escalation_recipient', $data, ['id = ?' => $recipientConfig['id']]); - } - } - } - } - - /** - * Edit an existing event rule - * - * @param int $id The id of the event rule - * @param array $config The new configuration - * - * @return void - */ - public function editRule(int $id, array $config): void - { - $db = Database::get(); - - $db->beginTransaction(); - - $db->update('rule', [ - 'name' => $config['name'], - 'timeperiod_id' => $config['timeperiod_id'] ?? null, - 'object_filter' => $config['object_filter'] ?? null, - 'is_active' => $config['is_active'] ?? 'n' - ], ['id = ?' => $id]); - - $escalationsFromDb = RuleEscalation::on($db) - ->filter(Filter::equal('rule_id', $id)); - - $escalationsInCache = $config['rule_escalation']; - - $escalationsToUpdate = []; - $escalationsToRemove = []; - - foreach ($escalationsFromDb as $escalationInDB) { - $escalationId = $escalationInDB->id; - $escalationInCache = array_filter($escalationsInCache, function (array $element) use ($escalationId) { - return (int) $element['id'] === $escalationId; - }); - - if ($escalationInCache) { - $position = array_key_first($escalationInCache); - // Escalations in DB to update - $escalationsToUpdate[$position] = $escalationInCache[$position]; - unset($escalationsInCache[$position]); - } else { - // Escalation in DB to remove - $escalationsToRemove[] = $escalationId; - } - } - - // Escalations to add - $escalationsToAdd = $escalationsInCache; - - if (! empty($escalationsToRemove)) { - $db->delete('rule_escalation_recipient', ['rule_escalation_id IN (?)' => $escalationsToRemove]); - $db->delete('rule_escalation', ['id IN (?)' => $escalationsToRemove]); - } - - if (! empty($escalationsToAdd)) { - $this->insertOrUpdateEscalations($id, $escalationsToAdd, $db, true); - } - - if (! empty($escalationsToUpdate)) { - $this->insertOrUpdateEscalations($id, $escalationsToUpdate, $db); - } - - $db->commitTransaction(); - } - - /** - * Remove the given event rule - * - * @param int $id - * - * @return void - */ - public function removeRule(int $id): void - { - $db = Database::get(); - - $db->beginTransaction(); - - $escalations = RuleEscalation::on($db) - ->columns('id') - ->filter(Filter::equal('rule_id', $id)); - - $escalationsToRemove = []; - foreach ($escalations as $escalation) { - $escalationsToRemove[] = $escalation->id; - } - - if (! empty($escalationsToRemove)) { - $db->delete('rule_escalation_recipient', ['rule_escalation_id IN (?)' => $escalationsToRemove]); - } - - $db->delete('rule_escalation', ['rule_id = ?' => $id]); - $db->delete('rule', ['id = ?' => $id]); - - $db->commitTransaction(); - } - - protected function onError() - { - foreach ($this->getMessages() as $message) { - if ($message instanceof Exception) { - Notification::error($this->translate($message->getMessage())); - } - } - } -} diff --git a/library/Notifications/Widget/EventRuleConfig.php b/library/Notifications/Widget/EventRuleConfig.php deleted file mode 100644 index 1ae0a4f9d..000000000 --- a/library/Notifications/Widget/EventRuleConfig.php +++ /dev/null @@ -1,417 +0,0 @@ - 'event-rule-detail' - ]; - - public const ON_CHANGE = 'on_change'; - - protected $tag = 'div'; - - /** @var Form[] */ - private $forms; - - /** @var array The config */ - protected $config; - - /** @var Url The url to open the SearchEditor at */ - protected $searchEditorUrl; - - /** @var array> */ - private $escalationForms = []; - - /** @var array */ - private $removeEscalationForms; - - /** @var int */ - private $numEscalations; - - public function __construct(Url $searchEditorUrl, $config = []) - { - $this->searchEditorUrl = $searchEditorUrl; - $this->setConfig($config); - - $this->createForms(); - } - - protected function createForms(): void - { - $config = $this->getConfig(); - $addFilter = (new AddFilterForm()) - ->on(Form::ON_SENT, function () { - $this->config['showSearchbar'] = true; - - $this->emit(self::ON_CHANGE, [$this]); - }); - - $escalations = $config['rule_escalation'] ?? [1 => ['id' => $this->generateFakeEscalationId()]]; - - if (! isset($this->config['rule_escalation'])) { - $this->config['rule_escalation'] = $escalations; - } - - $addEscalation = (new AddEscalationForm()) - ->on(AddEscalationForm::ON_SENT, function () use ($escalations) { - $newPosition = (int) array_key_last($escalations) + 1; - $this->config['rule_escalation'][$newPosition] = ['id' => $this->generateFakeEscalationId()]; - if ($this->config['conditionPlusButtonPosition'] === null) { - $this->config['conditionPlusButtonPosition'] = $newPosition; - } - - $this->removeEscalationForms[$newPosition] = $this->createRemoveEscalationForm($newPosition); - - if ($newPosition === 2) { - $this->removeEscalationForms[1] = $this->createRemoveEscalationForm(1); - $this->forms[] = $this->removeEscalationForms[1]; - } - - $this->escalationForms[$newPosition] = [ - $this->createConditionForm($newPosition), - $this->createRecipientForm($newPosition) - ]; - - $this->emit(self::ON_CHANGE, [$this]); - }); - - $this->forms = [ - $addFilter, - $addEscalation - ]; - - foreach ($escalations as $position => $escalation) { - /** @var int $position */ - $values = explode('|', $escalation['condition'] ?? ''); - $escalationCondition = $this->createConditionForm($position, $values); - - $values = $escalation['recipient'] ?? []; - $escalationRecipient = $this->createRecipientForm($position, $values); - - $this->escalationForms[$position] = [ - $escalationCondition, - $escalationRecipient - ]; - - $this->forms[] = $escalationCondition; - $this->forms[] = $escalationRecipient; - - if (count($escalations) > 1) { - $removeEscalation = $this->createRemoveEscalationForm($position); - - $this->forms[] = $removeEscalation; - $this->removeEscalationForms[$position] = $removeEscalation; - } - } - } - - /** - * Create and return the SearchEditor - * - * @return SearchEditor - * - * @throws ProgrammingError - */ - public static function createSearchEditor(): SearchEditor - { - $editor = new SearchEditor(); - - $editor->setAction(Url::fromRequest()->getAbsoluteUrl()); - - $editor->setSuggestionUrl(Url::fromPath( - "notifications/event-rule/complete", - ['_disableLayout' => true, 'showCompact' => true, 'id' => Url::fromRequest()->getParams()->get('id')] - )); - - return $editor; - } - - public static function createFilterString($filters): ?string - { - foreach ($filters as $filter) { - if ($filter instanceof Filter\Chain) { - self::createFilterString($filter); - } elseif (empty($filter->getValue())) { - $filter->setValue(true); - } - } - - if ($filters instanceof Filter\Condition && empty($filters->getValue())) { - $filters->setValue(true); - } - - $filterStr = QueryString::render($filters); - - return ! empty($filterStr) ? $filterStr : null; - } - - public function getForms(): array - { - return $this->forms; - } - - protected function assemble() - { - [$addFilter, $addEscalation] = $this->forms; - - $addFilterButtonOrSearchBar = $addFilter; - $horizontalLine = (new FlowLine())->getHorizontalLine(); - if (! empty($this->config['showSearchbar'])) { - $editorOpener = new Link( - new Icon('cog'), - $this->searchEditorUrl, - Attributes::create([ - 'class' => 'search-editor-opener control-button', - 'title' => t('Adjust Filter'), - 'data-icinga-modal' => true, - 'data-no-icinga-ajax' => true, - ]) - ); - - $searchBar = new TextElement( - 'searchbar', - [ - 'class' => 'filter-input control-button', - 'readonly' => true, - 'value' => isset($this->config['object_filter']) - ? rawurldecode($this->config['object_filter']) - : null - ] - ); - - $addFilterButtonOrSearchBar = Html::tag('div', ['class' => 'search-controls icinga-controls']); - $addFilterButtonOrSearchBar->add([$searchBar, $editorOpener]); - } else { - $horizontalLine->getAttributes() - ->add(['class' => 'horizontal-line-long']); - } - - $this->add([ - (new FlowLine())->getRightArrow(), - $addFilterButtonOrSearchBar, - $horizontalLine - ]); - - $escalations = new Escalations(); - - foreach ($this->escalationForms as $position => $escalation) { - if (isset($this->removeEscalationForms[$position])) { - $escalations->addEscalation($position, $escalation, $this->removeEscalationForms[$position]); - } else { - $escalations->addEscalation($position, $escalation); - } - } - - $escalationswithAdd = Html::tag('div', ['class' => 'escalations-with-add-form']); - - $escalationswithAdd->add([ - $escalations, - $addEscalation - ]); - - $this->add($escalationswithAdd); - } - - public function getConfig(): ?array - { - return $this->config; - } - - public function setConfig($config): self - { - $this->config = $config; - - return $this; - } - - public function isValid(): bool - { - foreach ($this->escalationForms as $escalation) { - [$conditionForm, $recipientForm] = $escalation; - - if (! $conditionForm->isValid() || ! $recipientForm->isValid()) { - return false; - } - } - - return true; - } - - private function createConditionForm(int $position, array $values = []): EscalationConditionForm - { - $cnt = empty(array_filter($values)) ? null : count($values); - - if (! array_key_exists('conditionPlusButtonPosition', $this->config)) { - //the default position of add condition button - $pos = null; - foreach ($this->config['rule_escalation'] as $p => $v) { - if (empty($v['condition'])) { - $pos = $p; - break; - } - } - - $this->config['conditionPlusButtonPosition'] = $pos; - } - - if ($cnt === null && $this->config['conditionPlusButtonPosition'] !== $position) { - $cnt = 1; - } - - $form = (new EscalationConditionForm($cnt)) - ->addAttributes(['name' => 'escalation-condition-form-' . $position]) - ->deleteRemoveButton($this->config['conditionPlusButtonPosition'] !== null) - ->on(Form::ON_SENT, function ($form) use ($position) { - $values = $form->getValues(); - if ( - $form->isAddButtonPressed() - && $this->config['conditionPlusButtonPosition'] === $position - && empty($this->config['rule_escalation'][$position]['condition']) - ) { - $this->config['conditionPlusButtonPosition'] = null; - } - if (empty($values)) { - $this->config['conditionPlusButtonPosition'] = $position; - } - - $this->config['rule_escalation'][$position]['condition'] = $values; - - $this->emit(self::ON_CHANGE, [$this]); - }); - - if ($cnt !== null) { - $form->populate($values); - } else { - $form->addAttributes(['class' => 'count-zero-escalation-condition-form']); - } - - return $form; - } - - private function createRecipientForm(int $position, array $values = []): EscalationRecipientForm - { - $cnt = empty(array_filter($values)) ? null : count($values); - $form = (new EscalationRecipientForm($cnt)) - ->addAttributes(['name' => 'escalation-recipient-form-' . $position]) - ->on(Form::ON_SENT, function ($form) use ($position) { - $this->config['rule_escalation'][$position]['recipient'] = $form->getValues(); - - $this->emit(self::ON_CHANGE, [$this]); - }); - - if ($cnt !== null) { - $form->populate($values); - } - - return $form; - } - - private function createRemoveEscalationForm(int $position): RemoveEscalationForm - { - $escalationId = $this->config['rule_escalation'][$position]['id']; - - $incident = Incident::on(Database::get()) - ->with('rule_escalation'); - - $disableRemoveButton = false; - if (is_int($escalationId)) { - $incident->filter(Filter::equal('rule_escalation.id', $escalationId)); - if ($incident->count() > 0) { - $disableRemoveButton = true; - } - } - - - $form = (new RemoveEscalationForm()) - ->addAttributes(['name' => 'remove-escalation-form-' . $escalationId]) - ->setRemoveButtonDisabled($disableRemoveButton) - ->on(Form::ON_SENT, function ($form) use ($position) { - unset($this->config['rule_escalation'][$position]); - unset($this->escalationForms[$position]); - unset($this->removeEscalationForms[$position]); - - if ($this->config['conditionPlusButtonPosition'] === $position) { - $this->config['conditionPlusButtonPosition'] = null; - } elseif ($this->config['conditionPlusButtonPosition'] > $position) { - $this->config['conditionPlusButtonPosition'] -= 1; - } - - if (! empty($this->config['rule_escalation'])) { - $this->config['rule_escalation'] = array_combine( - range( - 1, - count($this->config['rule_escalation']) - ), - array_values($this->config['rule_escalation']) - ); - } - - if (! empty($this->removeEscalationForms)) { - /** @var array $removeEscalationForms */ - $removeEscalationForms = array_combine( - range( - 1, - count($this->removeEscalationForms) - ), - array_values($this->removeEscalationForms) - ); - $this->removeEscalationForms = $removeEscalationForms; - } - - if (! empty($this->escalationForms)) { - /** @var array> $escalationForms */ - $escalationForms = array_combine( - range( - 1, - count($this->escalationForms) - ), - array_values($this->escalationForms) - ); - $this->escalationForms = $escalationForms; - } - - $numEscalation = count($this->escalationForms); - if ($numEscalation === 1) { - unset($this->removeEscalationForms[1]); - } - - $this->emit(self::ON_CHANGE, [$this]); - }); - - return $form; - } - - private function generateFakeEscalationId(): string - { - return bin2hex(random_bytes(4)); - } -}