From dfbde869862a7a630b8adf9e2fdc15a6c1c21705 Mon Sep 17 00:00:00 2001
From: webchick <drupal@webchick.net>
Date: Fri, 2 Aug 2019 10:07:27 -0700
Subject: [PATCH] Issue #3067041 by seanB, dhirendra.mishra, Al Munnings,
 handspiker, phenaproxima, DannyBoing: Media library pagination is broken due
 to invalid entity_id parameter

---
 .../Field/FieldWidget/MediaLibraryWidget.php  |  14 +-
 .../FunctionalJavascript/MediaLibraryTest.php | 178 ++++++++++++------
 2 files changed, 127 insertions(+), 65 deletions(-)

diff --git a/core/modules/media_library/src/Plugin/Field/FieldWidget/MediaLibraryWidget.php b/core/modules/media_library/src/Plugin/Field/FieldWidget/MediaLibraryWidget.php
index 419cf6617447..0d8af0979c04 100644
--- a/core/modules/media_library/src/Plugin/Field/FieldWidget/MediaLibraryWidget.php
+++ b/core/modules/media_library/src/Plugin/Field/FieldWidget/MediaLibraryWidget.php
@@ -464,15 +464,19 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
     // attribute is the same as $field_widget_id. The entity ID, entity type ID,
     // bundle, field name are used for access checking.
     $entity = $items->getEntity();
-    $state = MediaLibraryState::create('media_library.opener.field_widget', $allowed_media_type_ids, $selected_type_id, $remaining, [
+    $opener_parameters = [
       'field_widget_id' => $field_widget_id,
       'entity_type_id' => $entity->getEntityTypeId(),
       'bundle' => $entity->bundle(),
       'field_name' => $field_name,
-      // The entity ID needs to be a string to ensure that the media library
-      // state generates its tamper-proof hash in a consistent way.
-      'entity_id' => (string) $entity->id(),
-    ]);
+    ];
+    // Only add the entity ID when we actually have one. The entity ID needs to
+    // be a string to ensure that the media library state generates its
+    // tamper-proof hash in a consistent way.
+    if (!$entity->isNew()) {
+      $opener_parameters['entity_id'] = (string) $entity->id();
+    }
+    $state = MediaLibraryState::create('media_library.opener.field_widget', $allowed_media_type_ids, $selected_type_id, $remaining, $opener_parameters);
 
     // Add a button that will load the Media library in a modal using AJAX.
     $element['media_library_open_button'] = [
diff --git a/core/modules/media_library/tests/src/FunctionalJavascript/MediaLibraryTest.php b/core/modules/media_library/tests/src/FunctionalJavascript/MediaLibraryTest.php
index d4601eef0f2f..eff1fde6f03e 100644
--- a/core/modules/media_library/tests/src/FunctionalJavascript/MediaLibraryTest.php
+++ b/core/modules/media_library/tests/src/FunctionalJavascript/MediaLibraryTest.php
@@ -563,66 +563,6 @@ public function testWidget() {
     $assert_session->pageTextContains('Bear');
     $assert_session->elementExists('css', '.ui-dialog-titlebar-close')->click();
 
-    // Assert the media library contains header links to switch between the grid
-    // and table display.
-    $assert_session->elementExists('css', '.media-library-open-button[name^="field_unlimited_media"]')->click();
-    $assert_session->assertWaitOnAjaxRequest();
-    $assert_session->elementExists('css', '.media-library-view .media-library-item--grid');
-    $assert_session->elementNotExists('css', '.media-library-view .media-library-item--table');
-    // Assert the 'Apply filter' button is not moved to the button pane.
-    $button_pane = $assert_session->elementExists('css', '.ui-dialog-buttonpane');
-    $assert_session->buttonExists('Insert selected', $button_pane);
-    $assert_session->buttonNotExists('Apply filters', $button_pane);
-    $assert_session->linkExists('Grid');
-    $page->clickLink('Table');
-    // Assert the display change is correctly announced for screen readers.
-    $this->assertNotEmpty($assert_session->waitForText('Loading table view.'));
-    $this->assertNotEmpty($assert_session->waitForText('Changed to table view.'));
-    $this->assertNotEmpty($assert_session->waitForElementVisible('css', '.media-library-view .media-library-item--table'));
-    $assert_session->elementNotExists('css', '.media-library-view .media-library-item--grid');
-    // Assert the 'Apply filter' button is not moved to the button pane.
-    $assert_session->buttonExists('Insert selected', $button_pane);
-    $assert_session->buttonNotExists('Apply filters', $button_pane);
-    $assert_session->pageTextContains('Dog');
-    $assert_session->pageTextContains('Bear');
-    $assert_session->pageTextNotContains('Turtle');
-    // Assert the exposed filters can be applied.
-    $page->fillField('Name', 'Dog');
-    $page->pressButton('Apply filters');
-    $assert_session->assertWaitOnAjaxRequest();
-    $assert_session->pageTextContains('Dog');
-    $assert_session->pageTextNotContains('Bear');
-    $assert_session->pageTextNotContains('Turtle');
-    $page->checkField('Select Dog');
-    $assert_session->linkExists('Table');
-    $page->clickLink('Grid');
-    // Assert the display change is correctly announced for screen readers.
-    $this->assertNotEmpty($assert_session->waitForText('Loading grid view.'));
-    $this->assertNotEmpty($assert_session->waitForText('Changed to grid view.'));
-    $this->assertNotEmpty($assert_session->waitForElementVisible('css', '.media-library-view .media-library-item--grid'));
-    $assert_session->elementNotExists('css', '.media-library-view .media-library-item--table');
-    // Assert the exposed filters are persisted when changing display.
-    $this->assertSame('Dog', $page->findField('Name')->getValue());
-    $assert_session->pageTextContains('Dog');
-    $assert_session->pageTextNotContains('Bear');
-    $assert_session->pageTextNotContains('Turtle');
-    $assert_session->linkExists('Grid');
-    $assert_session->linkExists('Table');
-    // Select the item.
-    $assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Insert selected');
-    $this->assertNotEmpty($assert_session->waitForText('Added one media item.'));
-    $assert_session->assertWaitOnAjaxRequest();
-    // Ensure that the selection completed successfully.
-    $assert_session->pageTextNotContains('Add or select media');
-    $assert_session->pageTextContains('Dog');
-    $assert_session->pageTextNotContains('Bear');
-    $assert_session->pageTextNotContains('Turtle');
-    // Clear the selection.
-    $assert_session->elementAttributeContains('css', '.media-library-item__remove', 'aria-label', 'Remove Dog');
-    $assert_session->elementExists('css', '.media-library-item__remove')->click();
-    $this->assertNotEmpty($assert_session->waitForText('Removed Dog.'));
-    $assert_session->assertWaitOnAjaxRequest();
-
     // Assert adding a single media item and removing it.
     $assert_session->elementExists('css', '.media-library-open-button[name^="field_twin_media"]')->click();
     $assert_session->assertWaitOnAjaxRequest();
@@ -877,6 +817,124 @@ public function testWidget() {
     $assert_session->pageTextNotContains('Snake');
   }
 
+  /**
+   * Tests that the views in the Media library's widget work as expected.
+   */
+  public function testWidgetViews() {
+    $assert_session = $this->assertSession();
+    $page = $this->getSession()->getPage();
+
+    // Create more media items for use in selection. We want to have more than
+    // 24 items to trigger a pager in the widget view.
+    $media_names = [
+      'Goat',
+      'Sheep',
+      'Pig',
+      'Cow',
+      'Chicken',
+      'Duck',
+      'Donkey',
+      'Llama',
+      'Mouse',
+      'Goldfish',
+      'Rabbit',
+      'Turkey',
+      'Dove',
+      'Giraffe',
+      'Tiger',
+      'Hamster',
+      'Parrot',
+      'Monkey',
+      'Koala',
+      'Panda',
+      'Kangaroo',
+    ];
+
+    $time = time();
+    foreach ($media_names as $name) {
+      $entity = Media::create(['name' => $name, 'bundle' => 'type_one']);
+      $entity->setCreatedTime(++$time);
+      $entity->set('field_media_test', $name);
+      $entity->save();
+    }
+
+    $this->drupalGet('node/add/basic_page');
+
+    // Assert the media library contains header links to switch between the grid
+    // and table display.
+    $assert_session->elementExists('css', '.media-library-open-button[name^="field_unlimited_media"]')->click();
+    $assert_session->assertWaitOnAjaxRequest();
+    $assert_session->elementExists('css', '.media-library-view .media-library-item--grid');
+    $assert_session->elementNotExists('css', '.media-library-view .media-library-item--table');
+    $assert_session->linkExists('Grid');
+    $assert_session->linkExists('Table');
+
+    // Assert the 'Apply filter' button is not moved to the button pane.
+    $button_pane = $assert_session->elementExists('css', '.ui-dialog-buttonpane');
+    $assert_session->buttonExists('Insert selected', $button_pane);
+    $assert_session->buttonNotExists('Apply filters', $button_pane);
+
+    // Assert the pager works as expected.
+    $assert_session->elementTextContains('css', '.media-library-view .pager__item.is-active', 'Page 1');
+    $assert_session->elementsCount('css', '.media-library-view .js-click-to-select-checkbox input', 24);
+    $page->clickLink('Next page');
+    $assert_session->assertWaitOnAjaxRequest();
+    $assert_session->elementTextContains('css', '.media-library-view .pager__item.is-active', 'Page 2');
+    $assert_session->elementsCount('css', '.media-library-view .js-click-to-select-checkbox input', 1);
+    $page->clickLink('Previous page');
+    $assert_session->assertWaitOnAjaxRequest();
+    $assert_session->elementTextContains('css', '.media-library-view .pager__item.is-active', 'Page 1');
+    $assert_session->elementsCount('css', '.media-library-view .js-click-to-select-checkbox input', 24);
+
+    // Assert the display change is correctly announced for screen readers.
+    $page->clickLink('Table');
+    $this->assertNotEmpty($assert_session->waitForText('Loading table view.'));
+    $this->assertNotEmpty($assert_session->waitForText('Changed to table view.'));
+    $this->assertNotEmpty($assert_session->waitForElementVisible('css', '.media-library-view .media-library-item--table'));
+    $assert_session->elementNotExists('css', '.media-library-view .media-library-item--grid');
+
+    // Assert the 'Apply filter' button is not moved to the button pane.
+    $assert_session->buttonExists('Insert selected', $button_pane);
+    $assert_session->buttonNotExists('Apply filters', $button_pane);
+    $assert_session->pageTextContains('Dog');
+    $assert_session->pageTextContains('Bear');
+    $assert_session->pageTextNotContains('Turtle');
+
+    // Assert the exposed filters can be applied.
+    $page->fillField('Name', 'Dog');
+    $page->pressButton('Apply filters');
+    $assert_session->assertWaitOnAjaxRequest();
+    $assert_session->pageTextContains('Dog');
+    $assert_session->pageTextNotContains('Bear');
+    $assert_session->pageTextNotContains('Turtle');
+    $page->checkField('Select Dog');
+    $assert_session->linkExists('Table');
+    $page->clickLink('Grid');
+    // Assert the display change is correctly announced for screen readers.
+    $this->assertNotEmpty($assert_session->waitForText('Loading grid view.'));
+    $this->assertNotEmpty($assert_session->waitForText('Changed to grid view.'));
+    $this->assertNotEmpty($assert_session->waitForElementVisible('css', '.media-library-view .media-library-item--grid'));
+    $assert_session->elementNotExists('css', '.media-library-view .media-library-item--table');
+
+    // Assert the exposed filters are persisted when changing display.
+    $this->assertSame('Dog', $page->findField('Name')->getValue());
+    $assert_session->pageTextContains('Dog');
+    $assert_session->pageTextNotContains('Bear');
+    $assert_session->pageTextNotContains('Turtle');
+    $assert_session->linkExists('Grid');
+    $assert_session->linkExists('Table');
+
+    // Select the item.
+    $assert_session->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Insert selected');
+    $this->assertNotEmpty($assert_session->waitForText('Added one media item.'));
+    $assert_session->assertWaitOnAjaxRequest();
+    // Ensure that the selection completed successfully.
+    $assert_session->pageTextNotContains('Add or select media');
+    $assert_session->pageTextContains('Dog');
+    $assert_session->pageTextNotContains('Bear');
+    $assert_session->pageTextNotContains('Turtle');
+  }
+
   /**
    * Tests that the widget works as expected for anonymous users.
    */
-- 
GitLab