function ComponentValidator::validateProps

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

Validates that the props provided to the component.

Valid props are compliant with the schema definition in the component metadata file.

Parameters

array $context: The Twig context that contains the prop data.

\Drupal\Core\Plugin\Component $component: The component to validate the props against.

Return value

bool TRUE if the props adhere to the component definition.

Throws

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

File

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

Class

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

Namespace

Drupal\Core\Theme\Component

Code

public function validateProps(array $context, Component $component) : bool {
    // If the validator isn't set, then the validation library is not installed.
    if (!$this->validator) {
        return TRUE;
    }
    $component_id = $component->getPluginId();
    $schema = $component->metadata->schema;
    if (!$schema) {
        if ($component->metadata->mandatorySchemas) {
            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.', $component_id));
        }
        return TRUE;
    }
    if (empty($schema['properties'])) {
        // If there are no properties in the schema there is nothing to validate.
        return TRUE;
    }
    $prop_names = array_keys($schema['properties']);
    $props_raw = array_intersect_key($context, array_flip($prop_names));
    // Validator::arrayToObjectRecursive stringifies the props using the JSON
    // encoder. Before that happens, we want to validate classes. Once the
    // classes are validated, we remove them as potential problems for the JSON
    // Schema validation.
    [
        $schema,
        $props_raw,
    ] = $this->validateClassProps($schema, $props_raw, $component_id);
    $schema = Validator::arrayToObjectRecursive($schema);
    $props = Validator::arrayToObjectRecursive($props_raw);
    $validator = new Validator();
    $validator->validate($props, $schema, Constraint::CHECK_MODE_TYPE_CAST);
    $validator->getErrors();
    if ($validator->isValid()) {
        return TRUE;
    }
    // Dismiss type errors if the prop received a render array.
    $errors = array_filter($validator->getErrors(), function (array $error) use ($context) : bool {
        if (($error['constraint'] ?? '') !== 'type') {
            return TRUE;
        }
        return !Element::isRenderArray($context[$error['property']] ?? NULL);
    });
    if (empty($errors)) {
        return TRUE;
    }
    $message_parts = array_map(static function (array $error) : string {
        // We check the error message instead of values and definitions here
        // because it's hard to access both given the possible complexity of a
        // schema. Since this is a small non critical DX improvement error
        // message checking should be sufficient.
        if (str_contains($error['message'], 'NULL value found, but a ')) {
            $error['message'] .= '. This may be because the property is empty instead of having data present. If possible fix the source data, use the |default() twig filter, or update the schema to allow multiple types.';
        }
        return sprintf("[%s] %s", $error['property'], $error['message']);
    }, $errors);
    $message = implode("/n", $message_parts);
    throw new InvalidComponentException($message);
}

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