function ComponentValidator::validateDefinition

Same name in this branch
  1. 10 core/modules/sdc/src/Component/ComponentValidator.php \Drupal\sdc\Component\ComponentValidator::validateDefinition()
Same name and namespace in other branches
  1. 11.x core/modules/sdc/src/Component/ComponentValidator.php \Drupal\sdc\Component\ComponentValidator::validateDefinition()
  2. 11.x core/lib/Drupal/Core/Theme/Component/ComponentValidator.php \Drupal\Core\Theme\Component\ComponentValidator::validateDefinition()

Validates the component metadata file.

A valid component metadata file can be validated against the metadata-author.schema.json, plus the ability of classes and interfaces in the `type` property.

Parameters

array $definition: The definition to validate.

bool $enforce_schemas: TRUE if schema definitions are mandatory.

Return value

bool TRUE if the component is valid.

Throws

\Drupal\Core\Render\Component\Exception\InvalidComponentException

File

core/lib/Drupal/Core/Theme/Component/ComponentValidator.php, line 55

Class

ComponentValidator
Validates a component based on its definition and the component schema.

Namespace

Drupal\Core\Theme\Component

Code

public function validateDefinition(array $definition, bool $enforce_schemas) : bool {
  // First ensure there are no name collisions between props and slots.
  $prop_names = array_keys($definition['props']['properties'] ?? []);
  $slot_names = array_keys($definition['slots'] ?? []);
  $collisions = array_intersect($prop_names, $slot_names);
  if ($collisions) {
    $message = sprintf('The component "%s" declared [%s] both as a prop and as a slot. Make sure to use different names.', $definition['id'], implode(', ', $collisions));
    throw new InvalidComponentException($message);
  }
  // If the validator isn't set, then the validation library is not installed.
  if (!$this->validator) {
    return TRUE;
  }
  // Detect the props with a type class, and validate that the class exists.
  $schema = $definition['props'] ?? NULL;
  if (!$schema) {
    if ($enforce_schemas) {
      throw new InvalidComponentException(sprintf('The component "%s" does not provide schema information. Schema definitions are mandatory for components declared in modules. For components declared in themes, schema definitions are only mandatory if the "enforce_prop_schemas" key is set to "true" in the theme info file.', $definition['id']));
    }
    return TRUE;
  }
  // If there are no props, force casting to object instead of array.
  if (($schema['properties'] ?? NULL) === []) {
    $schema['properties'] = new \stdClass();
  }
  $classes_per_prop = $this->getClassProps($schema);
  $missing_class_errors = [];
  foreach ($classes_per_prop as $prop_name => $class_types) {
    // For each possible type, check if it is a class.
    $missing_classes = array_filter($class_types, static fn(string $class) => !class_exists($class) && !interface_exists($class));
    $missing_class_errors = [
      $missing_class_errors,
      array_map(static fn(string $class) => sprintf('Unable to find class/interface "%s" specified in the prop "%s" for the component "%s".', $class, $prop_name, $definition['id']), $missing_classes),
    ];
  }
  // Remove the non JSON Schema types for validation down below.
  $definition['props'] = $this->nullifyClassPropsSchema($schema, $classes_per_prop);
  $definition_object = Validator::arrayToObjectRecursive($definition);
  $this->validator
    ->validate($definition_object, (object) [
    '$ref' => 'file://' . dirname(__DIR__, 5) . '/assets/schemas/v1/metadata-full.schema.json',
  ]);
  if (empty($missing_class_errors) && $this->validator
    ->isValid()) {
    return TRUE;
  }
  $message_parts = array_map(static fn(array $error): string => sprintf("[%s] %s", $error['property'], $error['message']), $this->validator
    ->getErrors());
  $message_parts = [
    $message_parts,
    $missing_class_errors,
  ];
  $message = implode("/n", $message_parts);
  // Throw the exception with the error message.
  throw new InvalidComponentException($message);
}

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