diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1ddc05ab..512994da 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]
+- [PR-315](https://github.com/OS2Forms/os2forms/pull/315)
+ Added “Display on“ options to Map element
+- [PR-333](https://github.com/OS2Forms/os2forms/pull/333)
+ Added the ability to configure on which submission states handlers should run.
+ The default option is to run on the completed state. Changes was made to the
+ following handlers:
+ - Digital post
+ - Fasit
+ - FBS
+ - Digital signature
+
## [5.1.0] 2026-06-03
- [PR-326](https://github.com/OS2Forms/os2forms/pull/326)
diff --git a/modules/os2forms_digital_post/os2forms_digital_post.install b/modules/os2forms_digital_post/os2forms_digital_post.install
index 48768e21..cb410b1d 100644
--- a/modules/os2forms_digital_post/os2forms_digital_post.install
+++ b/modules/os2forms_digital_post/os2forms_digital_post.install
@@ -6,6 +6,7 @@
*/
use Drupal\os2forms_digital_post\Helper\BeskedfordelerHelper;
+use Drupal\webform\WebformSubmissionInterface;
/**
* Implements hook_schema().
@@ -26,3 +27,34 @@ function os2forms_digital_post_update_9001(): void {
'os2web_key',
], TRUE);
}
+
+/**
+ * Set states config to completed on existing digital post handlers.
+ */
+function os2forms_digital_post_update_10001(): void {
+ // To avoid having to load full webforms we load and update webform configs.
+ $configFactory = \Drupal::configFactory();
+
+ foreach ($configFactory->listAll('webform.webform.') as $name) {
+ $config = $configFactory->getEditable($name);
+ $handlers = $config->get('handlers');
+ if (!is_array($handlers)) {
+ continue;
+ }
+
+ $changed = FALSE;
+
+ foreach ($handlers as $handlerKey => $handler) {
+ // $handler['id'] is the handler plugin id.
+ if (($handler['id'] ?? NULL) !== 'digital_post_sf1601') {
+ continue;
+ }
+ $handlers[$handlerKey]['settings']['additional']['states'] = [WebformSubmissionInterface::STATE_COMPLETED];
+ $changed = TRUE;
+ }
+
+ if ($changed) {
+ $config->set('handlers', $handlers)->save();
+ }
+ }
+}
diff --git a/modules/os2forms_digital_post/src/Plugin/WebformHandler/WebformHandlerSF1601.php b/modules/os2forms_digital_post/src/Plugin/WebformHandler/WebformHandlerSF1601.php
index 6f0e06a9..ae633c01 100644
--- a/modules/os2forms_digital_post/src/Plugin/WebformHandler/WebformHandlerSF1601.php
+++ b/modules/os2forms_digital_post/src/Plugin/WebformHandler/WebformHandlerSF1601.php
@@ -32,6 +32,8 @@ final class WebformHandlerSF1601 extends WebformHandlerBase {
public const RECIPIENT_ELEMENT = 'recipient_element';
public const ATTACHMENT_ELEMENT = 'attachment_element';
public const SENDER_ADDRESS = 'sender_address';
+ private const string ADDITIONAL = 'additional';
+ private const string STATES = 'states';
/**
* Maximum length of sender label.
@@ -76,6 +78,9 @@ public static function create(ContainerInterface $container, array $configuratio
public function defaultConfiguration() {
return [
'debug' => FALSE,
+ self::ADDITIONAL => [
+ self::STATES => [WebformSubmissionInterface::STATE_COMPLETED],
+ ],
];
}
@@ -203,6 +208,31 @@ public function buildConfigurationForm(array $form, FormStateInterface $formStat
'#default_value' => $this->configuration['debug'] ?? NULL,
];
+ // Additional.
+ // Lifted from EmailWebformHandler::buildConfigurationForm().
+ $resultsDisabled = (bool) $this->getWebform()->getSetting('results_disabled');
+ $form[self::ADDITIONAL] = [
+ '#type' => 'fieldset',
+ '#title' => $this->t('Additional settings'),
+ ];
+ // Settings: States.
+ $states = (array) ($this->configuration[self::ADDITIONAL][self::STATES] ?? NULL);
+ $form[self::ADDITIONAL][self::STATES] = [
+ '#type' => 'checkboxes',
+ '#title' => $this->t('Run handler when …'),
+ '#options' => [
+ WebformSubmissionInterface::STATE_DRAFT_CREATED => $this->t('draft is created.'),
+ WebformSubmissionInterface::STATE_DRAFT_UPDATED => $this->t('draft is updated.'),
+ WebformSubmissionInterface::STATE_CONVERTED => $this->t('anonymous submission is converted to authenticated.'),
+ WebformSubmissionInterface::STATE_COMPLETED => $this->t('submission is completed.'),
+ WebformSubmissionInterface::STATE_UPDATED => $this->t('submission is updated.'),
+ WebformSubmissionInterface::STATE_DELETED => $this->t('submission is deleted.'),
+ WebformSubmissionInterface::STATE_LOCKED => $this->t('submission is locked.'),
+ ],
+ '#access' => !$resultsDisabled,
+ '#default_value' => $resultsDisabled ? [WebformSubmissionInterface::STATE_COMPLETED] : $states,
+ ];
+
return $this->setSettingsParents($form);
}
@@ -333,6 +363,11 @@ static function (array $action) {
$this->configuration[self::MEMO_ACTIONS] = $actions;
$this->configuration['debug'] = (bool) $formState->getValue('debug');
+
+ $additional = $formState->getValue(self::ADDITIONAL);
+ // Clean up states.
+ $additional[self::STATES] = array_values(array_filter($additional[self::STATES]));
+ $this->configuration[self::ADDITIONAL] = $additional;
}
/**
@@ -341,6 +376,12 @@ static function (array $action) {
* @phpstan-return void
*/
public function postSave(WebformSubmissionInterface $webformSubmission, $update = TRUE) {
+ $submissionState = $webformSubmission->getWebform()->getSetting('results_disabled') ? WebformSubmissionInterface::STATE_COMPLETED : $webformSubmission->getState();
+ $enabledStates = (array) ($this->configuration[self::ADDITIONAL][self::STATES] ?? NULL);
+ if (!in_array($submissionState, $enabledStates)) {
+ return;
+ }
+
$this->helper->createJob($webformSubmission, $this->configuration);
}
diff --git a/modules/os2forms_digital_signature/os2forms_digital_signature.install b/modules/os2forms_digital_signature/os2forms_digital_signature.install
new file mode 100644
index 00000000..4e5cb76a
--- /dev/null
+++ b/modules/os2forms_digital_signature/os2forms_digital_signature.install
@@ -0,0 +1,39 @@
+listAll('webform.webform.') as $name) {
+ $config = $configFactory->getEditable($name);
+ $handlers = $config->get('handlers');
+ if (!is_array($handlers)) {
+ continue;
+ }
+
+ $changed = FALSE;
+
+ foreach ($handlers as $handlerKey => $handler) {
+ // $handler['id'] is the handler plugin id.
+ if (($handler['id'] ?? NULL) !== 'os2forms_digital_signature') {
+ continue;
+ }
+ $handlers[$handlerKey]['settings']['additional']['states'] = [WebformSubmissionInterface::STATE_COMPLETED];
+ $changed = TRUE;
+ }
+
+ if ($changed) {
+ $config->set('handlers', $handlers)->save();
+ }
+ }
+}
diff --git a/modules/os2forms_digital_signature/src/Plugin/WebformHandler/DigitalSignatureWebformHandler.php b/modules/os2forms_digital_signature/src/Plugin/WebformHandler/DigitalSignatureWebformHandler.php
index 9a616bfc..78252c00 100644
--- a/modules/os2forms_digital_signature/src/Plugin/WebformHandler/DigitalSignatureWebformHandler.php
+++ b/modules/os2forms_digital_signature/src/Plugin/WebformHandler/DigitalSignatureWebformHandler.php
@@ -7,6 +7,7 @@
use Drupal\Core\File\FileExists;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\File\FileUrlGeneratorInterface;
+use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Site\Settings;
use Drupal\Core\Url;
use Drupal\file\FileRepositoryInterface;
@@ -88,6 +89,9 @@ class DigitalSignatureWebformHandler extends WebformHandlerBase {
*/
private readonly Settings $settings;
+ private const string ADDITIONAL = 'additional';
+ private const string STATES = 'states';
+
/**
* {@inheritdoc}
*/
@@ -107,14 +111,78 @@ public static function create(ContainerInterface $container, array $configuratio
/**
* {@inheritdoc}
+ *
+ * @phpstan-return array
*/
- public function preSave(WebformSubmissionInterface $webform_submission) {
- $webform = $webform_submission->getWebform();
+ public function defaultConfiguration() {
+ return [
+ self::ADDITIONAL => [
+ self::STATES => [WebformSubmissionInterface::STATE_COMPLETED],
+ ],
+ ];
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @phpstan-param array $form
+ * @phpstan-return array
+ */
+ public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
+ // Additional.
+ // Lifted from EmailWebformHandler::buildConfigurationForm().
+ $resultsDisabled = (bool) $this->getWebform()->getSetting('results_disabled');
+ $form[self::ADDITIONAL] = [
+ '#type' => 'fieldset',
+ '#title' => $this->t('Additional settings'),
+ ];
+ // Settings: States.
+ $states = (array) ($this->configuration[self::ADDITIONAL][self::STATES] ?? NULL);
+ $form[self::ADDITIONAL][self::STATES] = [
+ '#type' => 'checkboxes',
+ '#title' => $this->t('Run handler when …'),
+ '#options' => [
+ WebformSubmissionInterface::STATE_DRAFT_CREATED => $this->t('draft is created.'),
+ WebformSubmissionInterface::STATE_DRAFT_UPDATED => $this->t('draft is updated.'),
+ WebformSubmissionInterface::STATE_CONVERTED => $this->t('anonymous submission is converted to authenticated.'),
+ WebformSubmissionInterface::STATE_COMPLETED => $this->t('submission is completed.'),
+ WebformSubmissionInterface::STATE_UPDATED => $this->t('submission is updated.'),
+ WebformSubmissionInterface::STATE_DELETED => $this->t('submission is deleted.'),
+ // The digital signature logic locks after the first signing. Resigning
+ // does not make sense, so 'locked' is not an option here.
+ ],
+ '#access' => !$resultsDisabled,
+ '#default_value' => $resultsDisabled ? [WebformSubmissionInterface::STATE_COMPLETED] : $states,
+ ];
+
+ return $this->setSettingsParents($form);
+ }
- if ($webform_submission->isLocked()) {
+ /**
+ * {@inheritdoc}
+ *
+ * @phpstan-param array $form
+ * @phpstan-return void
+ */
+ public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
+ $additional = $form_state->getValue(self::ADDITIONAL);
+ // Clean up states.
+ $additional[self::STATES] = array_values(array_filter($additional[self::STATES]));
+ $this->configuration[self::ADDITIONAL] = $additional;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function preSave(WebformSubmissionInterface $webform_submission) {
+ $submissionState = $webform_submission->getWebform()->getSetting('results_disabled') ? WebformSubmissionInterface::STATE_COMPLETED : $webform_submission->getState();
+ $enabledStates = (array) ($this->configuration[self::ADDITIONAL][self::STATES] ?? NULL);
+ if (!in_array($submissionState, $enabledStates)) {
return;
}
+ $webform = $webform_submission->getWebform();
+
$attachment = $this->getSubmissionAttachment($webform_submission);
if (!$attachment) {
$this->logger->error('Attachment cannot be created webform: %webform, webform_submission: %webform_submission',
diff --git a/modules/os2forms_fasit/os2forms_fasit.install b/modules/os2forms_fasit/os2forms_fasit.install
index f862bafb..8d471f49 100644
--- a/modules/os2forms_fasit/os2forms_fasit.install
+++ b/modules/os2forms_fasit/os2forms_fasit.install
@@ -5,6 +5,8 @@
* Install hooks for os2forms_fasit.
*/
+use Drupal\webform\WebformSubmissionInterface;
+
/**
* Install Key module.
*/
@@ -13,3 +15,34 @@ function os2forms_fasit_update_9001(): void {
'key',
], TRUE);
}
+
+/**
+ * Set states config to completed on existing fasit handlers.
+ */
+function os2forms_fasit_update_10001(): void {
+ // To avoid having to load full webforms we load and update webform configs.
+ $configFactory = \Drupal::configFactory();
+
+ foreach ($configFactory->listAll('webform.webform.') as $name) {
+ $config = $configFactory->getEditable($name);
+ $handlers = $config->get('handlers');
+ if (!is_array($handlers)) {
+ continue;
+ }
+
+ $changed = FALSE;
+
+ foreach ($handlers as $handlerKey => $handler) {
+ // $handler['id'] is the handler plugin id.
+ if (($handler['id'] ?? NULL) !== 'os2forms_fasit') {
+ continue;
+ }
+ $handlers[$handlerKey]['settings']['additional']['states'] = [WebformSubmissionInterface::STATE_COMPLETED];
+ $changed = TRUE;
+ }
+
+ if ($changed) {
+ $config->set('handlers', $handlers)->save();
+ }
+ }
+}
diff --git a/modules/os2forms_fasit/src/Plugin/WebformHandler/FasitWebformHandler.php b/modules/os2forms_fasit/src/Plugin/WebformHandler/FasitWebformHandler.php
index 84eef379..e726bf44 100644
--- a/modules/os2forms_fasit/src/Plugin/WebformHandler/FasitWebformHandler.php
+++ b/modules/os2forms_fasit/src/Plugin/WebformHandler/FasitWebformHandler.php
@@ -35,6 +35,8 @@ class FasitWebformHandler extends WebformHandlerBase {
public const FASIT_HANDLER_DOCUMENT_DESCRIPTION = 'document_description';
public const FASIT_HANDLER_CPR_ELEMENT = 'cpr_element';
public const FASIT_HANDLER_ATTACHMENT_ELEMENT = 'attachment_element';
+ private const string ADDITIONAL = 'additional';
+ private const string STATES = 'states';
/**
* The submission logger.
@@ -79,6 +81,19 @@ public static function create(ContainerInterface $container, array $configuratio
);
}
+ /**
+ * {@inheritdoc}
+ *
+ * @phpstan-return array
+ */
+ public function defaultConfiguration() {
+ return [
+ self::ADDITIONAL => [
+ self::STATES => [WebformSubmissionInterface::STATE_COMPLETED],
+ ],
+ ];
+ }
+
/**
* {@inheritdoc}
*
@@ -129,6 +144,31 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
'#size' => 5,
];
+ // Additional.
+ // Lifted from EmailWebformHandler::buildConfigurationForm().
+ $resultsDisabled = (bool) $this->getWebform()->getSetting('results_disabled');
+ $form[self::ADDITIONAL] = [
+ '#type' => 'fieldset',
+ '#title' => $this->t('Additional settings'),
+ ];
+ // Settings: States.
+ $states = (array) ($this->configuration[self::ADDITIONAL][self::STATES] ?? NULL);
+ $form[self::ADDITIONAL][self::STATES] = [
+ '#type' => 'checkboxes',
+ '#title' => $this->t('Run handler when …'),
+ '#options' => [
+ WebformSubmissionInterface::STATE_DRAFT_CREATED => $this->t('draft is created.'),
+ WebformSubmissionInterface::STATE_DRAFT_UPDATED => $this->t('draft is updated.'),
+ WebformSubmissionInterface::STATE_CONVERTED => $this->t('anonymous submission is converted to authenticated.'),
+ WebformSubmissionInterface::STATE_COMPLETED => $this->t('submission is completed.'),
+ WebformSubmissionInterface::STATE_UPDATED => $this->t('submission is updated.'),
+ WebformSubmissionInterface::STATE_DELETED => $this->t('submission is deleted.'),
+ WebformSubmissionInterface::STATE_LOCKED => $this->t('submission is locked.'),
+ ],
+ '#access' => !$resultsDisabled,
+ '#default_value' => $resultsDisabled ? [WebformSubmissionInterface::STATE_COMPLETED] : $states,
+ ];
+
return $this->setSettingsParents($form);
}
@@ -143,12 +183,23 @@ public function submitConfigurationForm(array &$form, FormStateInterface $form_s
$this->configuration[self::FASIT_HANDLER_GENERAL][self::FASIT_HANDLER_DOCUMENT_DESCRIPTION] = $form_state->getValue(self::FASIT_HANDLER_GENERAL)[self::FASIT_HANDLER_DOCUMENT_DESCRIPTION];
$this->configuration[self::FASIT_HANDLER_GENERAL][self::FASIT_HANDLER_CPR_ELEMENT] = $form_state->getValue(self::FASIT_HANDLER_GENERAL)[self::FASIT_HANDLER_CPR_ELEMENT];
$this->configuration[self::FASIT_HANDLER_GENERAL][self::FASIT_HANDLER_ATTACHMENT_ELEMENT] = $form_state->getValue(self::FASIT_HANDLER_GENERAL)[self::FASIT_HANDLER_ATTACHMENT_ELEMENT];
+
+ $additional = $form_state->getValue(self::ADDITIONAL);
+ // Clean up states.
+ $additional[self::STATES] = array_values(array_filter($additional[self::STATES]));
+ $this->configuration[self::ADDITIONAL] = $additional;
}
/**
* {@inheritdoc}
*/
public function postSave(WebformSubmissionInterface $webform_submission, $update = TRUE): void {
+ $submissionState = $webform_submission->getWebform()->getSetting('results_disabled') ? WebformSubmissionInterface::STATE_COMPLETED : $webform_submission->getState();
+ $enabledStates = (array) ($this->configuration[self::ADDITIONAL][self::STATES] ?? NULL);
+ if (!in_array($submissionState, $enabledStates)) {
+ return;
+ }
+
$queueStorage = $this->entityTypeManager->getStorage('advancedqueue_queue');
/** @var \Drupal\advancedqueue\Entity\Queue $queue */
$queue = $queueStorage->load('fasit_queue');
diff --git a/modules/os2forms_fbs_handler/os2forms_fbs_handler.install b/modules/os2forms_fbs_handler/os2forms_fbs_handler.install
new file mode 100644
index 00000000..4fa0422f
--- /dev/null
+++ b/modules/os2forms_fbs_handler/os2forms_fbs_handler.install
@@ -0,0 +1,39 @@
+listAll('webform.webform.') as $name) {
+ $config = $configFactory->getEditable($name);
+ $handlers = $config->get('handlers');
+ if (!is_array($handlers)) {
+ continue;
+ }
+
+ $changed = FALSE;
+
+ foreach ($handlers as $handlerKey => $handler) {
+ // $handler['id'] is the handler plugin id.
+ if (($handler['id'] ?? NULL) !== 'os2forms_fbs') {
+ continue;
+ }
+ $handlers[$handlerKey]['settings']['additional']['states'] = [WebformSubmissionInterface::STATE_COMPLETED];
+ $changed = TRUE;
+ }
+
+ if ($changed) {
+ $config->set('handlers', $handlers)->save();
+ }
+ }
+}
diff --git a/modules/os2forms_fbs_handler/src/Plugin/WebformHandler/FbsWebformHandler.php b/modules/os2forms_fbs_handler/src/Plugin/WebformHandler/FbsWebformHandler.php
index aa1ae330..33c479c5 100644
--- a/modules/os2forms_fbs_handler/src/Plugin/WebformHandler/FbsWebformHandler.php
+++ b/modules/os2forms_fbs_handler/src/Plugin/WebformHandler/FbsWebformHandler.php
@@ -42,6 +42,8 @@ final class FbsWebformHandler extends WebformHandlerBase {
* The queue id.
*/
private const QUEUE_ID = 'os2forms_fbs_handler';
+ private const string ADDITIONAL = 'additional';
+ private const string STATES = 'states';
/**
* Constructs an FbsWebformHandler object.
@@ -89,6 +91,19 @@ public static function create(ContainerInterface $container, array $configuratio
);
}
+ /**
+ * {@inheritdoc}
+ *
+ * @phpstan-return array
+ */
+ public function defaultConfiguration() {
+ return [
+ self::ADDITIONAL => [
+ self::STATES => [WebformSubmissionInterface::STATE_COMPLETED],
+ ],
+ ];
+ }
+
/**
* {@inheritdoc}
*
@@ -146,6 +161,31 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
'#default_value' => $this->configuration['password'] ?? '',
];
+ // Additional.
+ // Lifted from EmailWebformHandler::buildConfigurationForm().
+ $resultsDisabled = (bool) $this->getWebform()->getSetting('results_disabled');
+ $form[self::ADDITIONAL] = [
+ '#type' => 'fieldset',
+ '#title' => $this->t('Additional settings'),
+ ];
+ // Settings: States.
+ $states = (array) ($this->configuration[self::ADDITIONAL][self::STATES] ?? NULL);
+ $form[self::ADDITIONAL][self::STATES] = [
+ '#type' => 'checkboxes',
+ '#title' => $this->t('Run handler when …'),
+ '#options' => [
+ WebformSubmissionInterface::STATE_DRAFT_CREATED => $this->t('draft is created.'),
+ WebformSubmissionInterface::STATE_DRAFT_UPDATED => $this->t('draft is updated.'),
+ WebformSubmissionInterface::STATE_CONVERTED => $this->t('anonymous submission is converted to authenticated.'),
+ WebformSubmissionInterface::STATE_COMPLETED => $this->t('submission is completed.'),
+ WebformSubmissionInterface::STATE_UPDATED => $this->t('submission is updated.'),
+ WebformSubmissionInterface::STATE_DELETED => $this->t('submission is deleted.'),
+ WebformSubmissionInterface::STATE_LOCKED => $this->t('submission is locked.'),
+ ],
+ '#access' => !$resultsDisabled,
+ '#default_value' => $resultsDisabled ? [WebformSubmissionInterface::STATE_COMPLETED] : $states,
+ ];
+
return $this->setSettingsParents($form);
}
@@ -164,12 +204,23 @@ public function submitConfigurationForm(array &$form, FormStateInterface $form_s
->getValue(['wrapper', 'username']);
$this->configuration['password'] = $form_state
->getValue(['wrapper', 'password']);
+
+ $additional = $form_state->getValue(self::ADDITIONAL);
+ // Clean up states.
+ $additional[self::STATES] = array_values(array_filter($additional[self::STATES]));
+ $this->configuration[self::ADDITIONAL] = $additional;
}
/**
* {@inheritdoc}
*/
public function postSave(WebformSubmissionInterface $webform_submission, $update = TRUE): void {
+ $submissionState = $webform_submission->getWebform()->getSetting('results_disabled') ? WebformSubmissionInterface::STATE_COMPLETED : $webform_submission->getState();
+ $enabledStates = (array) ($this->configuration[self::ADDITIONAL][self::STATES] ?? NULL);
+ if (!in_array($submissionState, $enabledStates)) {
+ return;
+ }
+
$logger_context = [
'handler_id' => 'os2forms_fbs',
'channel' => 'webform_submission',
diff --git a/modules/os2forms_webform_maps/README.md b/modules/os2forms_webform_maps/README.md
index c36b901e..d93aa5d4 100644
--- a/modules/os2forms_webform_maps/README.md
+++ b/modules/os2forms_webform_maps/README.md
@@ -14,3 +14,58 @@ the map. The data can be exported to PDF.
## Installation
The module can be installed using the standard Drupal installation procedure.
+
+## Fetching GeoJSON using the API
+
+Assume that we have a webform with ID `my_webform` and the webform has a Map element with ID `my_map`. We can then fetch
+the data for a submission with UUID `c34d01c5-7bd9-4b15-8b01-5787959453c0` on the webform with a HTTP `GET` request (cf.
+[OS2Forms REST API](https://github.com/OS2Forms/os2forms_rest_api/blob/main/README.md)):
+
+``` shell name=api-fetch-submission-data
+curl --silent --location --header 'api-key: my-api-key' http://127.0.0.1:8000/webform_rest/my_webform/submission/c34d01c5-7bd9-4b15-8b01-5787959453c0
+# {"entity":{"serial":[{"value":1}],"sid":[{"value":2}],"uuid":[{"value":"c34d01c5-7bd9-4b15-8b01-5787959453c0"}],…```
+```
+
+The result, however, contains a lot of data and we need a little more work the extract just the GeoJSON data.
+
+Using [`jq`](https://jqlang.org/) (or similar tools), we can drill down into the full submission data to extract just
+the GeoJSON data from the Map element (JSON decoding twice along the way):
+
+``` shell name=api-extract-map-element-data
+curl --silent --location --header 'api-key: my-api-key' http://127.0.0.1:8000/webform_rest/my_webform/submission/c34d01c5-7bd9-4b15-8b01-5787959453c0 | jq '.data.my_map | fromjson | .geojson | fromjson'
+```
+
+The final result will be something like
+
+``` json
+{
+ "type": "FeatureCollection",
+ "features": [
+ {
+ "type": "Feature",
+ "properties": {},
+ "geometry": {
+ "type": "LineString",
+ "coordinates": [
+ [
+ 10.193674,
+ 56.158929
+ ],
+ [
+ 10.241758,
+ 56.155296
+ ],
+ [
+ 10.242788,
+ 56.130048
+ ],
+ [
+ 10.189209,
+ 56.129283
+ ]
+ ]
+ }
+ }
+ ]
+}
+```
diff --git a/modules/os2forms_webform_maps/os2forms_webform_maps.module b/modules/os2forms_webform_maps/os2forms_webform_maps.module
index af545a5d..17d33aab 100644
--- a/modules/os2forms_webform_maps/os2forms_webform_maps.module
+++ b/modules/os2forms_webform_maps/os2forms_webform_maps.module
@@ -5,22 +5,6 @@
* Module file for os2forms_webform_maps.
*/
-/**
- * Implements hook_theme().
- */
-function os2forms_webform_maps_theme() {
- return [
- 'webform_element_base_html__webform_map_field' => [
- 'variables' => [
- 'element' => [],
- 'value' => NULL,
- 'webform_submission' => NULL,
- 'options' => [],
- ],
- ],
- ];
-}
-
/**
* Implements hook_locale_translation_projects_alter().
*/
@@ -29,31 +13,3 @@ function os2forms_webform_maps_locale_translation_projects_alter(&$projects) {
$path = $module_handler->getModule('os2forms_webform_maps')->getPath();
$projects['os2forms_webform_maps']['info']['interface translation server pattern'] = $path . '/translations/%language.po';
}
-
-/**
- * Implements hook_preprocess_webform_element_base_html__webform_map_field().
- */
-function os2forms_webform_maps_preprocess_webform_element_base_html__webform_map_field(array &$variables) {
- // Decode the plain text value once.
- $decoded_value = json_decode($variables['value']['#plain_text']);
-
- // Use the decoded geojson property.
- $variables['value']['#plain_text'] = $decoded_value->geojson;
-
- // Load the webform element base HTML template.
- \Drupal::moduleHandler()->loadInclude('webform', 'inc', 'includes/webform.theme.template');
- template_preprocess_webform_element_base_html($variables);
-
- // Generate a unique ID for the map image.
- $map_image_id = 'map-image-' . $variables['element']['#webform_key'];
-
- $variables['map_image'] = [
- '#type' => 'html_tag',
- '#tag' => 'img',
- '#attributes' => [
- 'class' => ['handler-help-message'],
- 'id' => [$map_image_id],
- 'src' => $decoded_value->image ?? '',
- ],
- ];
-}
diff --git a/modules/os2forms_webform_maps/src/Plugin/WebformElement/WebformLeafletMapField.php b/modules/os2forms_webform_maps/src/Plugin/WebformElement/WebformLeafletMapField.php
index 3b6aa405..00327dcf 100644
--- a/modules/os2forms_webform_maps/src/Plugin/WebformElement/WebformLeafletMapField.php
+++ b/modules/os2forms_webform_maps/src/Plugin/WebformElement/WebformLeafletMapField.php
@@ -5,6 +5,7 @@
use Drupal\Core\Form\FormStateInterface;
use Drupal\leaflet\LeafletSettingsElementsTrait;
use Drupal\webform\Plugin\WebformElementBase;
+use Drupal\webform\WebformSubmissionInterface;
/**
* Provides a 'webform_map_field' element.
@@ -70,6 +71,9 @@ public function defineDefaultProperties(): array {
'circle_color' => '#3388FF',
'rectangle_color' => '#3388FF',
+ // Display settings.
+ 'display_image_on' => ['email', 'html', 'pdf'],
+ 'display_geojson_on' => ['text', 'html'],
] + parent::defineDefaultProperties();
}
@@ -344,7 +348,120 @@ public function form(array $form, FormStateInterface $form_state) {
],
];
+ $form['display_settings'] = [
+ '#type' => 'fieldset',
+ '#title' => $this->t('Display settings'),
+ ];
+ $form['display_settings']['display_settings_container'] = [
+ 'display_image_on' => [
+ '#type' => 'checkboxes',
+ '#title' => $this->t('Display image on'),
+ '#options' => [
+ 'email' => $this->t('Email'),
+ 'html' => $this->t('HTML'),
+ 'pdf' => $this->t('PDF'),
+ ],
+ ],
+
+ 'display_geojson_on' => [
+ '#type' => 'checkboxes',
+ '#title' => $this->t('Display GeoJSON on'),
+ '#options' => [
+ 'email' => $this->t('Email'),
+ 'html' => $this->t('HTML'),
+ 'pdf' => $this->t('PDF'),
+ 'text' => $this->t('Text'),
+ ],
+ ],
+ ];
+
return $form;
}
+ /**
+ * {@inheritdoc}
+ */
+ protected function formatHtmlItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []): array {
+ $value = $this->getMapValue($element, $webform_submission, $options);
+
+ $imageId = 'map-image-' . $this->getKey($element);
+
+ $build = [];
+
+ $viewMode = $options['view_mode'] ?? 'results';
+ if ('table' === $viewMode) {
+ $viewMode = 'html';
+ }
+ elseif ($options['email'] ?? FALSE) {
+ $viewMode = 'email';
+ }
+ elseif ($options['pdf'] ?? FALSE) {
+ $viewMode = 'pdf';
+ }
+
+ // @todo Is this (i.e. $element['#display_image_on']) really the way to get element configuration?
+ $showImageOn = array_filter((array) ($element['#display_image_on'] ?? NULL));
+ $includeImage = isset($showImageOn[$viewMode]);
+
+ $showGeoJsonOn = array_filter((array) ($element['#display_geojson_on'] ?? NULL));
+ $includeGeoJson = isset($showGeoJsonOn[$viewMode]);
+
+ if ($includeImage) {
+ $build['image'] = [
+ '#type' => 'html_tag',
+ '#tag' => 'img',
+ '#attributes' => [
+ 'class' => ['handler-help-message'],
+ 'id' => $imageId,
+ 'src' => $value['image'],
+ ],
+ '#prefix' => '',
+ '#suffix' => '
',
+ ];
+ }
+
+ if ($includeGeoJson) {
+ $build['geojson'] = [
+ '#markup' => $value['geojson'],
+ '#prefix' => '',
+ '#suffix' => '
',
+ ];
+ }
+
+ return $build;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function formatTextItem(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
+ $value = $this->getMapValue($element, $webform_submission, $options);
+
+ return $value['geojson'];
+ }
+
+ /**
+ * Get structured map value.
+ *
+ * @return array{
+ * image: string,
+ * geojson: string
+ * }
+ */
+ private function getMapValue(array $element, WebformSubmissionInterface $webform_submission, array $options = []): array {
+ $value = $this->getValue($element, $webform_submission, $options);
+
+ try {
+ $data = json_decode($value, associative: TRUE, flags: JSON_THROW_ON_ERROR);
+ }
+ catch (\JsonException) {
+ $data = [];
+ }
+
+ return $data + [
+ 'image' => '',
+ 'geojson' => 'null',
+ ];
+ }
+
}
diff --git a/modules/os2forms_webform_maps/templates/webform-element-base-html--webform-map-field.html.twig b/modules/os2forms_webform_maps/templates/webform-element-base-html--webform-map-field.html.twig
deleted file mode 100644
index cd3a19bd..00000000
--- a/modules/os2forms_webform_maps/templates/webform-element-base-html--webform-map-field.html.twig
+++ /dev/null
@@ -1,18 +0,0 @@
-{#
-/**
- * @file
- * Default theme implementation for a webform base element as html.
- *
- * Available variables:
- * - element: The element.
- * - title: The label for the element.
- * - value: The content for the element.
- * - item: The form item used to display the element.
- * - options Associative array of options for element.
- * - multiline: Flag to determine if value spans multiple lines.
- * - email: Flag to determine if element is for an email.
- */
-#}
- {{ map_image }}
- {{ item }}
-