You are here

public function WebformEntityReferenceTrait::form in Webform 6.x

Same name and namespace in other branches
  1. 8.5 src/Plugin/WebformElement/WebformEntityReferenceTrait.php \Drupal\webform\Plugin\WebformElement\WebformEntityReferenceTrait::form()
1 method overrides WebformEntityReferenceTrait::form()
WebformTermReferenceTrait::form in src/Plugin/WebformElement/WebformTermReferenceTrait.php

File

src/Plugin/WebformElement/WebformEntityReferenceTrait.php, line 447

Class

WebformEntityReferenceTrait
Provides an 'entity_reference' trait.

Namespace

Drupal\webform\Plugin\WebformElement

Code

public function form(array $form, FormStateInterface $form_state) {
  $form = parent::form($form, $form_state);

  /**************************************************************************/

  // IMPORTANT: Most of the below code and #ajax tweaks compensate for the
  // fact that the EntityReferenceSelection plugin specifically targets
  // entity references managed via the Field API.
  // @see \Drupal\webform\Plugin\WebformElementBase::setConfigurationFormDefaultValueRecursive
  // @see \Drupal\webform\Plugin\WebformElementBase::buildConfigurationForm

  /**************************************************************************/

  // Get element properties.
  $element_properties = $form_state
    ->get('element_properties');

  // Alter element properties.
  if ($form_state
    ->isRebuilding()) {

    // Get entity reference value from user input because
    // $form_state->getValue() does not always contain every input's value.
    $user_input = $form_state
      ->getUserInput();
    $target_type = !empty($user_input['properties']['target_type']) ? $user_input['properties']['target_type'] : 'node';
    $selection_handler = !empty($user_input['properties']['selection_handler']) ? $user_input['properties']['selection_handler'] : 'default:' . $target_type;
    $selection_settings = !empty($user_input['properties']['selection_settings']) ? $user_input['properties']['selection_settings'] : [];

    // If the default selection handler has changed when need to update its
    // value.
    if (strpos($selection_handler, 'default:') === 0 && $selection_handler !== "default:{$target_type}") {
      $selection_handler = "default:{$target_type}";
      $selection_settings = [];
      NestedArray::setValue($form_state
        ->getUserInput(), [
        'properties',
        'selection_handler',
      ], $selection_handler);
      NestedArray::setValue($form_state
        ->getUserInput(), [
        'properties',
        'selection_settings',
      ], $selection_settings);
    }
  }
  else {

    // Set default #target_type and #selection_handler.
    if (empty($element_properties['target_type'])) {
      $element_properties['target_type'] = 'node';
    }
    if (empty($element_properties['selection_handler'])) {
      $element_properties['selection_handler'] = 'default:' . $element_properties['target_type'];
    }
    $target_type = $element_properties['target_type'];
    $selection_handler = $element_properties['selection_handler'];
    $selection_settings = $element_properties['selection_settings'];
  }

  // Set 'User' entity reference selection filter type role's #default_value
  // to an array and not NULL, which throws
  // "Warning: Invalid argument supplied for foreach()
  // in Drupal\Core\Render\Element\Checkboxes::valueCallback()"
  // @see \Drupal\user\Plugin\EntityReferenceSelection\UserSelection::buildConfigurationForm
  if ($target_type === 'user' && isset($selection_settings['filter']['type']) && $selection_settings['filter']['type'] === 'role' && empty($selection_settings['filter']['role'])) {
    $selection_settings['filter']['role'] = [];
  }

  // Reset element properties.
  $element_properties['target_type'] = $target_type;
  $element_properties['selection_handler'] = $selection_handler;
  $element_properties['selection_settings'] = $selection_settings;
  $form_state
    ->set('element_properties', $element_properties);

  /**************************************************************************/

  // @see \Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem
  $selection_plugins = $this->selectionManager
    ->getSelectionGroups($target_type);
  $handlers_options = [];
  foreach (array_keys($selection_plugins) as $selection_group_id) {
    if (array_key_exists($selection_group_id, $selection_plugins[$selection_group_id])) {
      $handlers_options[$selection_group_id] = Html::escape($selection_plugins[$selection_group_id][$selection_group_id]['label']);
    }
    elseif (array_key_exists($selection_group_id . ':' . $target_type, $selection_plugins[$selection_group_id])) {
      $selection_group_plugin = $selection_group_id . ':' . $target_type;
      $handlers_options[$selection_group_plugin] = Html::escape($selection_plugins[$selection_group_id][$selection_group_plugin]['base_plugin_label']);
    }
  }

  // Entity Reference fields are no longer supported to reference Paragraphs.
  // @see paragraphs_form_field_storage_config_edit_form_alter()
  $target_type_options = $this->entityTypeRepository
    ->getEntityTypeLabels(TRUE);
  unset($target_type_options[(string) $this
    ->t('Content')]['paragraph']);
  $form['entity_reference'] = [
    '#type' => 'fieldset',
    '#title' => $this
      ->t('Entity reference settings'),
    '#weight' => -40,
  ];

  // Target type.
  $form['entity_reference']['target_type'] = [
    '#type' => 'select',
    '#title' => $this
      ->t('Type of item to reference'),
    '#options' => $target_type_options,
    '#required' => TRUE,
    '#empty_option' => $this
      ->t('- Select a target type -'),
    '#default_value' => $target_type,
  ];

  // Selection handler.
  $form['entity_reference']['selection_handler'] = [
    '#type' => 'select',
    '#title' => $this
      ->t('Reference method'),
    '#options' => $handlers_options,
    '#required' => TRUE,
    '#default_value' => $selection_handler,
  ];

  // Selection settings.
  // Note: The below options are used to populate the #default_value for
  // selection settings.
  $entity_reference_selection_handler = $this->selectionManager
    ->getInstance([
    'target_type' => $target_type,
    'handler' => $selection_handler,
  ] + $selection_settings);
  $form['entity_reference']['selection_settings'] = $entity_reference_selection_handler
    ->buildConfigurationForm([], $form_state);
  $form['entity_reference']['selection_settings']['#tree'] = TRUE;

  // Remove the no-ajax submit button because we are not using the
  // EntityReferenceSelection with in Field API.
  unset($form['entity_reference']['selection_settings']['target_bundles_update']);

  // Remove auto create, except for entity_autocomplete.
  if ($this
    ->getPluginId() !== 'entity_autocomplete' || $target_type !== 'taxonomy_term') {
    unset($form['entity_reference']['selection_settings']['auto_create'], $form['entity_reference']['selection_settings']['auto_create_bundle']);
  }

  // Add hide/show #format_items based on #tags.
  if ($this
    ->supportsMultipleValues() && $this
    ->hasProperty('tags')) {
    $form['display']['format_items']['#states'] = [
      'visible' => [
        [
          ':input[name="properties[tags]"]' => [
            'checked' => TRUE,
          ],
        ],
      ],
    ];
  }

  // Apply ajax handling.
  $ajax_id = 'webform-entity-reference';
  $this
    ->buildAjaxElementWrapper($ajax_id, $form['entity_reference']);
  $this
    ->buildAjaxElementUpdate($ajax_id, $form['entity_reference']);
  $this
    ->buildAjaxElementTrigger($ajax_id, $form['entity_reference']['target_type']);
  $this
    ->buildAjaxElementTrigger($ajax_id, $form['entity_reference']['selection_handler']);
  $this
    ->buildAjaxElementTriggerRecursive($ajax_id, $form['entity_reference']['selection_settings']);

  // Tags (only applies to 'entity_autocomplete' element).
  $form['element']['tags'] = [
    '#type' => 'checkbox',
    '#title' => $this
      ->t('Tags'),
    '#description' => $this
      ->t('Check this option if the user should be allowed to enter multiple entity references using tags.'),
    '#return_value' => TRUE,
  ];
  if ($this
    ->hasProperty('tags') && $this
    ->hasProperty('multiple')) {
    $form['element']['multiple']['#states'] = [
      'disabled' => [
        ':input[name="properties[tags]"]' => [
          'checked' => TRUE,
        ],
      ],
    ];
    $form['element']['multiple__header_container']['#states']['visible'][] = [
      ':input[name="properties[tags]"]' => [
        'checked' => FALSE,
      ],
    ];
    $form['element']['tags']['#states'] = [
      'visible' => [
        ':input[name="properties[multiple][container][cardinality]"]' => [
          '!value' => -1,
        ],
        ':input[name="properties[multiple][container][cardinality_number]"]' => [
          'value' => 1,
        ],
      ],
    ];
  }

  // Disable tags in multiple is disabled.
  if (!empty($form['element']['multiple']['#disabled'])) {
    $form['element']['tags']['#disabled'] = $form['element']['multiple']['#disabled'];
    $form['element']['tags']['#description'] = $form['element']['multiple']['#description'];
  }
  return $form;
}