Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
0d8224a
288: Add address element to generated html during digital post
jekuaitk Feb 6, 2026
ba26c19
288: Updated CHANGELOG
jekuaitk Feb 6, 2026
e0815dc
288: Added comment to preg_replace
jekuaitk Feb 10, 2026
1fca0a2
288: Ensured required fields are set before accessing them
jekuaitk Feb 10, 2026
d25ba3e
288: Switched to h-card and saving lookup result in session
jekuaitk Feb 10, 2026
cfdd08f
288: Updated README with injected html and example styling
jekuaitk Feb 10, 2026
e3a719a
288: Cleaned up example styling
jekuaitk Feb 10, 2026
fdaafd5
Update modules/os2forms_digital_post/src/EventSubscriber/Os2formsDigi…
jekuaitk Feb 16, 2026
a552beb
Update modules/os2forms_digital_post/README.md
jekuaitk Feb 16, 2026
7ed8d8f
Update modules/os2forms_digital_post/README.md
jekuaitk Feb 16, 2026
0c39739
Update modules/os2forms_digital_post/src/EventSubscriber/Os2formsDigi…
jekuaitk Feb 16, 2026
a6e6f1f
Added missing comma in address
jekuaitk Feb 19, 2026
7c057aa
Updated README
jekuaitk Feb 19, 2026
a99952c
Cleanup
jekuaitk Feb 23, 2026
eeba74b
Ensure address is added to both digital post pdf and fjernprint pdf
jekuaitk Mar 9, 2026
5fdc5d4
Adjusted when context is set and removed
jekuaitk Mar 12, 2026
ed4c707
Added option to add sender address to digital post
jekuaitk Mar 13, 2026
8fbeeaa
Updated README with styling of sender adress
jekuaitk Mar 13, 2026
381f438
Added max length for sender and checks for context being correctly set
jekuaitk Mar 16, 2026
ee98943
Update modules/os2forms_digital_post/src/EventSubscriber/Os2formsDigi…
jekuaitk Mar 16, 2026
5a644a1
Update modules/os2forms_digital_post/src/Plugin/WebformHandler/Webfor…
jekuaitk Mar 16, 2026
4335ee3
Updated digital post README with sender address
jekuaitk Mar 16, 2026
e0794f6
Updated CHANGELOG
jekuaitk Mar 23, 2026
fc3d2c4
Merge pull request #13 from itk-dev/feature/sender-address-in-digital…
jekuaitk Mar 23, 2026
a4fce86
Merge branch 'develop' into feature/address-in-digital-post-pdfs
jekuaitk Mar 23, 2026
e7c58e5
Updated Digital Post README
jekuaitk Mar 23, 2026
d8bc9f5
Merge branch 'develop' into feature/address-in-digital-post-pdfs
jekuaitk Mar 23, 2026
54d9950
Added missing array return declaration
jekuaitk Mar 23, 2026
579d11e
Applied coding standards
jekuaitk Mar 23, 2026
ec1fe42
Merge branch 'develop' into feature/address-in-digital-post-pdfs
jekuaitk Mar 27, 2026
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]

- [PR-301](https://github.com/OS2Forms/os2forms/pull/301)
Add address information to Digital Post shipments to ensure "*fjernprint*"
can be sent.

## [5.0.0] 2025-11-18

- [PR-192](https://github.com/OS2Forms/os2forms/pull/192)
Expand Down
19 changes: 19 additions & 0 deletions modules/os2forms_digital_post/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,22 @@ of recipients:
``` shell
drush os2forms-digital-post:test:send --help
```

## Fjernprint (physical digital post)

To comply with the address placement in the envelope window (kuvert-rude) an
[event subscriber](src/EventSubscriber/Os2formsDigitalPostSubscriber.php) is
used to inject an address information element into generated HTML before it is
Comment thread
jekuaitk marked this conversation as resolved.
Outdated
converted to a PDF.

We are only guaranteed to have the necessary information when in a digital
post context. For that reason, the injection of address information is only
done when in a digital post context. Note also that the information is only
injected – it is not styled. This allows flexibility across installations but
also means that it is up to individual installations to style it correctly.
Comment thread
jekuaitk marked this conversation as resolved.
This should be done in OS2Forms Attachment-templates, see
[Overwriting templates](https://github.com/OS2Forms/os2forms/tree/develop/modules/os2forms_attachment#overwriting-templates).

To see the exact requirements for address placement, see
[digst_a4_farve_ej_til_kant_demo_ny_rudeplacering.pdf](docs/digst_a4_farve_ej_til_kant_demo_ny_rudeplacering.pdf).

Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ services:
- "@logger.channel.os2forms_digital_post"
- "@logger.channel.os2forms_digital_post_submission"
- "@Drupal\\os2forms_digital_post\\Helper\\DigitalPostHelper"
- "@Drupal\\os2forms_digital_post\\EventSubscriber\\Os2formsDigitalPostSubscriber"

Drupal\os2forms_digital_post\Helper\SF1461Helper:

Expand All @@ -69,3 +70,9 @@ services:
- '@database'
- '@Drupal\os2forms_digital_post\Helper\MeMoHelper'
- '@logger.channel.os2forms_digital_post'

Drupal\os2forms_digital_post\EventSubscriber\Os2formsDigitalPostSubscriber:
arguments:
- '@request_stack'
tags:
- { name: 'event_subscriber' }
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<?php

namespace Drupal\os2forms_digital_post\EventSubscriber;

use Drupal\entity_print\Event\PrintEvents;
use Drupal\entity_print\Event\PrintHtmlAlterEvent;
use Drupal\webform\WebformSubmissionInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RequestStack;

/**
* Used to alter the generated PDF to align with digital post requirements.
*/
final class Os2formsDigitalPostSubscriber implements EventSubscriberInterface {

public function __construct(private readonly RequestStack $requestStack) {
Comment thread
jekuaitk marked this conversation as resolved.
Outdated
}

/**
* Post render entity_print event.
*
* Injects an envelope-window element containing address information.
*/
public function onPrintRender(PrintHtmlAlterEvent $event): void {
$html = &$event->getHtml();

// Only modify HTML if there is exactly one submission.
if (count($event->getEntities()) === 1) {
$submission = $event->getEntities()[0];
if ($submission instanceof WebformSubmissionInterface) {
// Check whether generation is for digital post.
if ($digitalPostContext = $this->getDigitalPostContext($submission)) {

$name = $digitalPostContext['name'];
$address = $digitalPostContext['address'];
$zipAndCity = $digitalPostContext['zipAndCity'];
Comment thread
jekuaitk marked this conversation as resolved.
Outdated

$addressHtml = <<<HTML
<div class="envelope-window" id="envelope-window-digital-post">
<div class="envelope-window-recipient-section" id="envelope-window-recipient-section-digital-post">
Comment thread
jekuaitk marked this conversation as resolved.
Outdated
Comment thread
jekuaitk marked this conversation as resolved.
Outdated
$name</br>
$address</br>
$zipAndCity
Comment thread
jekuaitk marked this conversation as resolved.
Outdated
Comment thread
jekuaitk marked this conversation as resolved.
Outdated
</div>
</div>
HTML;
$html = preg_replace('@<body[^>]*>@', '${0}' . $addressHtml, $html);
Comment thread
jekuaitk marked this conversation as resolved.
$this->deleteDigitalPostContext($submission);
}
}
}

}

/**
* {@inheritdoc}
*/
public static function getSubscribedEvents(): array {
return [
PrintEvents::POST_RENDER => ['onPrintRender'],
];
}

/**
* Indicate Digital Post context in the current request.
*/
public function setDigitalPostContext(WebformSubmissionInterface $submission, array $digitalPostContext): void {

Check failure on line 67 in modules/os2forms_digital_post/src/EventSubscriber/Os2formsDigitalPostSubscriber.php

View workflow job for this annotation

GitHub Actions / PHP code analysis

Method Drupal\os2forms_digital_post\EventSubscriber\Os2formsDigitalPostSubscriber::setDigitalPostContext() has parameter $digitalPostContext with no value type specified in iterable type array.
$key = $this->createSessionKeyFromSubmission($submission);
$this->requestStack->getCurrentRequest()->getSession()->set($key, $digitalPostContext);
}

/**
* Check for Digital Post context in the current request.
*/
public function getDigitalPostContext(WebformSubmissionInterface $submission): array {

Check failure on line 75 in modules/os2forms_digital_post/src/EventSubscriber/Os2formsDigitalPostSubscriber.php

View workflow job for this annotation

GitHub Actions / PHP code analysis

Method Drupal\os2forms_digital_post\EventSubscriber\Os2formsDigitalPostSubscriber::getDigitalPostContext() return type has no value type specified in iterable type array.
$key = $this->createSessionKeyFromSubmission($submission);
return $this->requestStack->getCurrentRequest()->getSession()->get($key, []);
}

/**
* Delete Digital Post context from the current request.
*/
public function deleteDigitalPostContext(WebformSubmissionInterface $submission): bool {
$key = $this->createSessionKeyFromSubmission($submission);
return (bool) $this->requestStack->getCurrentRequest()->getSession()->remove($key);
}

/**
* Create a session key from a submission that is unique to the submission.
*/
public function createSessionKeyFromSubmission(WebformSubmissionInterface $submission): string {
// Due to cloning of submission during attachment logic, we cannot use
// submission id or uuid. Webform serial, however, is copied along, so a
// combination of webform id and serial is used for uniqueness.
// @see \Drupal\os2forms_attachment\Element\AttachmentElement::overrideWebformSettings
return 'digital_post_context_' . $submission->getWebform()->id() . '_' . $submission->serial();
}

}
35 changes: 35 additions & 0 deletions modules/os2forms_digital_post/src/Helper/WebformHelperSF1601.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@

namespace Drupal\os2forms_digital_post\Helper;

use Drupal\os2web_datalookup\LookupResult\CompanyLookupResult;
use Drupal\os2web_datalookup\LookupResult\CprLookupResult;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Logger\LoggerChannelInterface;
use Drupal\advancedqueue\Entity\QueueInterface;
use Drupal\advancedqueue\Job;
use Drupal\advancedqueue\JobResult;
use Drupal\os2forms_digital_post\EventSubscriber\Os2formsDigitalPostSubscriber;
use Drupal\os2forms_digital_post\Exception\InvalidRecipientIdentifierElementException;
use Drupal\os2forms_digital_post\Exception\RuntimeException;
use Drupal\os2forms_digital_post\Exception\SubmissionNotFoundException;
Expand Down Expand Up @@ -62,6 +65,7 @@
#[Autowire(service: 'logger.channel.os2forms_digital_post_submission')]
private readonly LoggerChannelInterface $submissionLogger,
private readonly DigitalPostHelper $digitalPostHelper,
private readonly Os2formsDigitalPostSubscriber $digitalPostSubscriber,
) {
$this->webformSubmissionStorage = $entityTypeManager->getStorage('webform_submission');
$this->queueStorage = $entityTypeManager->getStorage('advancedqueue_queue');
Expand Down Expand Up @@ -152,6 +156,10 @@
$recipientIdentifierType = 'CPR';
}

$digitalPostAddressData = $this->getAddressForDigitalPost($lookupResult);

$this->digitalPostSubscriber->setDigitalPostContext($submission, $digitalPostAddressData);

$senderSettings = $this->settings->getSender();
$messageOptions = [
self::RECIPIENT_IDENTIFIER_TYPE => $recipientIdentifierType,
Expand Down Expand Up @@ -342,4 +350,31 @@
$this->beskedfordelerHelper->deleteMessages($webformSubmissions);
}

/**
* Gets lookup results addresses in the format needed for SF1601.
*/
private function getAddressForDigitalPost(CprLookupResult|CompanyLookupResult $lookupResult): array {

Check failure on line 356 in modules/os2forms_digital_post/src/Helper/WebformHelperSF1601.php

View workflow job for this annotation

GitHub Actions / PHP code analysis

Method Drupal\os2forms_digital_post\Helper\WebformHelperSF1601::getAddressForDigitalPost() return type has no value type specified in iterable type array.
$name = $lookupResult->getName();

$address = $lookupResult->getStreet();

if ($lookupResult->getHouseNr()) {
$address .= ' ' . $lookupResult->getHouseNr();
}
if ($lookupResult->getFloor()) {
$address .= ' ' . $lookupResult->getFloor();
}
if ($lookupResult->getApartmentNr()) {
$address .= ' ' . $lookupResult->getApartmentNr();
}

$zipAndCity = $lookupResult->getPostalCode() . ' ' . $lookupResult->getCity();

return [
'name' => $name,
'address' => $address,
'zipAndCity' => $zipAndCity,
];
}

}
Loading