Unverified Commit 6470ab79 authored by Alex Pott's avatar Alex Pott
Browse files

Issue #3115054 by chr.fritsch, vsujeetkumar, Vidushi Mehta, sergiuteaca,...

Issue #3115054 by chr.fritsch, vsujeetkumar, Vidushi Mehta, sergiuteaca, janmejaig, ranjith_kumar_k_u, phenaproxima: Media library widget forgets ordering when adding or removing items
parent 80ba63ed
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
@@ -286,6 +286,22 @@ public function form(FieldItemListInterface $items, array &$form, FormStateInter
    return parent::form($items, $form, $form_state, $get_delta);
  }

  /**
   * {@inheritdoc}
   */
  public function extractFormValues(FieldItemListInterface $items, array $form, FormStateInterface $form_state) {
    parent::extractFormValues($items, $form, $form_state);

    // Update reference to 'items' stored during add or remove to take into
    // account changes to values like 'weight' etc.
    // @see Drupal\media_library\Plugin\Field\FieldWidget\MediaLibraryWidget::addItems
    // @see Drupal\media_library\Plugin\Field\FieldWidget\MediaLibraryWidget::removeItem
    $field_name = $this->fieldDefinition->getName();
    $field_state = static::getWidgetState($form['#parents'], $field_name, $form_state);
    $field_state['items'] = $items->getValue();
    static::setWidgetState($form['#parents'], $field_name, $form_state, $field_state);
  }

  /**
   * {@inheritdoc}
   */
@@ -744,7 +760,15 @@ public static function updateWidget(array $form, FormStateInterface $form_state)
   *   The form state.
   */
  public static function removeItem(array $form, FormStateInterface $form_state) {
    // During the form rebuild, formElement() will create field item widget
    // elements using re-indexed deltas, so clear out FormState::$input to
    // avoid a mismatch between old and new deltas. The rebuilt elements will
    // have #default_value set appropriately for the current state of the field,
    // so nothing is lost in doing this.
    // @see Drupal\media_library\Plugin\Field\FieldWidget\MediaLibraryWidget::extractFormValues
    $triggering_element = $form_state->getTriggeringElement();
    $parents = array_slice($triggering_element['#parents'], 0, -2);
    NestedArray::setValue($form_state->getUserInput(), $parents, NULL);

    // Get the parents required to find the top-level widget element.
    if (count($triggering_element['#array_parents']) < 4) {
@@ -844,7 +868,17 @@ public static function validateItems(array $form, FormStateInterface $form_state
   *   The form state.
   */
  public static function addItems(array $form, FormStateInterface $form_state) {
    // During the form rebuild, formElement() will create field item widget
    // elements using re-indexed deltas, so clear out FormState::$input to
    // avoid a mismatch between old and new deltas. The rebuilt elements will
    // have #default_value set appropriately for the current state of the field,
    // so nothing is lost in doing this.
    // @see Drupal\media_library\Plugin\Field\FieldWidget\MediaLibraryWidget::extractFormValues
    $button = $form_state->getTriggeringElement();
    $parents = array_slice($button['#parents'], 0, -1);
    $parents[] = 'selection';
    NestedArray::setValue($form_state->getUserInput(), $parents, NULL);

    $element = NestedArray::getValue($form, array_slice($button['#array_parents'], 0, -1));

    $field_state = static::getFieldState($element, $form_state);
+86 −0
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@
namespace Drupal\Tests\media_library\FunctionalJavascript;

use Drupal\field\Entity\FieldConfig;
use Drupal\FunctionalJavascriptTests\SortableTestTrait;

/**
 * Tests the Media library entity reference widget.
@@ -11,6 +12,8 @@
 */
class EntityReferenceWidgetTest extends MediaLibraryTestBase {

  use SortableTestTrait;

  /**
   * {@inheritdoc}
   */
@@ -256,6 +259,7 @@ public function testWidget() {
    $this->openMediaLibraryForField('field_twin_media');
    $page->checkField('Select Dog');
    $this->pressInsertSelected('Added one media item.');
    $this->waitForElementsCount('css', '.field--name-field-twin-media [data-media-library-item-delta]', 2);
    // Assert that we can toggle the visibility of the weight inputs when the
    // field contains more than one item.
    $wrapper = $assert_session->elementExists('css', '.field--name-field-twin-media');
@@ -485,4 +489,86 @@ public function testRequiredMediaField() {
    $this->assertSession()->pageTextContains('Basic page My page has been created.');
  }

  /**
   * Tests that changed order is maintained after removing a selection.
   */
  public function testRemoveAfterReordering(): void {
    $assert_session = $this->assertSession();
    $page = $this->getSession()->getPage();

    $this->drupalGet('node/add/basic_page');
    $page->fillField('Title', 'My page');

    $this->openMediaLibraryForField('field_unlimited_media');
    $page->checkField('Select Dog');
    $page->checkField('Select Cat');
    $page->checkField('Select Bear');
    // Order: Dog - Cat - Bear.
    $this->pressInsertSelected('Added 3 media items.');

    // Move first item (Dog) to the end.
    // Order: Cat - Bear - Dog.
    $this->sortableAfter('[data-media-library-item-delta="0"]', '[data-media-library-item-delta="2"]', '.js-media-library-selection');

    $wrapper = $assert_session->elementExists('css', '.field--name-field-unlimited-media');
    // Remove second item (Bear).
    // Order: Cat - Dog.
    $wrapper->find('css', "[aria-label='Remove Bear']")->press();
    $this->waitForText('Bear has been removed.');
    $page->pressButton('Save');

    $assert_session->elementTextContains('css', '.field--name-field-unlimited-media > .field__items > .field__item:last-child', 'Dog');
  }

  /**
   * Tests that order is correct after re-order and adding another item.
   */
  public function testAddAfterReordering(): void {
    $assert_session = $this->assertSession();
    $page = $this->getSession()->getPage();

    $this->drupalGet('node/add/basic_page');
    $page->fillField('Title', 'My page');

    $this->openMediaLibraryForField('field_unlimited_media');
    $page->checkField('Select Dog');
    $page->checkField('Select Cat');
    // Order: Dog - Cat.
    $this->pressInsertSelected('Added 2 media items.');

    // Change positions.
    // Order: Cat - Dog.
    $this->sortableAfter('[data-media-library-item-delta="0"]', '[data-media-library-item-delta="1"]', '.js-media-library-selection');

    $this->openMediaLibraryForField('field_unlimited_media');
    $this->selectMediaItem(2);
    // Order: Cat - Dog - Bear.
    $this->pressInsertSelected('Added one media item.');

    $page->pressButton('Save');

    $assert_session->elementTextContains('css', '.field--name-field-unlimited-media > .field__items > .field__item:first-child', 'Cat');
    $assert_session->elementTextContains('css', '.field--name-field-unlimited-media > .field__items > .field__item:last-child', 'Bear');
  }

  /**
   * {@inheritdoc}
   */
  protected function sortableUpdate($item, $from, $to = NULL) {
    // See core/modules/media_library/js/media_library.widget.es6.js.
    $script = <<<JS
(function ($) {
    var selection = document.querySelectorAll('.js-media-library-selection');
    selection.forEach(function (widget) {
        $(widget).children().each(function (index, child) {
            $(child).find('.js-media-library-item-weight').val(index);
        });
    });
})(jQuery)

JS;

    $this->getSession()->executeScript($script);
  }

}