From c28a8cf4da9307e14411efaa6d7127f4b721e44e Mon Sep 17 00:00:00 2001
From: catch <catch@35733.no-reply.drupal.org>
Date: Thu, 17 Dec 2020 17:23:07 +0000
Subject: [PATCH] Issue #2644468 by mondrake, DuaelFr, sanket_markan, swentel,
 alexpott, Lukas von Blarer, segovia94, Suresh Prabhu Parkala, shobhit_juyal,
 larowlan, rensingh99, Abhijith S, Haza, fietserwin, Berdir, catch, andypost:
 Multiple image upload breaks image dimensions

---
 .../Plugin/Field/FieldWidget/ImageWidget.php  | 13 ++--
 .../ImageFieldWidgetMultipleTest.php          | 75 +++++++++++++++++++
 2 files changed, 80 insertions(+), 8 deletions(-)
 create mode 100644 core/modules/image/tests/src/FunctionalJavascript/ImageFieldWidgetMultipleTest.php

diff --git a/core/modules/image/src/Plugin/Field/FieldWidget/ImageWidget.php b/core/modules/image/src/Plugin/Field/FieldWidget/ImageWidget.php
index 2a1805c67479..17360160a35e 100644
--- a/core/modules/image/src/Plugin/Field/FieldWidget/ImageWidget.php
+++ b/core/modules/image/src/Plugin/Field/FieldWidget/ImageWidget.php
@@ -206,11 +206,15 @@ public static function process($element, FormStateInterface $form_state, $form)
         'uri' => $file->getFileUri(),
       ];
 
+      $dimension_key = $variables['uri'] . '.image_preview_dimensions';
       // Determine image dimensions.
       if (isset($element['#value']['width']) && isset($element['#value']['height'])) {
         $variables['width'] = $element['#value']['width'];
         $variables['height'] = $element['#value']['height'];
       }
+      elseif ($form_state->has($dimension_key)) {
+        $variables += $form_state->get($dimension_key);
+      }
       else {
         $image = \Drupal::service('image.factory')->get($file->getFileUri());
         if ($image->isValid()) {
@@ -233,14 +237,7 @@ public static function process($element, FormStateInterface $form_state, $form)
 
       // Store the dimensions in the form so the file doesn't have to be
       // accessed again. This is important for remote files.
-      $element['width'] = [
-        '#type' => 'hidden',
-        '#value' => $variables['width'],
-      ];
-      $element['height'] = [
-        '#type' => 'hidden',
-        '#value' => $variables['height'],
-      ];
+      $form_state->set($dimension_key, ['width' => $variables['width'], 'height' => $variables['height']]);
     }
     elseif (!empty($element['#default_image'])) {
       $default_image = $element['#default_image'];
diff --git a/core/modules/image/tests/src/FunctionalJavascript/ImageFieldWidgetMultipleTest.php b/core/modules/image/tests/src/FunctionalJavascript/ImageFieldWidgetMultipleTest.php
new file mode 100644
index 000000000000..0638c03b5af6
--- /dev/null
+++ b/core/modules/image/tests/src/FunctionalJavascript/ImageFieldWidgetMultipleTest.php
@@ -0,0 +1,75 @@
+<?php
+
+namespace Drupal\Tests\image\FunctionalJavascript;
+
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
+use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
+use Drupal\node\Entity\Node;
+use Drupal\Tests\image\Kernel\ImageFieldCreationTrait;
+use Drupal\Tests\TestFileCreationTrait;
+
+/**
+ * Tests the image field widget support multiple upload correctly.
+ *
+ * @group image
+ */
+class ImageFieldWidgetMultipleTest extends WebDriverTestBase {
+
+  use ImageFieldCreationTrait;
+  use TestFileCreationTrait;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = ['node', 'field_ui', 'image'];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected $defaultTheme = 'stark';
+
+  /**
+   * Tests image widget element support multiple upload correctly.
+   */
+  public function testWidgetElementMultipleUploads(): void {
+    $image_factory = \Drupal::service('image.factory');
+    $file_system = \Drupal::service('file_system');
+    $web_driver = $this->getSession()->getDriver();
+
+    $this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']);
+    $field_name = 'images';
+    $storage_settings = ['cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED];
+    $field_settings = ['alt_field_required' => 0];
+    $this->createImageField($field_name, 'article', $storage_settings, $field_settings);
+    $this->drupalLogin($this->drupalCreateUser(['access content', 'create article content']));
+    $this->drupalGet('node/add/article');
+    $this->xpath('//input[@name="title[0][value]"]')[0]->setValue('Test');
+
+    $images = $this->getTestFiles('image');
+    $images = array_slice($images, 0, 5);
+
+    $paths = [];
+    foreach ($images as $image) {
+      $paths[] = $file_system->realpath($image->uri);
+    }
+
+    $remote_paths = [];
+    foreach ($paths as $path) {
+      $remote_paths[] = $web_driver->uploadFileAndGetRemoteFilePath($path);
+    }
+
+    $multiple_field = $this->xpath('//input[@multiple]')[0];
+    $multiple_field->setValue(implode("\n", $remote_paths));
+    $this->assertSession()->waitForElementVisible('css', '[data-drupal-selector="edit-images-4-preview"]');
+    $this->getSession()->getPage()->findButton('Save')->click();
+
+    $node = Node::load(1);
+    foreach ($paths as $delta => $path) {
+      $node_image = $node->{$field_name}[$delta];
+      $original_image = $image_factory->get($path);
+      $this->assertEquals($original_image->getWidth(), $node_image->width, "Correct width of image #$delta");
+      $this->assertEquals($original_image->getHeight(), $node_image->height, "Correct height of image #$delta");
+    }
+  }
+
+}
-- 
GitLab