Commit a89d7c33 authored by Marcos Cano's avatar Marcos Cano 💬
Browse files

Issue #3268790 by marcoscano: Skip widgets that don't render multiple values as a table

parent f4eec7cc
Loading
Loading
Loading
Loading
+81 −36
Original line number Diff line number Diff line
@@ -14,16 +14,35 @@ use Drupal\Core\Field\WidgetInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element;

/**
 * Widget IDs that can be simplified with the SAM module.
 */
const SAM_ALLOWED_WIDGET_TYPES = [
  'email_default',
  'entity_reference_autocomplete',
  'link_default',
  'number',
  'path',
  'string_textarea',
  'string_textfield',
  'telephone',
  'uri',
];

/**
 * Implements hook_field_widget_multivalue_form_alter().
 */
function sam_field_widget_multivalue_form_alter(array &$elements, FormStateInterface $form_state, array $context) {
  // Affect all multi-value widgets where cardinality is limited and > 1.
  if (!empty($context['items']) && !empty($elements['#cardinality']) && $elements['#cardinality'] > 1) {
    // Skip simplifying this if the widget was configured to show all elements.
    $widget = $context['widget'];
  $widget = $context['widget'] ?? NULL;
  assert($widget instanceof WidgetBaseInterface);
    if ($widget->getThirdPartySetting('sam', 'skip_simplification', FALSE)) {
  $field_definition = $context['items']->getFieldDefinition() ?? NULL;
  assert($field_definition instanceof FieldDefinitionInterface);
  if (empty($widget) || empty($field_definition)) {
    return;
  }
  // Abort early if this is a widget whose markup we can't simplify, or if the
  // field cardinality isn't limited > 1.
  if (sam_skip_widget($widget, $field_definition)) {
    return;
  }
  $items = $context['items'];
@@ -51,7 +70,6 @@ function sam_field_widget_multivalue_form_alter(array &$elements, FormStateInter
    $elements['#attributes']['data-sam-wrapper-simplify'] = TRUE;
  }
}
}

/**
 * Implements hook_preprocess_HOOK() for field_multiple_value_form().
@@ -77,11 +95,7 @@ function sam_preprocess_field_multiple_value_form(&$variables) {
 */
function sam_field_widget_third_party_settings_form(WidgetInterface $plugin, FieldDefinitionInterface $field_definition, $form_mode, array $form, FormStateInterface $form_state) {
  $element = [];
  $cardinality = $field_definition->getFieldStorageDefinition()->getCardinality();
  // @todo Is this too aggressive? We are adding this setting to all widgets,
  // even if they don't display as a table. Maybe it's a good idea to figure
  // that out and only display this checkbox where we can actually simplify.
  if ($cardinality > 1) {
  if (!sam_skip_widget($plugin, $field_definition)) {
    $element['skip_simplification'] = [
      '#type' => 'checkbox',
      '#title' => t('Skip "Simple Add More" simplification (i.e. show all elements, even if empty).'),
@@ -90,3 +104,34 @@ function sam_field_widget_third_party_settings_form(WidgetInterface $plugin, Fie
  }
  return $element;
}

/**
 * Helper to decide if our code should affect a widget/field.
 *
 * @param \Drupal\Core\Field\WidgetInterface $widget_plugin
 *   The widget plugin instance.
 * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
 *   The field definition object.
 *
 * @return bool
 *   TRUE (meaning we should skip this field/widget) if:
 *   - The cardinality is not > 1, or
 *   - The widget has been explicitly marked to be skipped in the settings, or
 *   - The widget is not one of the ones we can simplify, due to its markup.
 *   FALSE in all other cases.
 */
function sam_skip_widget(WidgetInterface $widget_plugin, FieldDefinitionInterface $field_definition) {
  $cardinality = $field_definition->getFieldStorageDefinition()->getCardinality();
  if ($cardinality <= 1) {
    return TRUE;
  }
  if ($widget_plugin->getThirdPartySetting('sam', 'skip_simplification', FALSE)) {
    return TRUE;
  }
  // @todo For now the most robust approach is just to explicitly stick to the
  // ones we know we can simplify.
  if (!in_array($widget_plugin->getPluginId(), SAM_ALLOWED_WIDGET_TYPES, TRUE)) {
    return TRUE;
  }
  return FALSE;
}