From c5a9a705925dd60e308cd3063ba7610e64fe77dc Mon Sep 17 00:00:00 2001
From: wizonesolutions <wizonesolutions@739994.no-reply.drupal.org>
Date: Sun, 16 Feb 2020 21:33:43 +0100
Subject: [PATCH] Issue #3044467 by wizonesolutions, khaldoon_masud,
 jasonschweb, Pancho: Webform Signature Field doesn't work with FillPDF

---
 composer.json                                 |  6 ++--
 src/TokenResolver.php                         | 35 ++++++++++++++++++-
 .../Functional/PdfWebformPopulationTest.php   | 21 ++++++++++-
 3 files changed, 58 insertions(+), 4 deletions(-)

diff --git a/composer.json b/composer.json
index 26f1411..897d11c 100644
--- a/composer.json
+++ b/composer.json
@@ -10,8 +10,10 @@
         }
     ],
     "minimum-stability": "dev",
-    "require-dev": {
-        "drupal/webform": "^5.0",
+    "require": {
         "drupal/token": "^1.0"
+    },
+    "require-dev": {
+        "drupal/webform": "^5.0"
     }
 }
diff --git a/src/TokenResolver.php b/src/TokenResolver.php
index e789c61..9428f4f 100644
--- a/src/TokenResolver.php
+++ b/src/TokenResolver.php
@@ -161,14 +161,27 @@ class TokenResolver implements TokenResolverInterface {
     // Loop through the tokens, starting with the last one.
     foreach (array_reverse($tokens) as $token) {
       $name = strtr($token, ['values:' => '']);
-      if (array_key_exists($name, $elements) && isset($elements[$name]['#type']) && $elements[$name]['#type'] === 'webform_image_file') {
+      if (!array_key_exists($name, $elements) || !isset($elements[$name]['#type'])) {
+        continue;
+      }
+      if ($elements[$name]['#type'] === 'webform_image_file') {
         $file = File::load($entity->getElementData($name));
         if ($file) {
           $uri = $file->getFileUri();
           return new ImageFieldMapping(file_get_contents($uri), NULL, $uri);
         }
       }
+      elseif ($elements[$name]['#type'] === 'webform_signature') {
+        $signature_data = $entity->getElementData($name);
+        $signature_image = static::getSignatureImage($signature_data);
+        if (!$signature_image) {
+          continue;
+        }
+        return new ImageFieldMapping($signature_image, NULL, 'webform_signature.png');
+      }
     }
+
+    return NULL;
   }
 
   /**
@@ -186,6 +199,8 @@ class TokenResolver implements TokenResolverInterface {
    *
    * @return \Drupal\fillpdf\FieldMapping\ImageFieldMapping|null
    *   An ImageFieldMapping, or NULL if the tokens were no image field tokens.
+   *
+   * @throws \Drupal\Core\TypedData\Exception\MissingDataException
    */
   protected static function parseImageFieldTokens(array $tokens, FieldableEntityInterface $entity) {
     // Loop through the tokens, starting with the last one.
@@ -223,4 +238,22 @@ class TokenResolver implements TokenResolverInterface {
     return $this->tokenEntityMapper;
   }
 
+  /**
+   * Convert the base64-encoded signature image into regular image data.
+   *
+   * The result can be fed into an ImageFieldMapping.
+   *
+   * @param string $webform_element_value
+   *   The value from the Webform submission, retrieved using
+   *   the getElementData() method.
+   *
+   * @see \Drupal\fillpdf\FieldMapping\ImageFieldMapping
+   *
+   * @return string
+   *   The signature image as a string to save to a file or stream.
+   */
+  public static function getSignatureImage($webform_element_value) {
+    return base64_decode(preg_replace('#^data:image/\w+;base64,#i', '', $webform_element_value));
+  }
+
 }
diff --git a/tests/src/Functional/PdfWebformPopulationTest.php b/tests/src/Functional/PdfWebformPopulationTest.php
index 9ad698b..61ab615 100644
--- a/tests/src/Functional/PdfWebformPopulationTest.php
+++ b/tests/src/Functional/PdfWebformPopulationTest.php
@@ -6,10 +6,11 @@ use Drupal\Component\Utility\UrlHelper;
 use Drupal\Core\Url;
 use Drupal\file\Entity\File;
 use Drupal\fillpdf\Entity\FillPdfForm;
+use Drupal\fillpdf\TokenResolver;
 use Drupal\user\Entity\Role;
-use Drupal\webform\WebformInterface;
 use Drupal\webform\Entity\Webform;
 use Drupal\webform\Entity\WebformSubmission;
+use Drupal\webform\WebformInterface;
 
 /**
  * Tests Webform population and image stamping.
@@ -117,6 +118,18 @@ class PdfWebformPopulationTest extends FillPdfTestBase {
       "{image}{$submission_file->getFileUri()}",
       'URI in metadata matches expected URI.'
     );
+
+    self::assertEquals(
+      '{image}webform_signature.png',
+      $populate_result['field_mapping']['fields']['TestButton'],
+      'Signature matches signature from Webform.'
+    );
+    $signature_image = TokenResolver::getSignatureImage($submission_values['test_signature']);
+    self::assertEquals(
+      base64_encode($signature_image),
+      $populate_result['field_mapping']['images']['TestButton']['data'],
+      'Signature matches signature from Webform.'
+    );
   }
 
   /**
@@ -149,6 +162,8 @@ class PdfWebformPopulationTest extends FillPdfTestBase {
    *
    * @param \Drupal\fillpdf\Entity\FillPdfFormField[] $fields
    *   Array of FillPdfFormFields.
+   *
+   * @throws \Drupal\Core\Entity\EntityStorageException
    */
   protected function mapFillPdfFieldsToWebformFields(array $fields) {
     foreach ($fields as $pdf_key => $field) {
@@ -160,6 +175,10 @@ class PdfWebformPopulationTest extends FillPdfTestBase {
         case 'TextField1':
           $field->value = '[webform_submission:webform:title]';
           break;
+
+        case 'TestButton':
+          $field->value = '[webform_submission:values:test_signature]';
+          break;
       }
       $field->save();
     }
-- 
GitLab