Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,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-326](https://github.com/OS2Forms/os2forms/pull/326)
Updating ckeditor -> ckeditor5.
- [PR-322](https://github.com/OS2Forms/os2forms/pull/322)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
use Drupal\Core\Form\FormStateInterface;
use Drupal\webform\Twig\WebformTwigExtension;
use Drupal\webform\Utility\WebformElementHelper;
use Drupal\os2forms_attachment\Os2formsAttachmentPrintBuilder;
use Drupal\webform_attachment\Plugin\WebformElement\WebformAttachmentBase;

/**
Expand All @@ -28,8 +27,6 @@ protected function defineDefaultProperties() {
'view_mode' => 'html',
'template' => '',
'export_type' => '',
'digital_signature' => '',
'digital_signature_position' => Os2formsAttachmentPrintBuilder::SIGNATURE_POSITION_AFTER_CONTENT,
'exclude_empty' => '',
'exclude_empty_checkbox' => '',
'excluded_elements' => '',
Expand Down Expand Up @@ -91,28 +88,6 @@ public function form(array $form, FormStateInterface $form_state) {
'html' => $this->t('HTML'),
],
];
$form['attachment']['digital_signature'] = [
'#type' => 'checkbox',
'#title' => $this->t('Digital signature'),
];
$form['attachment']['digital_signature_position'] = [
'#type' => 'select',
'#title' => $this->t('Digital signature position'),
'#description' => $this->t('Select where the digital signature validation text should be placed in the PDF document.'),
'#options' => [
Os2formsAttachmentPrintBuilder::SIGNATURE_POSITION_FOOTER => $this->t('Footer (repeats on every page)'),
Os2formsAttachmentPrintBuilder::SIGNATURE_POSITION_HEADER => $this->t('Header (repeats on every page)'),
Os2formsAttachmentPrintBuilder::SIGNATURE_POSITION_AFTER_CONTENT => $this->t('After content (end of document)'),
Os2formsAttachmentPrintBuilder::SIGNATURE_POSITION_BEFORE_CONTENT => $this->t('Before content (start of document)'),
],
'#default_value' => Os2formsAttachmentPrintBuilder::SIGNATURE_POSITION_AFTER_CONTENT,
'#states' => [
'visible' => [
':input[name="properties[digital_signature]"]' => ['checked' => TRUE],
],
],
];

// Set #access so that help is always visible.
WebformElementHelper::setPropertyRecursive($form['attachment']['help'], '#access', TRUE);

Expand Down
14 changes: 11 additions & 3 deletions modules/os2forms_digital_signature/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,20 @@ The signature server consists of two parts. A frontend module

### Activating Digital Signature

1. Add the OS2forms attachment element to the form.
2. Indicate that the OS2Forms attachment requires a digital signature.
3. Add the Digital Signature Handler to the webform.
1. Add an attachment-style element to the form (either *OS2Forms Attachment* — generated PDF — or
*OS2forms digital signature document* — uploaded PDF).
2. Add the **Digital Signature** handler to the webform.
3. In the handler configuration, pick the attachment element to sign from the **Attachment element to sign**
dropdown, and choose where the signature validation text should be placed in the generated PDF
(the position only applies to *OS2Forms Attachment* elements; it is ignored for uploaded PDFs).
4. If the form requires an email handler, ensure the trigger is set to **...when submission is locked** in the handler’s
*Additional settings*.

> [!NOTE]
> Prior to this release, the attachment element exposed `Digital signature` and `Digital signature position` properties
> directly. These settings have moved to the handler. Existing forms are migrated automatically by
> `os2forms_digital_signature_update_10001()`.

### Flow Explained

1. Upon form submission, a PDF is generated, saved in the private directory, and sent to the signature service via URL.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ package: 'OS2Forms'
core_version_requirement: ^9 || ^10
dependencies:
- 'webform:webform'
- 'os2forms:os2forms_attachment'

configure: os2forms_digital_signature.settings
114 changes: 114 additions & 0 deletions modules/os2forms_digital_signature/os2forms_digital_signature.install
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
<?php

/**
* @file
* Install, update and uninstall for the os2forms_digital_signature module.
*/

use Drupal\os2forms_attachment\Os2formsAttachmentPrintBuilder;
use Drupal\webform\Entity\Webform;

/**
* Migrate per-element digital signature config onto the handler.
*
* Previously the os2forms_attachment element exposed #digital_signature and
* #digital_signature_position properties. Both now live on the
* os2forms_digital_signature handler. This update walks every webform that
* has the handler enabled, lifts the values off the element into the handler
* config, and strips the element properties.
*/
function os2forms_digital_signature_update_10001(&$sandbox) {
$logger = \Drupal::logger('os2forms_digital_signature');
$migrated = 0;
$skipped = [];

/** @var \Drupal\webform\WebformInterface[] $webforms */
$webforms = Webform::loadMultiple();
foreach ($webforms as $webform) {
$handlers = $webform->getHandlers();
$signatureHandler = NULL;
foreach ($handlers as $handler) {
if ($handler->getPluginId() === 'os2forms_digital_signature') {
$signatureHandler = $handler;
break;
}
}
if (!$signatureHandler) {
continue;
}

$elements = $webform->getElementsDecodedAndFlattened();
$signedKey = NULL;
$signedPosition = NULL;
$multiple = [];
foreach ($elements as $key => $element) {
if (!empty($element['#digital_signature'])) {
if ($signedKey === NULL) {
$signedKey = $key;
$signedPosition = $element['#digital_signature_position']
?? Os2formsAttachmentPrintBuilder::SIGNATURE_POSITION_AFTER_CONTENT;
}
else {
$multiple[] = $key;
}
}
}

if ($signedKey === NULL) {
$skipped[$webform->id()] = 'no element had #digital_signature set';
continue;
}

if ($multiple) {
$logger->warning('Webform @id has multiple elements flagged for signing (@all); migrating @chosen and ignoring the rest.', [
'@id' => $webform->id(),
'@all' => implode(', ', array_merge([$signedKey], $multiple)),
'@chosen' => $signedKey,
]);
}

// Write the new config onto the handler.
$config = $signatureHandler->getConfiguration();
$config['settings']['attachment_element'] = $signedKey;
$config['settings']['signature_position'] = $signedPosition;
$signatureHandler->setConfiguration($config);

// Strip the legacy properties from every element.
$rawElements = $webform->getElementsDecoded();
_os2forms_digital_signature_strip_legacy_props($rawElements);
$webform->setElements($rawElements);

$webform->save();
$migrated++;
}

if ($skipped) {
foreach ($skipped as $id => $reason) {
$logger->warning('Skipped webform @id during digital signature config migration: @reason. Configure the handler manually.', [
'@id' => $id,
'@reason' => $reason,
]);
}
}

return t('Migrated digital signature config on @count webform(s).', ['@count' => $migrated]);
}

/**
* Recursively remove legacy digital signature element properties.
*
* @param array $elements
* The decoded elements tree, modified in place.
*/
function _os2forms_digital_signature_strip_legacy_props(array &$elements) {
foreach ($elements as $key => &$value) {
if (!is_array($value)) {
continue;
}
if (str_starts_with((string) $key, '#')) {
continue;
}
unset($value['#digital_signature'], $value['#digital_signature_position']);
_os2forms_digital_signature_strip_legacy_props($value);
}
}
Loading
Loading