- Issue created by @ad0z
- Issue was unassigned.
- Status changed to Needs review
over 1 year ago 3:39pm 16 October 2023
There is a bug in src/Plugin/Field/FieldWidget/FieldCollectionEmbedWidget.php
removeSubmit
renumber mechanism.
It leads the form state field storage to grow unexpectedly and nesting deeper and deeper for every next processed item, then form state cache cannot be saved in database because it's too big and item cannot be removed from UI - ajax call returns internal server error.
I had a node with over 15 field collection items added. (6 fields) and form state cache was calculated to be over 800MB when I tried to remove one of the first items.
I think this issue was reported here:
https://www.drupal.org/project/field_collection/issues/2887246 →
but it was ignored and closed.
$old_element_address = array_merge($address, ['widget', $i + 1]);
$old_element_state_address = array_merge($address_state, [$i + 1]);
$new_element_state_address = array_merge($address_state, [$i]);
$moving_element = NestedArray::getValue($form, $old_element_address);
$moving_element_value = NestedArray::getValue($form_state->getValues(), $old_element_state_address);
$moving_element_input = NestedArray::getValue($form_state->getUserInput(), $old_element_state_address);
$moving_element_field = NestedArray::getValue($form_state->get('field_storage'), array_merge(['#parents'], $address));
// Tell the element where it's being moved to.
$moving_element['#parents'] = $new_element_state_address;
// Move the element around.
$form_state->setValueForElement($moving_element, $moving_element_value);
$user_input = $form_state->getUserInput();
NestedArray::setValue($user_input, $moving_element['#parents'], $moving_element_input);
$form_state->setUserInput($user_input);
NestedArray::setValue($form_state->get('field_storage'), array_merge(['#parents'], $moving_element['#parents']), $moving_element_field);
$moving_element_field
take the whole field storage, instead of single element storage and save it in new element position, for the next item the whole field storage is taken again(with updates made by previous loop execution), so it's growing and growing for every next element.
Method 1:
1. Add field collection field with multiple fields to a node type.
2. Add a new node with multiple field collection items and save it.
3. Edit the node and try to remove one of the first items.
Method 2:
1. Basic field collection setup
2. Debug remove item button.
$moving_element_field = NestedArray::getValue($form_state->get('field_storage'), array_merge(['#parents'], $address));
is changed to:
$moving_element_field = NestedArray::getValue($form_state->get('field_storage'), array_merge(['#parents'], $old_element_state_address));
so $moving_element_field
contains specific element storage only(not the whole field storage as it is now) to save it in new position when it happens - NestedArray::setValue($form_state->get('field_storage'), array_merge(['#parents'], $moving_element['#parents']), $moving_element_field);
Needs review
3.0
Code