function ComponentValidator::validateDefinition
Same name in this branch
- 10 core/lib/Drupal/Core/Theme/Component/ComponentValidator.php \Drupal\Core\Theme\Component\ComponentValidator::validateDefinition()
Same name in other branches
- 11.x core/modules/sdc/src/Component/ComponentValidator.php \Drupal\sdc\Component\ComponentValidator::validateDefinition()
- 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\sdc\Exception\InvalidComponentException
File
-
core/
modules/ sdc/ src/ Component/ ComponentValidator.php, line 57
Class
- ComponentValidator
- Validates a component based on its definition and the component schema.
Namespace
Drupal\sdc\ComponentCode
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__) . '/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.