You are here

public static function ConditionalFieldsFormHelper::dependentValidate in Conditional Fields 8

Same name and namespace in other branches
  1. 4.x src/ConditionalFieldsFormHelper.php \Drupal\conditional_fields\ConditionalFieldsFormHelper::dependentValidate()

Dependent field validation callback.

If the dependencies of a dependent field are not triggered, the validation errors that it might have thrown must be removed, together with its submitted values. This will simulate the field not being present in the form at all. In this field-level callback we just collect needed information and store it in $form_state. Values and errors will be removed in a single sweep in formValidate(), which runs at the end of the validation cycle.

See also

\Drupal\conditional_fields\ConditionalFieldsFormHelper::formValidate()

File

src/ConditionalFieldsFormHelper.php, line 316

Class

ConditionalFieldsFormHelper
Helper to interact with forms.

Namespace

Drupal\conditional_fields

Code

public static function dependentValidate($element, FormStateInterface &$form_state, $form) {
  if (!isset($form['#conditional_fields'])) {
    return;
  }
  $dependent = $form['#conditional_fields'][reset($element['#array_parents'])];

  // Check if this field's dependencies were triggered.
  $triggered = self::evaluateDependencies($dependent, $form, $form_state);
  $return = FALSE;

  // TODO: refactor this!
  if ($evaluated_dependencies = self::evaluateDependencies($dependent, $form, $form_state, FALSE)) {
    foreach ($evaluated_dependencies[reset($dependent['field_parents'])] as $operator) {
      foreach ($operator as $state => $result) {
        if ($result && $state == 'visible' && $triggered || !$result && $state == '!visible' && !$triggered) {
          $return = TRUE;
        }
        if ($result && $state == 'required' && $triggered || !$result && $state == '!required' && !$triggered) {
          $return = TRUE;
          $key_exists = NULL;
          $input_state = NestedArray::getValue($form_state
            ->getValues(), $dependent['field_parents'], $key_exists);
          if ($key_exists && !is_object($input_state) && isset($input_state['add_more'])) {

            // Remove the 'value' of the 'add more' button.
            unset($input_state['add_more']);
          }
          $input_state = is_null($input_state) ? [] : $input_state;
          if (isset($dependent['field_parents'][0])) {
            $field = FieldStorageConfig::loadByName($form['#entity_type'], $dependent['field_parents'][0]);
          }
          else {
            $field = null;
          }
          if (empty($input_state)) {
            if (isset($element['widget']['#title'])) {
              $title = $element['widget']['#title'];
            }
            elseif (isset($dependent['field_parents'][0])) {
              $title = $dependent['field_parents'][0];
            }
            elseif ($field) {
              $title = $field
                ->getName();
            }
            $form_state
              ->setError($element, t('%name is required.', [
              '%name' => $title,
            ]));
          }
        }
      }
    }
  }
  if ($return) {
    return;
  }

  // Mark submitted values for removal. We have to remove them after all fields
  // have been validated to avoid collision between dependencies.
  $form_state_addition['parents'] = $dependent['field_parents'];

  // Optional behavior: reset the field to its default values.
  // Default values are always valid, so it's safe to skip validation.
  if (!empty($element['#conditional_fields_reset_if_untriggered']) && !$triggered) {
    $form_state_addition['reset'] = TRUE;
  }

  // Tag validation errors previously set on this field for removal in
  // ConditionalFieldsFormHelper::formValidate().
  $errors = $form_state
    ->getErrors();
  if ($errors) {
    $error_key = reset($dependent['field_parents']);
    foreach ($errors as $name => $error) {

      // An error triggered by this field might have been set on a descendant
      // element. This also means that so there can be multiple errors on the
      // same field (even though Drupal doesn't support multiple errors on the
      // same element).
      if (strpos((string) $name, $error_key) === 0) {
        $field_errors[$name] = $error;
      }
    }
  }
  if (!empty($field_errors)) {
    $form_state_addition['errors'] = $field_errors;
  }
  $fiel_state_values_count = count($form_state
    ->getValue('conditional_fields_untriggered_dependents'));
  $form_state
    ->setValue([
    'conditional_fields_untriggered_dependents',
    $fiel_state_values_count,
  ], $form_state_addition);
}