diff --git a/CHANGELOG.md b/CHANGELOG.md index 9bf72d67..f4af33ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,17 @@ before starting to add changes. Use example [placed in the end of the page](#exa ## [Unreleased] +## [3.13.3] 2023-12-05 + +- [#76](https://github.com/OS2Forms/os2forms/pull/76) + Fixed digital post logging on submissions. +- [#74](https://github.com/OS2Forms/os2forms/pull/74) + Allow composite elements in Maestro notification recipient +- [#73](https://github.com/OS2Forms/os2forms/pull/73a) + Fix issue with nested elements in webform inherit +- [#77](https://github.com/OS2Forms/os2forms/pull/77) + Fix color picker fields in os2forms_webform_maps + ## [3.13.2] 2023-10-19 - Fixing CPR fetch pattern @@ -179,7 +190,28 @@ before starting to add changes. Use example [placed in the end of the page](#exa - Security in case of vulnerabilities. ``` -[Unreleased]: https://github.com/OS2Forms/os2forms/compare/3.5.0...HEAD -[3.5.0]: https://github.com/OS2Forms/os2forms/compare/3.2.5...3.5.0 +[Unreleased]: https://github.com/OS2Forms/os2forms/compare/3.13.3...HEAD +[3.13.3]: https://github.com/OS2Forms/os2forms/compare/3.13.2...3.13.3 +[3.13.2]: https://github.com/OS2Forms/os2forms/compare/3.13.1...3.13.2 +[3.13.1]: https://github.com/OS2Forms/os2forms/compare/3.13.0...3.13.1 +[3.13.0]: https://github.com/OS2Forms/os2forms/compare/3.12.2...3.13.0 +[3.12.2]: https://github.com/OS2Forms/os2forms/compare/3.12.1...3.12.2 +[3.12.1]: https://github.com/OS2Forms/os2forms/compare/3.12.0...3.12.1 +[3.12.0]: https://github.com/OS2Forms/os2forms/compare/3.11.0...3.12.0 +[3.11.0]: https://github.com/OS2Forms/os2forms/compare/3.10.0...3.11.0 +[3.10.0]: https://github.com/OS2Forms/os2forms/compare/3.9.0...3.10.0 +[3.9.0]: https://github.com/OS2Forms/os2forms/compare/3.8.3...3.9.0 +[3.8.3]: https://github.com/OS2Forms/os2forms/compare/3.8.2...3.8.3 +[3.8.2]: https://github.com/OS2Forms/os2forms/compare/3.8.1...3.8.2 +[3.8.1]: https://github.com/OS2Forms/os2forms/compare/3.8.0...3.8.1 +[3.8.0]: https://github.com/OS2Forms/os2forms/compare/3.7.0...3.8.0 +[3.7.0]: https://github.com/OS2Forms/os2forms/compare/3.6.0...3.7.0 +[3.6.0]: https://github.com/OS2Forms/os2forms/compare/3.5.0...3.6.0 +[3.5.0]: https://github.com/OS2Forms/os2forms/compare/3.4.0...3.5.0 +[3.4.0]: https://github.com/OS2Forms/os2forms/compare/3.3.0...3.4.0 +[3.3.0]: https://github.com/OS2Forms/os2forms/compare/3.2.9...3.3.0 +[3.2.9]: https://github.com/OS2Forms/os2forms/compare/3.2.8...3.2.9 +[3.2.8]: https://github.com/OS2Forms/os2forms/compare/3.2.7...3.2.8 +[3.2.7]: https://github.com/OS2Forms/os2forms/compare/3.2.6...3.2.7 [3.2.6]: https://github.com/OS2Forms/os2forms/compare/3.2.5...3.2.6 [3.2.5]: https://github.com/OS2Forms/os2forms/compare/3.2.4...3.2.5 diff --git a/modules/os2forms_digital_post/os2forms_digital_post.services.yml b/modules/os2forms_digital_post/os2forms_digital_post.services.yml index e4930534..a40d88a4 100644 --- a/modules/os2forms_digital_post/os2forms_digital_post.services.yml +++ b/modules/os2forms_digital_post/os2forms_digital_post.services.yml @@ -5,7 +5,7 @@ services: logger.channel.os2forms_digital_post_submission: parent: logger.channel_base - arguments: [ 'os2forms_digital_post_submission' ] + arguments: [ 'webform_submission' ] Drupal\os2forms_digital_post\Helper\Settings: arguments: diff --git a/modules/os2forms_digital_post/src/Helper/WebformHelperSF1601.php b/modules/os2forms_digital_post/src/Helper/WebformHelperSF1601.php index fd8a0815..4fb86767 100644 --- a/modules/os2forms_digital_post/src/Helper/WebformHelperSF1601.php +++ b/modules/os2forms_digital_post/src/Helper/WebformHelperSF1601.php @@ -217,6 +217,7 @@ public function log($level, $message, array $context = []): void { */ public function createJob(WebformSubmissionInterface $webformSubmission, array $handlerConfiguration): ?Job { $context = [ + 'handler_id' => 'os2forms_digital_post', 'webform_submission' => $webformSubmission, ]; @@ -230,7 +231,6 @@ public function createJob(WebformSubmissionInterface $webformSubmission, array $ $queue->enqueueJob($job); $context['@queue'] = $queue->id(); $this->notice('Job for sending digital post add to the queue @queue.', $context + [ - 'handler_id' => 'os2forms_digital_post', 'operation' => 'digital post queued for sending', ]); @@ -238,7 +238,6 @@ public function createJob(WebformSubmissionInterface $webformSubmission, array $ } catch (\Exception $exception) { $this->error('Error creating job for sending digital post.', $context + [ - 'handler_id' => 'os2forms_digital_post', 'operation' => 'digital post failed', ]); return NULL; @@ -253,6 +252,10 @@ public function createJob(WebformSubmissionInterface $webformSubmission, array $ public function processJob(Job $job): JobResult { $payload = $job->getPayload(); + $context = [ + 'handler_id' => 'os2forms_digital_post', + 'operation' => 'digital post send', + ]; try { $submissionId = $payload['submissionId']; $submission = $this->loadSubmission($submissionId); @@ -267,21 +270,16 @@ public function processJob(Job $job): JobResult { $message)); } + $context['webform_submission'] = $submission; $this->sendDigitalPost($submission, $payload['handlerConfiguration']); - $this->notice('Digital post sent', [ - 'handler_id' => 'os2forms_digital_post', - 'operation' => 'digital post send', - 'webform_submission' => $submission, - ]); + $this->notice('Digital post sent', $context); return JobResult::success(); } catch (\Exception $e) { - $this->error('Error: @message', [ + $this->error('Error: @message', $context + [ '@message' => $e->getMessage(), - 'handler_id' => 'os2forms_digital_post', - 'operation' => 'digital post send', ]); return JobResult::failure($e->getMessage()); diff --git a/modules/os2forms_forloeb/src/MaestroHelper.php b/modules/os2forms_forloeb/src/MaestroHelper.php index ce0b5fbb..dfa65cae 100644 --- a/modules/os2forms_forloeb/src/MaestroHelper.php +++ b/modules/os2forms_forloeb/src/MaestroHelper.php @@ -8,6 +8,7 @@ use Drupal\advancedqueue\Job; use Drupal\advancedqueue\JobResult; use Drupal\Component\Render\MarkupInterface; +use Drupal\Component\Utility\NestedArray; use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Config\ImmutableConfig; use Drupal\Core\Entity\EntityStorageInterface; @@ -466,6 +467,17 @@ public function renderNotification(WebformSubmissionInterface $submission, strin ?? $data[$recipientElement] ?? NULL; + // Handle composite elements. + if ($recipient === NULL) { + // Composite subelement keys consist of + // the composite element key and the subelement key separated by '__', + // e.g. 'contact__name'. + if (str_contains($recipientElement, '__')) { + $keys = explode('__', $recipientElement); + $recipient = NestedArray::getValue($data, $keys); + } + } + if ($notificationType === self::NOTIFICATION_ESCALATION) { $recipient = $settings[MaestroNotificationHandler::NOTIFICATION][$notificationType][MaestroNotificationHandler::NOTIFICATION_RECIPIENT] ?? NULL; } diff --git a/modules/os2forms_forloeb/src/Plugin/EngineTasks/MaestroWebformInheritTask.php b/modules/os2forms_forloeb/src/Plugin/EngineTasks/MaestroWebformInheritTask.php index b04137ce..8bd0040e 100644 --- a/modules/os2forms_forloeb/src/Plugin/EngineTasks/MaestroWebformInheritTask.php +++ b/modules/os2forms_forloeb/src/Plugin/EngineTasks/MaestroWebformInheritTask.php @@ -2,9 +2,11 @@ namespace Drupal\os2forms_forloeb\Plugin\EngineTasks; +use Drupal\Component\Utility\NestedArray; use Drupal\Core\Form\FormStateInterface; use Drupal\maestro\Engine\MaestroEngine; use Drupal\maestro_webform\Plugin\EngineTasks\MaestroWebformTask; +use Drupal\webform\Entity\Webform; use Drupal\webform\Entity\WebformSubmission; use Drupal\webform\Utility\WebformArrayHelper; @@ -152,9 +154,18 @@ public static function webformSubmissionFormAlter(array &$form, FormStateInterfa if ('webform_submission' === ($entityIdentifier['entity_type'] ?? NULL)) { $submission = WebformSubmission::load($entityIdentifier['entity_id']); $data = $submission->getData(); - foreach ($data as $key => $value) { - if (isset($form['elements'][$key])) { - $form['elements'][$key]['#default_value'] = $value; + + // The target element may be hidden inside sections or field groups + // on the target form. Therefore, we need to load that form and get + // element information to properly set default element values nested + // inside the form. + if ($targetWebform = Webform::load($form['#webform_id'] ?? NULL)) { + foreach ($data as $key => $value) { + if ($targetElement = $targetWebform->getElement($key)) { + if ($element = &NestedArray::getValue($form['elements'], $targetElement['#webform_parents'])) { + $element['#default_value'] = $value; + } + } } } } diff --git a/modules/os2forms_forloeb/src/Plugin/WebformHandler/MaestroNotificationHandler.php b/modules/os2forms_forloeb/src/Plugin/WebformHandler/MaestroNotificationHandler.php index d0afc201..02c7f943 100644 --- a/modules/os2forms_forloeb/src/Plugin/WebformHandler/MaestroNotificationHandler.php +++ b/modules/os2forms_forloeb/src/Plugin/WebformHandler/MaestroNotificationHandler.php @@ -99,7 +99,7 @@ public function buildConfigurationForm(array $form, FormStateInterface $formStat '#title' => $this->t('Notification'), ]; - $availableElements = $this->getRecipientElements(); + $availableElements = $this->getRecipientElementOptions(); $form[self::NOTIFICATION][static::RECIPIENT_ELEMENT] = [ '#type' => 'select', '#title' => $this->t('Element that contains the recipient identifier (email, CPR or CVR) of the notification'), @@ -228,7 +228,7 @@ public function validateConfigurationForm(array &$form, FormStateInterface $form /** * Get recipient elements. */ - private function getRecipientElements(): array { + private function getRecipientElementOptions(): array { $elements = $this->getWebform()->getElementsDecodedAndFlattened(); $elementTypes = [ @@ -240,16 +240,60 @@ private function getRecipientElements(): array { 'cvr_value_element', 'os2forms_person_lookup', ]; + + $isAllowedElement = static fn ($e) => in_array($e['#type'], $elementTypes, TRUE); + + // Expand composite elements, NOT custom composite elements. + foreach ($elements as $key => $element) { + $formElement = $this->getWebform()->getElement($key); + + if ('webform_custom_composite' === $formElement['#type']) { + continue; + } + + if (isset($formElement['#webform_composite_elements'])) { + foreach ($formElement['#webform_composite_elements'] as $compositeElement) { + // If composite element is not accessible ignore it. + if (!($compositeElement['#access'] ?? TRUE)) { + continue; + } + + if ($isAllowedElement($compositeElement)) { + // Group composite subelements. + $elements[$element['#title']][$compositeElement['#webform_composite_key']] = [ + '#title' => $compositeElement['#title'], + ]; + + $elements[$element['#title']]['#is_composite'] = TRUE; + } + } + } + } + $elements = array_filter( $elements, - static function (array $element) use ($elementTypes) { - return in_array($element['#type'], $elementTypes, TRUE); - } + static fn (array $element) => $isAllowedElement($element) + // Composite elements are already filtered, + // i.e. they do not need to be filtered here. + || ($element['#is_composite'] ?? FALSE) ); - return array_map(static function (array $element) { - return $element['#title']; - }, $elements); + // Get titles of remaining elements. + return array_map( + static function (array $element) { + if ($element['#is_composite'] ?? FALSE) { + + return array_map( + static fn (array $compositeElement) => $compositeElement['#title'], + // Consider only elements with a title, + // i.e. the subelements we added earlier. + array_filter($element, static fn ($e) => isset($e['#title']))); + } + + return $element['#title']; + }, + $elements + ); } /** diff --git a/modules/os2forms_webform_maps/src/Plugin/WebformElement/WebformLeafletMapField.php b/modules/os2forms_webform_maps/src/Plugin/WebformElement/WebformLeafletMapField.php index 290b1a64..d6a5afea 100644 --- a/modules/os2forms_webform_maps/src/Plugin/WebformElement/WebformLeafletMapField.php +++ b/modules/os2forms_webform_maps/src/Plugin/WebformElement/WebformLeafletMapField.php @@ -190,7 +190,7 @@ public function form(array $form, FormStateInterface $form_state) { ], ], 'polyline_color' => [ - '#type' => 'input_color', + '#type' => 'textfield', '#title' => 'Color', '#description' => $this->t('Enter value as HEX or CSS color'), ], @@ -199,7 +199,7 @@ public function form(array $form, FormStateInterface $form_state) { '#title' => 'Prevent Intersection', ], 'polyline_error_color' => [ - '#type' => 'input_color', + '#type' => 'textfield', '#title' => 'Error color', '#description' => $this->t('Enter value as HEX or CSS color'), '#states' => [ @@ -233,7 +233,7 @@ public function form(array $form, FormStateInterface $form_state) { ], ], 'rectangle_color' => [ - '#type' => 'input_color', + '#type' => 'textfield', '#title' => 'Color', '#description' => $this->t('Enter value as HEX or CSS color'), ], @@ -253,7 +253,7 @@ public function form(array $form, FormStateInterface $form_state) { ], ], 'polygon_color' => [ - '#type' => 'input_color', + '#type' => 'textfield', '#title' => 'Color', '#description' => $this->t('Enter value as HEX or CSS color'), ], @@ -262,7 +262,7 @@ public function form(array $form, FormStateInterface $form_state) { '#title' => 'Prevent Intersection', ], 'polygon_error_color' => [ - '#type' => 'input_color', + '#type' => 'textfield', '#title' => 'Error color', '#states' => [ 'invisible' => [ @@ -296,7 +296,7 @@ public function form(array $form, FormStateInterface $form_state) { ], ], 'circle_color' => [ - '#type' => 'input_color', + '#type' => 'textfield', '#title' => 'Color', '#description' => $this->t('Enter value as HEX or CSS color'), ], diff --git a/src/Form/SettingsForm.php b/src/Form/SettingsForm.php index efb88219..41b2645a 100644 --- a/src/Form/SettingsForm.php +++ b/src/Form/SettingsForm.php @@ -85,6 +85,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) { } $this->messenger()->addStatus($this->t('The configuration options have been saved.')); + } }