diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..987e2a2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +composer.lock +vendor diff --git a/.php-version b/.php-version new file mode 100644 index 0000000..37722eb --- /dev/null +++ b/.php-version @@ -0,0 +1 @@ +7.4 diff --git a/composer.json b/composer.json index 24360b1..a188abf 100644 --- a/composer.json +++ b/composer.json @@ -10,6 +10,21 @@ } ], "repositories": [ + { + "//": "https://git.drupalcode.org/issue/webform_embed-3149360/-/tree/3149360-automated-drupal-9", + "type": "package", + "package": { + "name": "drupal/webform_embed", + "//": "@see https://github.com/OS2Forms/os2forms/blob/master/composer.json#L27", + "version": "1.x-dev", + "type": "drupal-module", + "source": { + "url": "https://git.drupalcode.org/issue/webform_embed-3149360.git", + "type": "git", + "reference": "3149360-automated-drupal-9" + } + } + }, { "type": "composer", "url": "https://packages.drupal.org/8" @@ -49,5 +64,11 @@ "coding-standards-apply": [ "@coding-standards-apply/phpcs" ] + }, + "config": { + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true, + "vaimo/composer-patches": true + } } } diff --git a/phpcs.xml.dist b/phpcs.xml.dist index afd36d2..a81e1e1 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -3,7 +3,9 @@ The coding standard. . + generated-sources/ vendor/ + src/Client/ diff --git a/src/Commands/CreatePdf.php b/src/Commands/CreatePdf.php index b212234..b14f4a7 100644 --- a/src/Commands/CreatePdf.php +++ b/src/Commands/CreatePdf.php @@ -16,7 +16,7 @@ class CreatePdf extends DrushCommands { /** * The os2forms_digital_post template manager. * - * @var TemplateManager + * @var \Drupal\os2forms_digital_post\Manager\TemplateManager */ protected TemplateManager $templateManager; @@ -27,6 +27,9 @@ class CreatePdf extends DrushCommands { */ protected $entityTypeManager; + /** + * Constructor. + */ public function __construct(TemplateManager $templateManager, EntityTypeManagerInterface $entity_type_manager) { parent::__construct(); $this->templateManager = $templateManager; @@ -49,7 +52,11 @@ public function __construct(TemplateManager $templateManager, EntityTypeManagerI * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException */ - public function create($template, $options = ['submission_id' => 0, 'file_location' => '', 'file_name' => 'test.pdf']) { + public function create($template, array $options = [ + 'submission_id' => 0, + 'file_location' => '', + 'file_name' => 'test.pdf', + ]) { $elements[] = []; $webformLabel = ''; $webform_submission = $this->entityTypeManager->getStorage('webform_submission')->load($options['submission_id']); @@ -91,4 +98,5 @@ public function create($template, $options = ['submission_id' => 0, 'file_locati file_put_contents($filePath, $pdf); $this->output()->writeln(sprintf('Pdf written to %s', $filePath)); } + } diff --git a/src/Consumer/PrintServiceConsumer.php b/src/Consumer/PrintServiceConsumer.php index 9555596..cbd04a6 100644 --- a/src/Consumer/PrintServiceConsumer.php +++ b/src/Consumer/PrintServiceConsumer.php @@ -2,6 +2,7 @@ namespace Drupal\os2forms_digital_post\Consumer; +use Drupal\Core\Config\ImmutableConfig; use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Lock\LockBackendInterface; use Drupal\Core\State\State; @@ -17,10 +18,8 @@ use Drupal\os2forms_digital_post\Client\StructType\KontaktOplysningType; use Drupal\os2forms_digital_post\Client\StructType\PrintAfsendBrevRequestType; use Drupal\os2forms_digital_post\Client\StructType\SlutbrugerIdentitetType; -use Exception; use ItkDev\Serviceplatformen\Certificate\AzureKeyVaultCertificateLocator; use ItkDev\Serviceplatformen\Certificate\CertificateLocatorInterface; -use SoapFault; use WsdlToPhp\PackageBase\AbstractSoapClientBase; use GuzzleHttp\Client; use Http\Factory\Guzzle\RequestFactory; @@ -28,16 +27,55 @@ use Http\Adapter\Guzzle6\Client as GuzzleAdapter; use ItkDev\AzureKeyVault\KeyVault\VaultSecret; +/** + * Print service consumer. + */ class PrintServiceConsumer { - - private $config; - private $guzzleClient; - private $lock; - private $state; + /** + * The config. + * + * @var \Drupal\Core\Config\ImmutableConfig + */ + private ImmutableConfig $config; + + /** + * The client. + * + * @var \GuzzleHttp\Client + */ + private Client $guzzleClient; + + /** + * The lock. + * + * @var \Drupal\Core\Lock\LockBackendInterface + */ + private LockBackendInterface $lock; + + /** + * The state. + * + * @var \Drupal\Core\State\State + */ + private State $state; + + /** + * The UUID generator. + * + * @var UuidInterface + */ private $uuid; + /** + * The lock name. + * + * @var string + */ private $lockName = 'os2forms_digital_post_print_service'; + /** + * Constructor. + */ public function __construct(ConfigFactoryInterface $configFactory, Client $guzzleClient, LockBackendInterface $lock, State $state) { $this->config = $configFactory->get('os2forms_digital_post'); @@ -47,25 +85,28 @@ public function __construct(ConfigFactoryInterface $configFactory, Client $guzzl $this->uuid = \Drupal::service('uuid'); } + /** + * Afsend brev person. + */ public function afsendBrevPerson( - string $kanalValg = null, - string $prioritet = null, - string $cprNummerIdentifikator = null, - string $personName = null, - string $coNavn = null, - string $streetName = null, - string $streetBuildingIdentifier = null, - string $floorIdentifier = null, - string $suiteIdentifier = null, - string $mailDeliverySublocationIdentifier = null, - string $postCodeIdentifier = null, - string $districtSubdivisionIdentifier = null, - string $postOfficeBoxIdentifier = null, - string $countryIdentificationCode = null, - string $filFormatNavn = null, - string $meddelelseIndholdData = null, - string $titelTekst = null, - string $brevDato = null + string $kanalValg = NULL, + string $prioritet = NULL, + string $cprNummerIdentifikator = NULL, + string $personName = NULL, + string $coNavn = NULL, + string $streetName = NULL, + string $streetBuildingIdentifier = NULL, + string $floorIdentifier = NULL, + string $suiteIdentifier = NULL, + string $mailDeliverySublocationIdentifier = NULL, + string $postCodeIdentifier = NULL, + string $districtSubdivisionIdentifier = NULL, + string $postOfficeBoxIdentifier = NULL, + string $countryIdentificationCode = NULL, + string $filFormatNavn = NULL, + string $meddelelseIndholdData = NULL, + string $titelTekst = NULL, + string $brevDato = NULL ) { if (!$this->acquireLock()) { @@ -94,12 +135,12 @@ public function afsendBrevPerson( $postCodeIdentifier, $districtSubdivisionIdentifier, $postOfficeBoxIdentifier, - null, - null, - null, - null, - null, - null, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, $countryIdentificationCodeType ); @@ -114,10 +155,10 @@ public function afsendBrevPerson( $forsendelsesModtager, $filFormatNavn, $meddelelseIndholdData, - null, + NULL, $dokumentParametre, - null, - null, + NULL, + NULL, $digitalPostParametre ); @@ -140,21 +181,24 @@ public function afsendBrevPerson( AbstractSoapClientBase::WSDL_LOCATION => $this->config->get('service_endpoint'), ]); - $response = $client->afsendBrev($request); $this->releaseLock(); - if (false === $response) { + if (FALSE === $response) { $lastError = $client->getLastError(); - /* @var $soapError SoapFault */ + /** @var SoapFault $soapError */ $soapError = $lastError['Drupal\os2forms_digital_post\Client\ServiceType\Afsend::afsendBrev']; - throw new Exception($soapError->getMessage(), $soapError->getCode()); // Should maybe log this instead! + // Should maybe log this instead! + throw new \Exception($soapError->getMessage(), $soapError->getCode()); } return $response->getResultat(); } + /** + * Get absolute path to certificate. + */ private function getAzureKeyVaultCertificateLocator( string $tenantId, string $applicationId, @@ -188,13 +232,16 @@ private function getAzureKeyVaultCertificateLocator( ); } + /** + * Afsend digital post person. + */ public function afsendDigitalPostPerson( - string $kanalValg = null, - string $prioritet = null, - string $cprNummerIdentifikator = null, - string $filFormatNavn = null, - string $meddelelseIndholdData = null, - string $titelTekst = null + string $kanalValg = NULL, + string $prioritet = NULL, + string $cprNummerIdentifikator = NULL, + string $filFormatNavn = NULL, + string $meddelelseIndholdData = NULL, + string $titelTekst = NULL ): bool { if (!$this->acquireLock()) { @@ -213,18 +260,18 @@ public function afsendDigitalPostPerson( $forsendelsesModtager = new ForsendelseModtagerType($slutBrugerIdentitetType); $dokumentParametre = new DokumentParametreType($titelTekst); - $digitalPostParametre = new DigitalPostParametreType(null, $this->config->get('digital_post_materiale_id')); + $digitalPostParametre = new DigitalPostParametreType(NULL, $this->config->get('digital_post_materiale_id')); $forsendelse = new ForsendelseIType( $this->generateAfsendelseIdentifikator(), - null, + NULL, $forsendelsesModtager, $filFormatNavn, $meddelelseIndholdData, - null, + NULL, $dokumentParametre, - null, - null, + NULL, + NULL, $digitalPostParametre ); @@ -247,21 +294,24 @@ public function afsendDigitalPostPerson( AbstractSoapClientBase::WSDL_LOCATION => $this->config->get('service_endpoint'), ]); - $response = $client->afsendBrev($request); $this->releaseLock(); - if (false === $response) { + if (FALSE === $response) { $lastError = $client->getLastError(); - /* @var $soapError SoapFault */ + /** @var SoapFault $soapError */ $soapError = $lastError['Drupal\os2forms_digital_post\Client\ServiceType\Afsend::afsendBrev']; - throw new \Exception($soapError->getMessage(), $soapError->getCode()); // Should maybe log this instead! + // Should maybe log this instead! + throw new \Exception($soapError->getMessage(), $soapError->getCode()); } return $response->getResultat(); } + /** + * Generate afsendelse identifikator. + */ protected function generateAfsendelseIdentifikator(): string { $stateKey = 'os2forms_digital_post_last_letter_counter'; @@ -276,19 +326,28 @@ protected function generateAfsendelseIdentifikator(): string { return $this->config->get('digital_post_system_id') . $this->config->get('digital_post_afsender_system') - . $nextLetterNumber - ; + . $nextLetterNumber; } + /** + * Acquire lock. + */ protected function acquireLock(): bool { return $this->lock->acquire($this->lockName); } + /** + * Release lock. + */ protected function releaseLock() { $this->lock->release($this->lockName); } + /** + * Wait lock. + */ protected function waitLock(): bool { return $this->lock->wait($this->lockName); } + } diff --git a/src/Exception/CprElementNotFoundInSubmissionException.php b/src/Exception/CprElementNotFoundInSubmissionException.php index e3d352a..42f7f83 100644 --- a/src/Exception/CprElementNotFoundInSubmissionException.php +++ b/src/Exception/CprElementNotFoundInSubmissionException.php @@ -2,6 +2,9 @@ namespace Drupal\os2forms_digital_post\Exception; +/** + * Cpr Element Not Found In Submission Exception. + */ class CprElementNotFoundInSubmissionException extends \Exception { } diff --git a/src/Manager/TemplateManager.php b/src/Manager/TemplateManager.php index 0c0a094..2f74a08 100644 --- a/src/Manager/TemplateManager.php +++ b/src/Manager/TemplateManager.php @@ -2,6 +2,7 @@ namespace Drupal\os2forms_digital_post\Manager; +use Drupal\Core\Config\ImmutableConfig; use Dompdf\Css\Stylesheet; use Dompdf\Dompdf; use Dompdf\Options; @@ -9,11 +10,27 @@ use Drupal\Core\Template\TwigEnvironment; use Twig\Loader\FilesystemLoader; +/** + * Template manager. + */ class TemplateManager implements TemplateManagerInterface { + /** + * The config. + * + * @var \Drupal\Core\Config\ImmutableConfig + */ + private ImmutableConfig $config; - private $config; - private $twigEnvironment; + /** + * The Twig environment. + * + * @var \Drupal\Core\Template\TwigEnvironment + */ + private TwigEnvironment $twigEnvironment; + /** + * Constructor. + */ public function __construct(ConfigFactoryInterface $configFactory, TwigEnvironment $twigEnvironment, FilesystemLoader $filesystemLoader) { $this->config = $configFactory->get('os2forms_digital_post'); $filesystemLoader->addPath($this->config->get('path_to_templates')); @@ -23,8 +40,7 @@ public function __construct(ConfigFactoryInterface $configFactory, TwigEnvironme /** * {@inheritDoc} */ - public function getAvailableTemplates(): array - { + public function getAvailableTemplates(): array { $pathToTemplates = $this->config->get('path_to_templates'); $listOfTemplates = []; @@ -45,6 +61,9 @@ public function getAvailableTemplates(): array return $listOfTemplates; } + /** + * {@inheritDoc} + */ public function renderHtml(string $template, array $context = []): string { $context['logo'] = $this->getPathToBase64EncodedLogo($template); @@ -53,13 +72,15 @@ public function renderHtml(string $template, array $context = []): string { return $this->twigEnvironment->render($pathToTemplate, $context); } - public function renderPdf(string $template, array $context = [], bool $stream = false): string { + /** + * {@inheritDoc} + */ + public function renderPdf(string $template, array $context = [], bool $stream = FALSE): string { $html = $this->renderHtml($template, $context); - $options = new Options(); - $options->setIsHtml5ParserEnabled(true); + $options->setIsHtml5ParserEnabled(TRUE); $domPdf = new Dompdf(); $domPdf->setPaper('A4', 'portrait'); @@ -73,14 +94,19 @@ public function renderPdf(string $template, array $context = [], bool $stream = $domPdf->loadHtml($html); $domPdf->render(); - if (true === $stream) { - $domPdf->stream(); // Streams PDF to browser + if (TRUE === $stream) { + // Streams PDF to browser. + $domPdf->stream(); return ''; } - return $domPdf->output(); //Returns PDF as string + // Returns PDF as string. + return $domPdf->output(); } + /** + * Get path to base64encoded logo. + */ private function getPathToBase64EncodedLogo($template): string { $pathToLogo = $this->getPathToTemplate($template) . '/logo.png'; @@ -95,7 +121,11 @@ private function getPathToBase64EncodedLogo($template): string { return 'data:image/' . $extension . ';base64,' . $logoBase64; } + /** + * Get path to template. + */ private function getPathToTemplate(string $template): string { return $this->config->get('path_to_templates') . '/' . $template; } + } diff --git a/src/Manager/TemplateManagerInterface.php b/src/Manager/TemplateManagerInterface.php index fd51f87..e1ba526 100644 --- a/src/Manager/TemplateManagerInterface.php +++ b/src/Manager/TemplateManagerInterface.php @@ -2,6 +2,9 @@ namespace Drupal\os2forms_digital_post\Manager; +/** + * Template manager interface. + */ interface TemplateManagerInterface { /** @@ -11,4 +14,5 @@ interface TemplateManagerInterface { * List of available templates. */ public function getAvailableTemplates(): array; + } diff --git a/src/Plugin/WebformHandler/DigitalPostWebformHandler.php b/src/Plugin/WebformHandler/DigitalPostWebformHandler.php index 8e3a4d7..768b438 100644 --- a/src/Plugin/WebformHandler/DigitalPostWebformHandler.php +++ b/src/Plugin/WebformHandler/DigitalPostWebformHandler.php @@ -4,11 +4,7 @@ use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Render\Element; -use Drupal\os2forms_cpr_lookup\Service\CprServiceInterface; -use Drupal\os2forms_digital_post\Consumer\PrintServiceConsumer; use Drupal\os2forms_digital_post\Exception\CprElementNotFoundInSubmissionException; -use Drupal\os2forms_digital_post\Manager\TemplateManager; -use Drupal\webform\Annotation\WebformHandler; use Drupal\webform\Plugin\WebformHandlerBase; use Drupal\webform\WebformInterface; use Drupal\webform\WebformSubmissionInterface; @@ -27,8 +23,7 @@ * submission = \Drupal\webform\Plugin\WebformHandlerInterface::SUBMISSION_REQUIRED, * ) */ -class DigitalPostWebformHandler extends WebformHandlerBase -{ +class DigitalPostWebformHandler extends WebformHandlerBase { /** * The token manager. * @@ -44,17 +39,23 @@ class DigitalPostWebformHandler extends WebformHandlerBase protected $elementManager; /** - * @var TemplateManager + * The template manager. + * + * @var \Drupal\os2forms_digital_post\Manager\TemplateManager */ protected $templateManager; /** - * @var PrintServiceConsumer + * The print service consumer. + * + * @var \Drupal\os2forms_digital_post\Consumer\PrintServiceConsumer */ protected $printServiceConsumer; /** - * @var CprServiceInterface + * The cpr service. + * + * @var \Drupal\os2forms_cpr_lookup\Service\CprServiceInterface */ protected $cprService; @@ -95,7 +96,7 @@ public function defaultConfiguration() { * {@inheritdoc} */ public function buildConfigurationForm(array $form, FormStateInterface $form_state) { - $this->getLogger()->debug('This was the form: ' . print_r($this->getWebform()->getElementsDecoded(), true)); + $this->getLogger()->debug('This was the form: ' . print_r($this->getWebform()->getElementsDecoded(), TRUE)); $availableElements = $this->getAvailableElements($this->getWebform()->getElementsDecoded()); @@ -104,7 +105,7 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta '#title' => $this->t('Prevent elements displayed in template'), '#options' => $availableElements, '#default_value' => $this->configuration['blacklist_elements_for_template'], - '#multiple' => true, + '#multiple' => TRUE, '#size' => 10, ]; @@ -115,7 +116,7 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta '#title' => $this->t('Select template'), '#options' => $listOfTemplates, '#default_value' => $this->configuration['template'], - '#required' => true, + '#required' => TRUE, ]; // The channels available here are required by the @@ -126,8 +127,11 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta '#type' => 'select', '#title' => $this->t('Select channel'), '#options' => [ - 'D' => $this->t('Digital Post'), // Only send the letter as Digital Post. - 'A' => $this->t('Automatisk'), // Serviceplatformen decides if a citizen should have digital or physical mail based on the citizens registration. + // Only send the letter as Digital Post. + 'D' => $this->t('Digital Post'), + // Serviceplatformen decides if a citizen should have digital or + // physical mail based on the citizens registration. + 'A' => $this->t('Automatisk'), ], '#default_value' => $this->configuration['channel'], ]; @@ -149,7 +153,6 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta '#options' => $availableElements, ]; - $form['document_title'] = [ '#type' => 'textfield', '#title' => $this->t('Title of document'), @@ -173,6 +176,9 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta return $this->setSettingsParents($form); } + /** + * Get available elements. + */ private function getAvailableElements(array $elements): array { $availableElements = []; @@ -248,9 +254,6 @@ public function submitForm(array &$form, FormStateInterface $form_state, Webform * {@inheritdoc} */ public function confirmForm(array &$form, FormStateInterface $form_state, WebformSubmissionInterface $webform_submission) { -// $message = $this->configuration['message']; -// $message = $this->replaceTokens($message, $this->getWebformSubmission()); -// $this->messenger()->addStatus(Markup::create(Xss::filter($message)), FALSE); $this->debug(__FUNCTION__); } @@ -335,7 +338,7 @@ public function postSave(WebformSubmissionInterface $webform_submission, $update // when sending digital port. Therefore we append it to “floor” instead. $floor = $cprSearchResult->getFloor(); if (!empty($cprSearchResult->getSide())) { - $floor .= ' '.$cprSearchResult->getSide(); + $floor .= ' ' . $cprSearchResult->getSide(); } $recipient = [ @@ -343,7 +346,7 @@ public function postSave(WebformSubmissionInterface $webform_submission, $update 'streetName' => $cprSearchResult->getStreetName(), 'streetNumber' => $cprSearchResult->getHouseNumber(), 'floor' => $floor, - 'side' => null, + 'side' => NULL, 'postalCode' => $cprSearchResult->getPostalCode(), 'city' => $cprSearchResult->getCity(), ]; @@ -353,12 +356,12 @@ public function postSave(WebformSubmissionInterface $webform_submission, $update 'recipient' => $recipient, ]; - if (true === $this->configuration['debug']) { - $this->templateManager->renderPdf($this->configuration['template'], $context, true); + if (TRUE === $this->configuration['debug']) { + $this->templateManager->renderPdf($this->configuration['template'], $context, TRUE); return; } - $result = false; + $result = FALSE; switch ($this->configuration['channel']) { case 'A': @@ -367,21 +370,22 @@ public function postSave(WebformSubmissionInterface $webform_submission, $update $this->configuration['priority'], $submissionData[$this->configuration['cpr_element']], $cprSearchResult->getName(), - null, + NULL, $cprSearchResult->getStreetName(), $cprSearchResult->getHouseNumber(), $floor, - null, - null, + NULL, + NULL, $cprSearchResult->getPostalCode(), - null, - null, + NULL, + NULL, 'DK', 'PDF', $this->templateManager->renderPdf($this->configuration['template'], $context), $this->configuration['document_title'] ); break; + case 'D': $result = $this->printServiceConsumer->afsendDigitalPostPerson( $this->configuration['channel'], @@ -394,7 +398,7 @@ public function postSave(WebformSubmissionInterface $webform_submission, $update break; } - if (false === $result) { + if (FALSE === $result) { // Throw an error? } } @@ -467,4 +471,5 @@ protected function debug($method_name, $context1 = NULL) { $this->messenger()->addWarning($this->t('Invoked @id: @class_name:@method_name @context1', $t_args), TRUE); } } + }