You are here

public function InlineEntityFormComplex::extractFormValues in Inline Entity Form 8

Extracts field values from submitted form values.

Parameters

\Drupal\Core\Field\FieldItemListInterface $items: The field values. This parameter is altered by reference to receive the incoming form values.

array $form: The form structure where field elements are attached to. This might be a full form structure, or a sub-element of a larger form.

\Drupal\Core\Form\FormStateInterface $form_state: The form state.

Overrides WidgetBase::extractFormValues

File

src/Plugin/Field/FieldWidget/InlineEntityFormComplex.php, line 586

Class

InlineEntityFormComplex
Complex inline widget.

Namespace

Drupal\inline_entity_form\Plugin\Field\FieldWidget

Code

public function extractFormValues(FieldItemListInterface $items, array $form, FormStateInterface $form_state) {
  if ($this
    ->isDefaultValueWidget($form_state)) {
    $items
      ->filterEmptyItems();
    return;
  }
  $triggering_element = $form_state
    ->getTriggeringElement();
  if (empty($triggering_element['#ief_submit_trigger'])) {
    return;
  }
  $field_name = $this->fieldDefinition
    ->getName();
  $parents = array_merge($form['#parents'], [
    $field_name,
    'form',
  ]);
  $ief_id = $this
    ->makeIefId($parents);
  $this
    ->setIefId($ief_id);
  $widget_state =& $form_state
    ->get([
    'inline_entity_form',
    $ief_id,
  ]);
  foreach ($widget_state['entities'] as $key => $value) {
    $changed = TranslationHelper::updateEntityLangcode($value['entity'], $form_state);
    if ($changed) {
      $widget_state['entities'][$key]['entity'] = $value['entity'];
      $widget_state['entities'][$key]['needs_save'] = TRUE;
    }
  }
  $values = $widget_state['entities'];

  // If the inline entity form is still open, then its entity hasn't
  // been transferred to the IEF form state yet.
  if (empty($values) && !empty($widget_state['form'])) {
    if ($widget_state['form'] == 'add') {
      $element = NestedArray::getValue($form, [
        $field_name,
        'widget',
        'form',
      ]);
      $entity = $element['inline_entity_form']['#entity'];
      $values[] = [
        'entity' => $entity,
      ];
    }
    elseif ($widget_state['form'] == 'ief_add_existing') {
      $parent = NestedArray::getValue($form, [
        $field_name,
        'widget',
        'form',
      ]);
      $element = isset($parent['entity_id']) ? $parent['entity_id'] : [];
      if (!empty($element['#value'])) {
        $options = [
          'target_type' => $element['#target_type'],
          'handler' => $element['#selection_handler'],
        ] + $element['#selection_settings'];

        /** @var \Drupal\Core\Entity\EntityReferenceSelection\SelectionInterface $handler */
        $handler = $this->selectionManager
          ->getInstance($options);
        $input_values = $element['#tags'] ? Tags::explode($element['#value']) : [
          $element['#value'],
        ];
        foreach ($input_values as $input) {
          $match = EntityAutocomplete::extractEntityIdFromAutocompleteInput($input);
          if ($match === NULL) {

            // Try to get a match from the input string when the user didn't use
            // the autocomplete but filled in a value manually.
            $entities_by_bundle = $handler
              ->getReferenceableEntities($input, '=');
            $entities = array_reduce($entities_by_bundle, function ($flattened, $bundle_entities) {
              return $flattened + $bundle_entities;
            }, []);
            $params = [
              '%value' => $input,
              '@value' => $input,
            ];
            if (empty($entities)) {
              $form_state
                ->setError($element, $this
                ->t('There are no entities matching "%value".', $params));
            }
            elseif (count($entities) > 5) {
              $params['@id'] = key($entities);

              // Error if there are more than 5 matching entities.
              $form_state
                ->setError($element, $this
                ->t('Many entities are called %value. Specify the one you want by appending the id in parentheses, like "@value (@id)".', $params));
            }
            elseif (count($entities) > 1) {

              // More helpful error if there are only a few matching entities.
              $multiples = [];
              foreach ($entities as $id => $name) {
                $multiples[] = $name . ' (' . $id . ')';
              }
              $params['@id'] = $id;
              $form_state
                ->setError($element, $this
                ->t('Multiple entities match this reference; "%multiple". Specify the one you want by appending the id in parentheses, like "@value (@id)".', [
                '%multiple' => implode('", "', $multiples),
              ] + $params));
            }
            else {

              // Take the one and only matching entity.
              $values += [
                'target_id' => key($entities),
              ];
            }
          }
          else {
            $values += [
              'target_id' => $match,
            ];
          }
        }
      }
    }
  }

  // Sort values by weight.
  uasort($values, '\\Drupal\\Component\\Utility\\SortArray::sortByWeightElement');

  // Let the widget massage the submitted values.
  $values = $this
    ->massageFormValues($values, $form, $form_state);

  // Assign the values and remove the empty ones.
  $items
    ->setValue($values);
  $items
    ->filterEmptyItems();
}