function ValidKeysConstraintValidator::getDynamicMessageParameters

Same name and namespace in other branches
  1. 11.x core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/ValidKeysConstraintValidator.php \Drupal\Core\Validation\Plugin\Validation\Constraint\ValidKeysConstraintValidator::getDynamicMessageParameters()

Computes message parameters for dynamic type violations.

Parameters

\Drupal\Core\Config\Schema\Mapping $mapping: A `type: mapping` instance, with values.

Return value

array An array containing the following message parameters:

  • '@unresolved_dynamic_type': unresolved dynamic type
  • '@resolved_dynamic_type': resolved dynamic type
  • '@dynamic_type_property_path': (relative) property path of the condition
  • '@dynamic_type_property_value': value of the condition

See also

\Drupal\Core\Validation\Plugin\Validation\Constraint\ValidKeysConstraint::$dynamicInvalidKeyMessage

1 call to ValidKeysConstraintValidator::getDynamicMessageParameters()
ValidKeysConstraintValidator::validate in core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/ValidKeysConstraintValidator.php

File

core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/ValidKeysConstraintValidator.php, line 189

Class

ValidKeysConstraintValidator
Validates the ValidKeys constraint.

Namespace

Drupal\Core\Validation\Plugin\Validation\Constraint

Code

protected static function getDynamicMessageParameters(Mapping $mapping) : array {
  $definition = $mapping->getDataDefinition();
  assert($definition instanceof MapDataDefinition);
  $definition = $definition->toArray();
  assert(array_key_exists('mapping', $definition));
  // The original mapping definition is used to determine the unresolved type.
  // e.g. if $unresolved_type is …
  // 1. `editor.settings.[%parent.editor]`, then $resolved_type could perhaps
  //    `editor.settings.ckeditor5`, `editor.settings.unicorn`, etc.
  // 2. `block.settings.[%parent.plugin]`, then $resolved_type could perhaps
  //    be `block.settings.*`, `block.settings.system_branding_block`, etc.
  $parent_data_def = $mapping->getParent()
    ->getDataDefinition();
  $unresolved_type = match (TRUE) {  $parent_data_def instanceof MapDataDefinition => $parent_data_def->toArray()['mapping'][$mapping->getName()]['type'],
    $parent_data_def instanceof SequenceDataDefinition => $parent_data_def->toArray()['sequence']['type'],
    default => throw new \LogicException('Invalid config schema detected.'),
  
  };
  $resolved_type = $definition['type'];
  // $unresolved_type must be a dynamic type and the resolved type must be
  // different and not be dynamic.
  // @see \Drupal\Core\Config\TypedConfigManager::buildDataDefinition()
  assert(strpos($unresolved_type, ']'));
  assert($unresolved_type !== $resolved_type);
  assert(!strpos($resolved_type, ']'));
  $message_parameters = [
    '@unresolved_dynamic_type' => $unresolved_type,
    '@resolved_dynamic_type' => $resolved_type,
  ];
  $config = $mapping->getRoot();
  // Every config object is a mapping.
  assert($config instanceof Mapping);
  // Find the relative property path where this mapping starts.
  assert(str_starts_with($mapping->getPropertyPath(), $config->getName() . '.'));
  $property_path_mapping = substr($mapping->getPropertyPath(), strlen($config->getName()) + 1);
  // Extract the expressions stored in the dynamic type name.
  $matches = [];
  // @see \Drupal\Core\Config\TypedConfigManager::replaceDynamicTypeName()
  $result = preg_match("/\\[(.*)\\]/U", $unresolved_type, $matches);
  assert($result === 1);
  // @see \Drupal\Core\Config\TypedConfigManager::replaceExpression()
  $expression = $matches[1];
  // From the expression, extract the instructions for where to retrieve a value.
  $instructions = explode('.', $expression);
  // Determine the property path to the configuration key that has determined
  // this type.
  // @see \Drupal\Core\Config\TypedConfigManager::replaceExpression()
  $property_path_parts = explode('.', $property_path_mapping);
  // @see \Drupal\Core\Config\Schema\Mapping::getDynamicallyValidKeys()
  assert(!in_array('%type', $instructions, TRUE));
  // The %key instruction can only be used on its own. In this case, there is
  // no need to fetch a value, only the string that was used as the key is
  // responsible for determining the mapping type.
  if ($instructions === [
    '%key',
  ]) {
    $key = array_pop($property_path_parts);
    array_push($property_path_parts, '%key');
    $resolved_property_path = implode('.', $property_path_parts);
    return $message_parameters + [
      '@dynamic_type_property_path' => $resolved_property_path,
      '@dynamic_type_property_value' => $key,
    ];
  }
  // Do not replace variables, do not traverse the tree of data, but instead
  // resolve the property path that contains the value causing this particular
  // type to be selected.
  while ($instructions) {
    $instruction = array_shift($instructions);
    // Go up one level: remove the last part of the property path.
    if ($instruction === '%parent') {
      array_pop($property_path_parts);
    }
    else {
      array_push($property_path_parts, $instruction);
    }
  }
  $resolved_property_path = implode('.', $property_path_parts);
  $message_parameters += [
    '@dynamic_type_property_path' => $resolved_property_path,
  ];
  // Determine the corresponding value for that property path.
  $val = $config->get($resolved_property_path)
    ->getValue();
  // @see \Drupal\Core\Config\TypedConfigManager::replaceExpression()
  $val = is_bool($val) ? (int) $val : $val;
  return $message_parameters + [
    '@dynamic_type_property_value' => $val,
  ];
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.