You are here

protected function ComponentSectionForm::cleanUpValues in Module Builder 8.3

Recursively clean up the submitted form values.

Note that this is called by validateForm(), and so is run BEFORE any button-specific validators. This means that it can't rely on any action- specific clean up of values.

Parameters

array &$array: An array of form values, passed by reference. This will be altered in place.

\MutableTypedData\Data\DataItem $data: The data item that corresponds to the form values array.

2 calls to ComponentSectionForm::cleanUpValues()
ComponentSectionForm::copyFormValuesToEntity in src/Form/ComponentSectionForm.php
Copies top-level form values to entity properties
ComponentSectionForm::validateForm in src/Form/ComponentSectionForm.php
Form validation handler.

File

src/Form/ComponentSectionForm.php, line 1006

Class

ComponentSectionForm
Generic form for entering a section of data for a component.

Namespace

Drupal\module_builder\Form

Code

protected function cleanUpValues(&$array, DataItem $data) {

  // Clean up the data for the old variant if mutable data is having its
  // variant changed.
  if ($data
    ->isMutable() && !$data
    ->isMultiple()) {
    $variant_property_name = $data
      ->getVariantData()
      ->getName();
    if ($array[$variant_property_name] != $data
      ->getVariantData()->value) {

      // The variant property has been changed. Remove everything from the
      // array except for the variant property.
      $array = [
        $variant_property_name => $array[$variant_property_name],
      ];
    }
  }
  foreach ($array as $key => &$value) {

    // Remove buttons.
    if (substr($key, 0, 1) == ':') {
      unset($array[$key]);
      continue;
    }

    // Single checkbox.
    // TODO ARRRGH can't figure out how to safely get a child item in all
    // circumstances.
    // See https://github.com/joachim-n/mutable-typed-data/issues/3
    if (!is_numeric($key) && $data->{$key}
      ->getType() == 'boolean') {
      $array[$key] = (bool) $array[$key];
      continue;
    }

    // Remove empty values, so for example, empty checkboxes in a set don't
    // try to set an empty value on the data item.
    if (is_null($value)) {
      unset($array[$key]);
      continue;
    }

    // Remove empty mutable data. This means that we remove the empty option
    // during an AJAX call to add a delta to a multi-valued mutable item,
    // which can't be set on the data as a variant can't be set to an empty
    // value.
    // TODO: needs test coverage.
    if ($data
      ->isMutable()) {
      if (empty($value)) {
        unset($array[$key]);
        continue;
      }
    }
    if (is_array($value)) {
      if (is_numeric($key)) {
        $this
          ->cleanUpValues($value, $data[$key]);
      }
      elseif ($data->{$key}
        ->hasOptions()) {

        // We're dealing with checkboxes. Convert the keyed array to an numeric
        // array.
        $value = array_values(array_filter($value));
      }
      else {
        $this
          ->cleanUpValues($value, $data->{$key});
      }

      // If the value array is now empty (because recursively cleaning it has
      // removed all its keys), remove it.
      if (empty($value)) {
        unset($array[$key]);
      }

      // For FKW reasons, the form state values get order mixed up when
      // the variant type is set on an additional variant. The new value is
      // first in the array, which MTD won't accept because it expects deltas
      // to be in the correct order. Values are in the right order in
      // updateVariantSubmit(), but in the wrong order when
      // when copyFormValuesToEntity() is called.
      // I've given up figuring out why FormAPI does this so here is a hack
      // to fix the values.
      // See https://www.drupal.org/project/module_builder/issues/3173604
      if (!empty($value) && is_numeric(array_keys($value)[0])) {
        ksort($value);
      }
    }
    else {

      // Some single values need special handling too.
      // Handle a textarea.
      if ($data->{$key}
        ->isMultiple() && !$data->{$key}
        ->isComplex() && !$data->{$key}
        ->hasOptions()) {

        // Text area line breaks are weird, apparently.
        $values = preg_split("@[\r\n]+@", $value);
        $values = array_filter($values);
        $array[$key] = $values;
      }
      if (in_array($data->{$key}
        ->getName(), [
        'injected_services',
        'container_services',
        'mocked_services',
      ])) {

        // Form elements for injected services need special handling.
        $value = preg_split("@[,]+@", $value);
        $value = array_filter($value);
        $array[$key] = array_map('trim', $value);
      }
      elseif (!is_numeric($key) && $data->{$key}
        ->hasOptions() && !$data->{$key}
        ->isRequired()) {

        // Options elements that are not required should be cleaned up, so we
        // don't set an empty string as the data value.
        unset($array[$key]);
      }
    }
  }
}