diff --git a/core/lib/Drupal/Core/Field/WidgetBase.php b/core/lib/Drupal/Core/Field/WidgetBase.php index b1579f2445..b90d9b941c 100644 --- a/core/lib/Drupal/Core/Field/WidgetBase.php +++ b/core/lib/Drupal/Core/Field/WidgetBase.php @@ -240,9 +240,21 @@ protected function formMultipleElements(FieldItemListInterface $items, array &$f 'effect' => 'fade', ], ]; + + // Allow modules to alter the field multiple widget form element. + $context = [ + 'form' => $form, + 'widget' => $this, + 'items' => $items, + 'delta' => $delta, + 'default' => $this->isDefaultValueWidget($form_state), + ]; + \Drupal::moduleHandler()->alter([ + 'field_widget_multiple_form', + 'field_widget_multiple_' . $this->getPluginId() . '_form', + ], $elements, $form_state, $context); } } - return $elements; } diff --git a/core/modules/field/field.api.php b/core/modules/field/field.api.php index 130f923180..aed3dde820 100644 --- a/core/modules/field/field.api.php +++ b/core/modules/field/field.api.php @@ -183,6 +183,7 @@ function hook_field_widget_info_alter(array &$info) { * @see \Drupal\Core\Field\WidgetBaseInterface::form() * @see \Drupal\Core\Field\WidgetBase::formSingleElement() * @see hook_field_widget_WIDGET_TYPE_form_alter() + * @see hook_field_widget_multiple_form_alter() */ function hook_field_widget_form_alter(&$element, \Drupal\Core\Form\FormStateInterface $form_state, $context) { // Add a css class to widget form elements for all fields of type mytype. @@ -212,6 +213,7 @@ function hook_field_widget_form_alter(&$element, \Drupal\Core\Form\FormStateInte * @see \Drupal\Core\Field\WidgetBaseInterface::form() * @see \Drupal\Core\Field\WidgetBase::formSingleElement() * @see hook_field_widget_form_alter() + * @see hook_field_widget_multiple_WIDGET_TYPE_form_alter() */ function hook_field_widget_WIDGET_TYPE_form_alter(&$element, \Drupal\Core\Form\FormStateInterface $form_state, $context) { // Code here will only act on widgets of type WIDGET_TYPE. For example, @@ -220,6 +222,78 @@ function hook_field_widget_WIDGET_TYPE_form_alter(&$element, \Drupal\Core\Form\F $element['#autocomplete_route_name'] = 'mymodule.autocomplete_route'; } +/** + * Alter forms for multivalue field widgets provided by other modules. + * + * To adjust the individual widgets for the values themselves, use + * hook_field_widget_form_alter() instead. + * + * @param $element + * The field widget form element as constructed by + * \Drupal\Core\Field\WidgetBaseInterface::form(). + * @param $form_state + * The current state of the form. + * @param $context + * An associative array containing the following key-value pairs: + * - form: The form structure to which widgets are being attached. This may be + * a full form structure, or a sub-element of a larger form. + * - widget: The widget plugin instance. + * - items: The field values, as a + * \Drupal\Core\Field\FieldItemListInterface object. + * - delta: The order of this item in the array of subelements (0, 1, 2, etc). + * - default: A boolean indicating whether the form is being shown as a dummy + * form to set default values. + * + * @see \Drupal\Core\Field\WidgetBaseInterface::form() + * @see \Drupal\Core\Field\WidgetBase::formSingleElement() + * @see hook_field_widget_form_alter() + * @see hook_field_widget_multiple_WIDGET_TYPE_form_alter() + */ +function hook_field_widget_multiple_form_alter(&$element, \Drupal\Core\Form\FormStateInterface $form_state, $context) { + // Add a css class to the overall element of any widget. + $element['#attributes']['class'][] = 'myclass'; +} + +/** + * Alter multi-value widget forms for a widget provided by another module. + * + * Modules can implement hook_field_widget_multiple_WIDGET_TYPE_form_alter() to + * modify a specific widget form, rather than using + * hook_field_widget_form_alter() and checking the widget type. + * + * To modify the widget for individual itesm, use + * hook_field_widget_WIDGET_TYPE_form_alter() instead. + * + * @param $element + * The field widget form element as constructed by + * \Drupal\Core\Field\WidgetBaseInterface::form(). + * @param $form_state + * The current state of the form. + * @param $context + * An associative array. See hook_field_widget_form_alter() for the structure + * and content of the array. + * + * @see \Drupal\Core\Field\WidgetBaseInterface::form() + * @see \Drupal\Core\Field\WidgetBase::formSingleElement() + * @see hook_field_widget_multiple_form_alter() + */ +function hook_field_widget_multiple_WIDGET_TYPE_form_alter(&$elements, \Drupal\Core\Form\FormStateInterface $form_state, $context) { + // Alter the overall title for the multivalue widget (the table header, + // above the rows). + $elements['#title'] = \Drupal::t('Review your %title entries', ['%title' => $elements['#title']]); + + if (!empty($elements['#description'])) { + // Add a paragraph to the description, above all the rows. + $elements['#description'] = [ + '#markup' => \Drupal::t('These items might be out of date.'), + '#markup' => $elements['#description'], + ]; + } + else { + $elements['#description'] = \Drupal::t('These items might be out of date.'); + } +} + /** * @} End of "defgroup field_widget". */ diff --git a/core/modules/media/media.module b/core/modules/media/media.module index 296945973a..fa76bb406a 100644 --- a/core/modules/media/media.module +++ b/core/modules/media/media.module @@ -9,6 +9,7 @@ use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Render\Element; +use Drupal\Core\Render\Markup; use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\Session\AccountInterface; use Drupal\Core\Url; @@ -172,3 +173,99 @@ function media_form_field_ui_field_storage_add_form_alter(&$form, FormStateInter $form['add']['new_storage_type']['#weight'] = 0; $form['add']['description_wrapper']['#weight'] = 1; } + +/** + * Implements hook_field_widget_WIDGET_TYPE_form_alter(). + */ +function media_field_widget_entity_reference_autocomplete_form_alter(&$element, \Drupal\Core\Form\FormStateInterface $form_state, $context) { + // Only act on Media entity reference autocomplete fields. + if (!empty($element['target_id']['#type']) && ($element['target_id']['#type'] === 'entity_autocomplete') && ($element['target_id']['#target_type'] === 'media')) { + + $label = $element['target_id']['#title']; + $element['target_id']['#title'] = t('