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 1f91c19a9a..0101af01e4 100644 --- a/core/modules/media_library/src/Plugin/Field/FieldWidget/MediaLibraryWidget.php +++ b/core/modules/media_library/src/Plugin/Field/FieldWidget/MediaLibraryWidget.php @@ -322,7 +322,6 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen '#attached' => [ 'library' => ['media_library/widget'], ], - '#element_validate' => [[static::class, 'validateMediaWidget']], ]; // When the list of allowed types in the field configuration is null, @@ -548,12 +547,11 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen ], '#validate' => [[static::class, 'validateItems']], '#submit' => [[static::class, 'addItems']], - // If no media has been uploaded ($referenced_entities), suppress - // validation errors in the widget entirely. This prevents the - // widget-level validation from triggering required fields errors before - // media has been uploaded. - // If media is present, check for errors within this widget, but suppress - // errors in all other widgets. + // We need to prevent the widget from being validated when no media items + // are selected. When a media field is added in a subform, entity + // validation is triggered in EntityFormDisplay::validateFormValues(). + // Since the media item is not added to the form yet, this triggers errors + // for required media fields. '#limit_validation_errors' => !empty($referenced_entities) ? $limit_validation_errors : [], ]; @@ -757,55 +755,6 @@ public static function openMediaLibrary(array $form, FormStateInterface $form_st ->addCommand(new OpenModalDialogCommand($dialog_options['title'], $library_ui, $dialog_options)); } - /** - * Validation checks specific to the Media Library widget in a parent form. - * - * @param array $element - * The form element. - * @param \Drupal\Core\Form\FormStateInterface $form_state - * The form state. - * @param array $form - * The form array. - */ - public static function validateMediaWidget(array $element, FormStateInterface $form_state, array $form) { - // If a remove button triggered submit, this validation isn't needed. - if (in_array([static::class, 'removeItem'], $form_state->getSubmitHandlers(), TRUE)) { - return; - } - - $media = static::getNewMediaItems($element, $form_state); - - // Trigger error if the field is required and no media is present. - // Although the Form API's default validation would also catch this, the - // validation error message is too vague, so a more precise one is - // provided here. - $selection_count = !empty($element['selection']) ? count(Element::children($element['selection'])) : 0; - if (empty($media) && $selection_count === 0 && !empty($element['#required'])) { - $form_state->setError($element, new TranslatableMarkup('The field @name requires an item from the media library.', - ['@name' => $element['#title']])); - return; - } - - $field_state = static::getFieldState($element, $form_state); - - // After media is uploaded, validation of this field occurs on the widget - // level (the validation in this method). The field is then additionally - // validated by rules applied at the parent form level. - // The validation from the parent form can occur before uploaded media is - // added to the field. This can result in a validation error due to the - // parent form assuming the presence of media before it's been transferred - // to the field. To avoid this error, newly added media is added to the - // field prior to parent form validation. - if (count($field_state['items']) === 0 && !empty($media)) { - $media_target_ids = array_map(function ($media_item) { - return $media_item->access('view') ? ['target_id' => $media_item->id()] : NULL; - }, $media); - $field_state['items'] = array_filter($media_target_ids); - - static::setFieldState($element, $form_state, $field_state); - } - } - /** * Validates that newly selected items can be added to the widget. * @@ -895,8 +844,11 @@ public static function addItems(array $form, FormStateInterface $form_state) { * An array of selected media items. */ protected static function getNewMediaItems(array $element, FormStateInterface $form_state) { - // Get the new media IDs passed to our hidden button. - $values = $form_state->getValues(); + // Get the new media IDs passed to our hidden button. We need to use the + // actual user input, since when #limit_validation_errors is used, the + // unvalidated user input is not added to the form state. + // @see FormValidator::handleErrorsWithLimitedValidation() + $values = $form_state->getUserInput(); $path = $element['#parents']; $value = NestedArray::getValue($values, $path); @@ -928,7 +880,10 @@ protected static function getNewMediaItems(array $element, FormStateInterface $f protected static function getFieldState(array $element, FormStateInterface $form_state) { // Default to using the current selection if the form is new. $path = $element['#parents']; - $values = NestedArray::getValue($form_state->getValues(), $path); + // We need to use the actual user input, since when #limit_validation_errors + // is used, the unvalidated user input is not added to the form state. + // @see FormValidator::handleErrorsWithLimitedValidation() + $values = NestedArray::getValue($form_state->getUserInput(), $path); $selection = isset($values['selection']) ? $values['selection'] : []; $widget_state = static::getWidgetState($element['#field_parents'], $element['#field_name'], $form_state);