You are here

protected static function ConditionalFieldsFormHelper::evaluateDependency in Conditional Fields 8

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

Evaluate if a dependency meets the requirements to be triggered.

Parameters

string $context: Options: 'edit' if $values are extracted from $form_state. 'view' if $values are extracted from an entity.

Return value

bool Can the dependency be triggered?

1 call to ConditionalFieldsFormHelper::evaluateDependency()
ConditionalFieldsFormHelper::evaluateDependencies in src/ConditionalFieldsFormHelper.php
Evaluate a set of dependencies for a dependent field.

File

src/ConditionalFieldsFormHelper.php, line 576

Class

ConditionalFieldsFormHelper
Helper to interact with forms.

Namespace

Drupal\conditional_fields

Code

protected static function evaluateDependency($context, $values, $options) {
  if ($options['values_set'] == ConditionalFieldsInterface::CONDITIONAL_FIELDS_DEPENDENCY_VALUES_WIDGET) {
    $dependency_values = $context == 'view' ? $options['value'] : $options['value_form'];
    if ($options['condition'] === '!empty') {
      $values = isset($values[0]['value']) ? $values[0]['value'] : $values;
      $values = $values === '_none' ? '' : $values;
      return !empty($values) ? TRUE : FALSE;
    }
    if ($options['condition'] === 'empty') {
      $values = isset($values[0]['value']) ? $values[0]['value'] : $values;
      $values = $values === '_none' ? '' : $values;
      return empty($values) ? TRUE : FALSE;
    }

    // The BooleanList widget provides an empty array as $dependency_values,
    // thus checking this field requires a different handling in case of
    // 'checked or '!checked' conditions, where $value has 0 or 1.
    if ($options['condition'] === 'checked' || $options['condition'] === '!checked') {
      $dependency_values = (int) ($options['condition'] === 'checked');
    }

    // Simple case: both values are strings or integers. Should never happen in
    // view context, but does no harm to check anyway.
    if (!is_array($values) || is_array($values) && empty($values)) {

      // Options elements consider "_none" value same as empty.
      $values = $values === '_none' ? '' : $values;
      if (!is_array($dependency_values)) {

        // Some widgets store integers, but values saved in $dependency_values
        // are always strings. Convert them to integers because we want to do a
        // strict equality check to differentiate empty strings from '0'.
        if (is_int($values) && is_numeric($dependency_values)) {
          $dependency_values = (int) $dependency_values;
        }
        return $dependency_values === $values;
      }

      // If $values is a string and $dependency_values an array, convert $values
      // to the standard field array form format. This covers cases like single
      // value textfields.
      $values = [
        [
          'value' => $values,
        ],
      ];
    }

    // If we are in form context, we are almost done.
    if ($context == 'edit') {

      // If $dependency_values is not an array, we can only assume that it
      // should map to the first key of the first value of $values.
      if (!is_array($dependency_values)) {
        if (is_null(current($values)) || empty($options['value'][0])) {
          return FALSE;
        }
        $key = current(array_keys((array) current($values)));
        $dependency_values = [
          [
            $key => $options['value'][0][$key],
          ],
        ];
        $temp[][$key] = $values[0][$key];
        $values = $temp;
      }

      // Compare arrays recursively ignoring keys, since multiple select widgets
      // values have numeric keys in form format and string keys in storage
      // format.
      return array_values($dependency_values) == array_values($values);
    }

    // $values, when viewing fields, may contain all sort of additional
    // information, so filter out from $values the keys that are not present in
    // $dependency_values.
    // Values here are alway keyed by delta (regardless of multiple value
    // settings).
    foreach ($values as $delta => &$value) {
      if (isset($dependency_values[$delta])) {
        $value = array_intersect_key($value, $dependency_values[$delta]);
        foreach ($value as $key => &$element_value) {
          if (isset($dependency_values[$delta][$key]) && is_int($dependency_values[$delta][$key]) && is_numeric($element_value)) {
            $element_value = (int) $element_value;
          }
        }
      }
    }

    // Compare values.
    foreach ($dependency_values as $delta => $dependency_value) {
      if (!isset($values[$delta])) {
        return FALSE;
      }
      foreach ($dependency_value as $key => $dependency_element_value) {

        // Ignore keys set in the field and not in the dependency.
        if (isset($values[$delta][$key]) && $values[$delta][$key] !== $dependency_element_value) {
          return FALSE;
        }
      }
    }
    return TRUE;
  }

  // Flatten array of values.
  $reference_values = [];
  foreach ((array) $values as $value) {

    // TODO: support multiple values.
    $reference_values[] = is_array($value) ? array_shift($value) : $value;
  }

  // Regular expression method.
  if ($options['values_set'] == ConditionalFieldsInterface::CONDITIONAL_FIELDS_DEPENDENCY_VALUES_REGEX) {
    foreach ($reference_values as $reference_value) {
      if (!preg_match('/' . $options['regex'] . '/', $reference_value)) {
        return FALSE;
      }
    }
    return TRUE;
  }
  if (!empty($options['values']) && is_string($options['values'])) {
    $options['values'] = explode("\r\n", $options['values']);
  }
  switch ($options['values_set']) {
    case ConditionalFieldsInterface::CONDITIONAL_FIELDS_DEPENDENCY_VALUES_AND:
      $diff = array_diff($options['values'], $reference_values);
      return empty($diff);
    case ConditionalFieldsInterface::CONDITIONAL_FIELDS_DEPENDENCY_VALUES_OR:
      $intersect = array_intersect($options['values'], $reference_values);
      return !empty($intersect);
    case ConditionalFieldsInterface::CONDITIONAL_FIELDS_DEPENDENCY_VALUES_XOR:
      $intersect = array_intersect($options['values'], $reference_values);
      return count($intersect) == 1;
    case ConditionalFieldsInterface::CONDITIONAL_FIELDS_DEPENDENCY_VALUES_NOT:
      $intersect = array_intersect($options['values'], $reference_values);
      return empty($intersect);
  }
  return TRUE;
}