diff --git a/CHANGELOG.md b/CHANGELOG.md index fbba0e9..55b61ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,10 +13,10 @@ before starting to add changes. Use example [placed in the end of the page](#exa ## [Unreleased] -- Moved digital signature configuration (which attachment to sign and the - signature validation text position) from the *OS2Forms Attachment* element - onto the *Digital Signature* webform handler. Includes an automatic - migration update hook for existing webforms. +- [PR-353](https://github.com/OS2Forms/os2forms/pull/353) + - Moved `WebformInheritTask` data inheriting from + `hook_webform_submission_form_alter` to `hook_entity_prepare_form`. + - Set data on the submission. ## [5.1.0] 2026-06-03 diff --git a/build_release.sh b/build_release.sh index 0ae94a1..8975f06 100755 --- a/build_release.sh +++ b/build_release.sh @@ -27,6 +27,10 @@ git merge --no-ff origin/feature/move-digital-signature-configuration-to-handler git checkout --theirs CHANGELOG.md git add CHANGELOG.md git commit -m "Merge remote-tracking branch 'origin/feature/move-digital-signature-configuration-to-handler' into selvbetjening.aarhuskommune.dk" +git merge --no-ff origin/feature/maestro-inherit-data-on-prepare-form +git checkout --theirs CHANGELOG.md +git add CHANGELOG.md +git commit -m "Merge remote-tracking branch 'origin/feature/maestro-inherit-data-on-prepare-form' into selvbetjening.aarhuskommune.dk" docker run --rm --volume .:/app itkdev/php8.4-fpm:latest sed --in-place '1i This is a hack so the CHANGELOG is messed up. \nGenerated by build_release.sh' CHANGELOG.md diff --git a/modules/os2forms_forloeb/os2forms_forloeb.module b/modules/os2forms_forloeb/os2forms_forloeb.module index 4636ec3..cbdd09e 100644 --- a/modules/os2forms_forloeb/os2forms_forloeb.module +++ b/modules/os2forms_forloeb/os2forms_forloeb.module @@ -5,6 +5,7 @@ * Install, update and uninstall functions for the os2forms_forloeb. */ +use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\maestro\Engine\MaestroEngine; use Drupal\os2forms_forloeb\MaestroHelper; @@ -12,6 +13,7 @@ use Drupal\os2forms_forloeb\Plugin\EngineTasks\MaestroWebformInheritTask; use Drupal\user\Entity\User; use Drupal\webform\Entity\WebformSubmission; use Drupal\webform\WebformInterface; +use Drupal\webform\WebformSubmissionInterface; /** * Implements hook_maestro_interactive_handlers(). @@ -293,10 +295,16 @@ function os2forms_forloeb_preprocess_page(&$variables) { } /** - * Implements hook_webform_submission_form_alter(). + * Implements hook_entity_prepare_form(). + * + * Uses the generic hook rather than hook_webform_submission_prepare_form() + * because core invokes the generic hook first, and the inherited data should + * be set early (@see \Drupal\Core\Entity\EntityForm::init() for details). */ -function os2forms_forloeb_webform_submission_form_alter(array &$form, FormStateInterface $formState, string $formId) { - MaestroWebformInheritTask::webformSubmissionFormAlter($form, $formState, $formId); +function os2forms_forloeb_entity_prepare_form(EntityInterface $entity, string $operation, FormStateInterface $formState) { + if ($entity instanceof WebformSubmissionInterface) { + MaestroWebformInheritTask::webformSubmissionPrepareForm($entity, $operation, $formState); + } } /** diff --git a/modules/os2forms_forloeb/src/Plugin/EngineTasks/MaestroWebformInheritTask.php b/modules/os2forms_forloeb/src/Plugin/EngineTasks/MaestroWebformInheritTask.php index dd25f1c..ea7de0d 100644 --- a/modules/os2forms_forloeb/src/Plugin/EngineTasks/MaestroWebformInheritTask.php +++ b/modules/os2forms_forloeb/src/Plugin/EngineTasks/MaestroWebformInheritTask.php @@ -2,13 +2,12 @@ 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; +use Drupal\webform\WebformSubmissionInterface; /** * Maestro Webform Task Plugin for Multiple Submissions. @@ -141,44 +140,62 @@ public function prepareTaskForSave(array &$form, FormStateInterface $form_state, } /** - * Implements hook_webform_submission_form_alter(). + * Implements hook_entity_prepare_form() for webform submissions. + * + * Sets inherited data on the webform submission entity. + * + * @see \Drupal\webform\WebformSubmissionForm::populateElements() */ - public static function webformSubmissionFormAlter(array &$form, FormStateInterface $formState, string $formId) { - // Only inherit values on the initial form load. This skip condition is the - // complement of webform's own prepopulate guard. - // @see \Drupal\webform\WebformSubmissionForm::buildForm() - if ($formState->isRebuilding() && !$formState->get('is_ajax_restart')) { - return; + public static function webformSubmissionPrepareForm(WebformSubmissionInterface $submission, string $operation, FormStateInterface $formState): void { + if ($source = self::getInheritedSourceSubmission()) { + $webform = $submission->getWebform(); + + // Only inherit values for elements on the target form. + $inheritedData = array_filter( + $source->getData(), + static fn (string $key) => NULL !== $webform->getElement($key), + ARRAY_FILTER_USE_KEY + ); + + if ($inheritedData) { + $submission->setData($inheritedData + $submission->getData()); + } } + } - // @todo Clean up and align with MaestroHelper::maestroZeroUserNotification(). - if ($queueID = self::getQueueIdFromRequest()) { - $templateTask = MaestroEngine::getTemplateTaskByQueueID($queueID); - if (self::isWebformTask($templateTask)) { - if ($inheritWebformUniqueId = ($templateTask['data'][self::INHERIT_WEBFORM_UNIQUE_ID] ?? NULL)) { - $processID = MaestroEngine::getProcessIdFromQueueId($queueID); - $entityIdentifier = MaestroEngine::getAllEntityIdentifiersForProcess($processID)[$inheritWebformUniqueId] ?? NULL; - if ('webform_submission' === ($entityIdentifier['entity_type'] ?? NULL)) { - $submission = WebformSubmission::load($entityIdentifier['entity_id']); - $data = $submission->getData(); - - // 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; - } - } - } - } - } - } - } + /** + * Get the webform submission that the current request's task inherits from. + * + * Resolves the Maestro queue ID from the current request and, if the + * corresponding template task is a webform task configured to inherit + * another task's submission, loads that submission. + * + * @todo Align with MaestroHelper::maestroZeroUserNotification(), which + * resolves the process submission in a similar way. + */ + public static function getInheritedSourceSubmission(): ?WebformSubmissionInterface { + $queueID = self::getQueueIdFromRequest(); + if (NULL === $queueID) { + return NULL; + } + + $templateTask = MaestroEngine::getTemplateTaskByQueueID($queueID); + if (!self::isWebformTask($templateTask)) { + return NULL; + } + + $inheritWebformUniqueId = $templateTask['data'][self::INHERIT_WEBFORM_UNIQUE_ID] ?? NULL; + if (!$inheritWebformUniqueId) { + return NULL; + } + + $processID = MaestroEngine::getProcessIdFromQueueId($queueID); + $entityIdentifier = MaestroEngine::getAllEntityIdentifiersForProcess($processID)[$inheritWebformUniqueId] ?? NULL; + if ('webform_submission' !== ($entityIdentifier['entity_type'] ?? NULL)) { + return NULL; } + + return WebformSubmission::load($entityIdentifier['entity_id']); } /**