Unverified Commit 81e2d9c0 authored by Alex Pott's avatar Alex Pott
Browse files

Issue #2872162 by chr.fritsch, adityasingh, jian he, p4trizio, amateescu,...

Issue #2872162 by chr.fritsch, adityasingh, jian he, p4trizio, amateescu, alexpott: No hook alter to override Field Widget wrappers created by WidgetBase::form
parent 5f043576
Loading
Loading
Loading
Loading
+15 −3
Original line number Diff line number Diff line
@@ -119,7 +119,7 @@ public function form(FieldItemListInterface $items, array &$form, FormStateInter
      'items' => $items,
      'default' => $this->isDefaultValueWidget($form_state),
    ];
    \Drupal::moduleHandler()->alter([
    \Drupal::moduleHandler()->alterDeprecated('Deprecated in drupal:9.2.0 and is removed from drupal:10.0.0. Use hook_field_widget_complete_form_alter or hook_field_widget_complete_WIDGET_TYPE_form_alter instead. See https://www.drupal.org/node/3180429.', [
      'field_widget_multivalue_form',
      'field_widget_multivalue_' . $this->getPluginId() . '_form',
    ], $elements, $form_state, $context);
@@ -135,7 +135,7 @@ public function form(FieldItemListInterface $items, array &$form, FormStateInter
    // Most widgets need their internal structure preserved in submitted values.
    $elements += ['#tree' => TRUE];

    return [
    $field_widget_complete_form = [
      // Aid in theming of widgets by rendering a classified container.
      '#type' => 'container',
      // Assign a different parent, to keep the main id for the widget itself.
@@ -149,6 +149,17 @@ public function form(FieldItemListInterface $items, array &$form, FormStateInter
      ],
      'widget' => $elements,
    ];

    // Allow modules to alter the field widget form element.
    $context = [
      'form' => $form,
      'widget' => $this,
      'items' => $items,
      'default' => $this->isDefaultValueWidget($form_state),
    ];
    \Drupal::moduleHandler()->alter(['field_widget_complete_form', 'field_widget_complete_' . $this->getPluginId() . '_form'], $field_widget_complete_form, $form_state, $context);

    return $field_widget_complete_form;
  }

  /**
@@ -350,7 +361,8 @@ protected function formSingleElement(FieldItemListInterface $items, $delta, arra
        'delta' => $delta,
        'default' => $this->isDefaultValueWidget($form_state),
      ];
      \Drupal::moduleHandler()->alter(['field_widget_form', 'field_widget_' . $this->getPluginId() . '_form'], $element, $form_state, $context);
      \Drupal::moduleHandler()->alterDeprecated('Deprecated in drupal:9.2.0 and is removed from drupal:10.0.0. Use hook_field_widget_single_element_form_alter or hook_field_widget_single_element_WIDGET_TYPE_form_alter instead. See https://www.drupal.org/node/3180429.', ['field_widget_form', 'field_widget_' . $this->getPluginId() . '_form'], $element, $form_state, $context);
      \Drupal::moduleHandler()->alter(['field_widget_single_element_form', 'field_widget_single_element_' . $this->getPluginId() . '_form'], $element, $form_state, $context);
    }

    return $element;
+4 −4
Original line number Diff line number Diff line
@@ -57,8 +57,8 @@ public function settingsSummary();
   * formElement() method will be called as many times as needed.
   *
   * Other modules may alter the form element provided by this function using
   * hook_field_widget_form_alter() or
   * hook_field_widget_WIDGET_TYPE_form_alter().
   * hook_field_widget_single_element_form_alter() or
   * hook_field_widget_single_element_WIDGET_TYPE_form_alter().
   *
   * The FAPI element callbacks (such as #process, #element_validate,
   * #value_callback, etc.) used by the widget do not have access to the
@@ -98,8 +98,8 @@ public function settingsSummary();
   * @return array
   *   The form elements for a single widget for this field.
   *
   * @see hook_field_widget_form_alter()
   * @see hook_field_widget_WIDGET_TYPE_form_alter()
   * @see hook_field_widget_single_element_form_alter()
   * @see hook_field_widget_single_element_WIDGET_TYPE_form_alter()
   */
  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state);

+150 −0
Original line number Diff line number Diff line
@@ -184,6 +184,10 @@ function hook_field_widget_info_alter(array &$info) {
 *   - default: A boolean indicating whether the form is being shown as a dummy
 *     form to set default values.
 *
 * @deprecated in drupal:9.2.0 and is removed from drupal:10.0.0. Use
 *   hook_field_widget_single_element_form_alter instead.
 *
 * @see https://www.drupal.org/node/3180429
 * @see \Drupal\Core\Field\WidgetBaseInterface::form()
 * @see \Drupal\Core\Field\WidgetBase::formSingleElement()
 * @see hook_field_widget_WIDGET_TYPE_form_alter()
@@ -219,6 +223,10 @@ function hook_field_widget_form_alter(&$element, \Drupal\Core\Form\FormStateInte
 *   An associative array. See hook_field_widget_form_alter() for the structure
 *   and content of the array.
 *
 * @deprecated in drupal:9.2.0 and is removed from drupal:10.0.0. Use
 *   hook_field_widget_single_element_WIDGET_TYPE_form_alter instead.
 *
 * @see https://www.drupal.org/node/3180429
 * @see \Drupal\Core\Field\WidgetBaseInterface::form()
 * @see \Drupal\Core\Field\WidgetBase::formSingleElement()
 * @see hook_field_widget_form_alter()
@@ -231,6 +239,140 @@ function hook_field_widget_WIDGET_TYPE_form_alter(&$element, \Drupal\Core\Form\F
  $element['#autocomplete_route_name'] = 'mymodule.autocomplete_route';
}

/**
 * Alter forms for field widgets provided by other modules.
 *
 * This hook can only modify individual elements within a field widget and
 * cannot alter the top level (parent element) for multi-value fields. In most
 * cases, you should use hook_field_widget_complete_form_alter() instead and
 * loop over the elements.
 *
 * @param array $element
 *   The field widget form element as constructed by
 *   \Drupal\Core\Field\WidgetBaseInterface::form().
 * @param \Drupal\Core\Form\FormStateInterface $form_state
 *   The current state of the form.
 * @param array $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_single_element_WIDGET_TYPE_form_alter()
 * @see hook_field_widget_complete_form_alter()
 * @see https://www.drupal.org/node/3180429
 */
function hook_field_widget_single_element_form_alter(array &$element, \Drupal\Core\Form\FormStateInterface $form_state, array $context) {
  // Add a css class to widget form elements for all fields of type my_type.
  $field_definition = $context['items']->getFieldDefinition();
  if ($field_definition->getType() == 'my_type') {
    // Be sure not to overwrite existing attributes.
    $element['#attributes']['class'][] = 'my-class';
  }
}

/**
 * Alter widget forms for a specific widget provided by another module.
 *
 * Modules can implement
 * hook_field_widget_single_element_WIDGET_TYPE_form_alter() to modify a
 * specific widget form, rather than using
 * hook_field_widget_single_element_form_alter() and checking the widget type.
 *
 * This hook can only modify individual elements within a field widget and
 * cannot alter the top level (parent element) for multi-value fields. In most
 * cases, you should use hook_field_widget_complete_WIDGET_TYPE_form_alter()
 * instead and loop over the elements.
 *
 * @param array $element
 *   The field widget form element as constructed by
 *   \Drupal\Core\Field\WidgetBaseInterface::form().
 * @param \Drupal\Core\Form\FormStateInterface $form_state
 *   The current state of the form.
 * @param array $context
 *   An associative array. See hook_field_widget_single_element_form_alter()
 *   for the structure and content of the array.
 *
 * @see https://www.drupal.org/node/3180429
 * @see \Drupal\Core\Field\WidgetBaseInterface::form()
 * @see \Drupal\Core\Field\WidgetBase::formSingleElement()
 * @see hook_field_widget_single_element_form_alter()
 * @see hook_field_widget_complete_WIDGET_TYPE_form_alter()
 */
function hook_field_widget_single_element_WIDGET_TYPE_form_alter(array &$element, \Drupal\Core\Form\FormStateInterface $form_state, array $context) {
  // Code here will only act on widgets of type WIDGET_TYPE.  For example,
  // hook_field_widget_single_element_mymodule_autocomplete_form_alter() will
  // only act on widgets of type 'mymodule_autocomplete'.
  $element['#autocomplete_route_name'] = 'mymodule.autocomplete_route';
}

/**
 * Alter the complete form for field widgets provided by other modules.
 *
 * @param $field_widget_complete_form
 *   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::form()
 * @see hook_field_widget_complete_WIDGET_TYPE_form_alter()
 * @see https://www.drupal.org/node/3180429
 */
function hook_field_widget_complete_form_alter(&$field_widget_complete_form, \Drupal\Core\Form\FormStateInterface $form_state, $context) {
  $field_widget_complete_form['#attributes']['class'][] = 'my-class';
}

/**
 * Alter the complete form for a specific widget provided by other modules.
 *
 * Modules can implement hook_field_widget_complete_WIDGET_TYPE_form_alter()
 * to modify a specific widget form, rather than using
 * hook_field_widget_complete_form_alter() and checking the widget type.
 *
 * @param $field_widget_complete_form
 *   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::form()
 * @see hook_field_widget_complete_form_alter()
 * @see https://www.drupal.org/node/3180429
 */
function hook_field_widget_complete_WIDGET_TYPE_form_alter(&$field_widget_complete_form, \Drupal\Core\Form\FormStateInterface $form_state, $context) {
  $field_widget_complete_form['#attributes']['class'][] = 'my-class';
}

/**
 * Alter forms for multi-value field widgets provided by other modules.
 *
@@ -252,6 +394,10 @@ function hook_field_widget_WIDGET_TYPE_form_alter(&$element, \Drupal\Core\Form\F
 *   - default: A boolean indicating whether the form is being shown as a dummy
 *     form to set default values.
 *
 * @deprecated in drupal:9.2.0 and is removed from drupal:10.0.0. Use
 *   hook_field_widget_complete_form_alter instead.
 *
 * @see https://www.drupal.org/node/3180429
 * @see \Drupal\Core\Field\WidgetBaseInterface::form()
 * @see \Drupal\Core\Field\WidgetBase::formMultipleElements()
 * @see hook_field_widget_multivalue_WIDGET_TYPE_form_alter()
@@ -284,6 +430,10 @@ function hook_field_widget_multivalue_form_alter(array &$elements, \Drupal\Core\
 *   An associative array. See hook_field_widget_multivalue_form_alter() for
 *   the structure and content of the array.
 *
 * @deprecated in drupal:9.2.0 and is removed from drupal:10.0.0. Use
 *   hook_field_widget_complete_WIDGET_TYPE_form_alter instead.
 *
 * @see https://www.drupal.org/node/3180429
 * @see \Drupal\Core\Field\WidgetBaseInterface::form()
 * @see \Drupal\Core\Field\WidgetBase::formMultipleElements()
 * @see hook_field_widget_multivalue_form_alter()
+14 −14
Original line number Diff line number Diff line
@@ -98,36 +98,36 @@ function field_test_entity_display_build_alter(&$output, $context) {
}

/**
 * Implements hook_field_widget_form_alter().
 * Implements hook_field_widget_single_element_form_alter().
 */
function field_test_field_widget_form_alter(&$element, FormStateInterface $form_state, $context) {
function field_test_field_widget_single_element_form_alter(&$element, FormStateInterface $form_state, $context) {
  // Set a message if this is for the form displayed to set default value for
  // the field.
  if ($context['default']) {
    \Drupal::messenger()
      ->addStatus('From hook_field_widget_form_alter(): Default form is true.');
      ->addStatus('From hook_field_widget_single_element_form_alter(): Default form is true.');
  }
}

/**
 * Implements hook_field_widget_multivalue_form_alter().
 * Implements hook_field_widget_complete_form_alter().
 */
function field_test_field_widget_multivalue_form_alter(array &$elements, FormStateInterface $form_state, array $context) {
  _field_test_alter_widget("hook_field_widget_multivalue_form_alter", $elements, $form_state, $context);
function field_test_field_widget_complete_form_alter(array &$field_widget_complete_form, FormStateInterface $form_state, array $context) {
  _field_test_alter_widget("hook_field_widget_complete_form_alter", $field_widget_complete_form, $form_state, $context);
}

/**
 * Implements hook_field_widget_multivalue_WIDGET_TYPE_form_alter().
 * Implements hook_field_widget_complete_WIDGET_TYPE_form_alter().
 */
function field_test_field_widget_multivalue_test_field_widget_multiple_form_alter(array &$elements, FormStateInterface $form_state, array $context) {
  _field_test_alter_widget("hook_field_widget_multivalue_WIDGET_TYPE_form_alter", $elements, $form_state, $context);
function field_test_field_widget_complete_test_field_widget_multiple_form_alter(array &$field_widget_complete_form, FormStateInterface $form_state, array $context) {
  _field_test_alter_widget("hook_field_widget_complete_WIDGET_TYPE_form_alter", $field_widget_complete_form, $form_state, $context);
}

/**
 * Implements hook_field_widget_multivalue_WIDGET_TYPE_form_alter().
 * Implements hook_field_widget_complete_WIDGET_TYPE_form_alter().
 */
function field_test_field_widget_multivalue_test_field_widget_multiple_single_value_form_alter(array &$elements, FormStateInterface $form_state, array $context) {
  _field_test_alter_widget("hook_field_widget_multivalue_WIDGET_TYPE_form_alter", $elements, $form_state, $context);
function field_test_field_widget_complete_test_field_widget_multiple_single_value_form_alter(array &$field_widget_complete_form, FormStateInterface $form_state, array $context) {
  _field_test_alter_widget("hook_field_widget_complete_WIDGET_TYPE_form_alter", $field_widget_complete_form, $form_state, $context);
}

/**
@@ -135,8 +135,8 @@ function field_test_field_widget_multivalue_test_field_widget_multiple_single_va
 *
 * @see \Drupal\field\Tests\FormTest::widgetAlterTest()
 */
function _field_test_alter_widget($hook, array &$elements, FormStateInterface $form_state, array $context) {

function _field_test_alter_widget($hook, array &$field_widget_complete_form, FormStateInterface $form_state, array $context) {
  $elements = &$field_widget_complete_form['widget'];
  // Set a message if this is for the form displayed to set default value for
  // the field.
  if ($context['default']) {
+14 −14
Original line number Diff line number Diff line
@@ -126,12 +126,12 @@ public function testFieldFormSingle() {
    // Verify that no extraneous widget is displayed.
    $this->assertSession()->fieldNotExists("{$field_name}[1][value]");

    // Check that hook_field_widget_form_alter() does not believe this is the
    // default value form.
    $this->assertNoText('From hook_field_widget_form_alter(): Default form is true.');
    // Check that hook_field_widget_form_alter() does not believe this is the
    // default value form.
    $this->assertNoText('From hook_field_widget_multivalue_form_alter(): Default form is true.');
    // Check that hook_field_widget_single_element_form_alter() does not believe
    // this is the default value form.
    $this->assertNoText('From hook_field_widget_single_element_form_alter(): Default form is true.');
    // Check that hook_field_widget_single_element_form_alter() does not believe
    // this is the default value form.
    $this->assertNoText('From hook_field_widget_complete_form_alter(): Default form is true.');

    // Submit with invalid value (field-level validation).
    $edit = [
@@ -685,31 +685,31 @@ public function testLabelOnMultiValueFields() {
  }

  /**
   * Tests hook_field_widget_multivalue_form_alter().
   * Tests hook_field_widget_complete_form_alter().
   */
  public function testFieldFormMultipleWidgetAlter() {
    $this->widgetAlterTest('hook_field_widget_multivalue_form_alter', 'test_field_widget_multiple');
    $this->widgetAlterTest('hook_field_widget_complete_form_alter', 'test_field_widget_multiple');
  }

  /**
   * Tests hook_field_widget_multivalue_form_alter() with single value elements.
   * Tests hook_field_widget_complete_form_alter() with single value elements.
   */
  public function testFieldFormMultipleWidgetAlterSingleValues() {
    $this->widgetAlterTest('hook_field_widget_multivalue_form_alter', 'test_field_widget_multiple_single_value');
    $this->widgetAlterTest('hook_field_widget_complete_form_alter', 'test_field_widget_multiple_single_value');
  }

  /**
   * Tests hook_field_widget_multivalue_WIDGET_TYPE_form_alter().
   * Tests hook_field_widget_complete_WIDGET_TYPE_form_alter().
   */
  public function testFieldFormMultipleWidgetTypeAlter() {
    $this->widgetAlterTest('hook_field_widget_multivalue_WIDGET_TYPE_form_alter', 'test_field_widget_multiple');
    $this->widgetAlterTest('hook_field_widget_complete_WIDGET_TYPE_form_alter', 'test_field_widget_multiple');
  }

  /**
   * Tests hook_field_widget_multivalue_WIDGET_TYPE_form_alter() with single value elements.
   * Tests hook_field_widget_complete_WIDGET_TYPE_form_alter() with single value elements.
   */
  public function testFieldFormMultipleWidgetTypeAlterSingleValues() {
    $this->widgetAlterTest('hook_field_widget_multivalue_WIDGET_TYPE_form_alter', 'test_field_widget_multiple_single_value');
    $this->widgetAlterTest('hook_field_widget_complete_WIDGET_TYPE_form_alter', 'test_field_widget_multiple_single_value');
  }

  /**
Loading