Skip to content
Snippets Groups Projects
Commit 3a8f5c16 authored by Alex Pott's avatar Alex Pott Committed by Jess
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

(cherry picked from commit 6470ab79)
(cherry picked from commit 3e90900f)
parent 9bfe62ab
No related branches found
No related tags found
6 merge requests!2496Issue #3222757 by lauriii, Wim Leers, nod_, rachel_norfolk, itmaybejj,...,!2366Issue #3285105 by Daniel Arend,!2304Issue #3258987: Class "Drupal\Core\Utility\Error" not found in _drupal_error_handler_real() due to bug in PHP 8.1.0-8.1.5,!2148Issue #3270899: Remove Color module from core,!2071Issue #927570: Setting 403 or 404 handler to a page that redirects leads to endless loop,!1387Draft: Resolve #2511878 "Support enclosure field"
......@@ -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);
......
......@@ -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);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment