trait SchemaCheckTrait

Same name in other branches
  1. 9 core/lib/Drupal/Core/Config/Schema/SchemaCheckTrait.php \Drupal\Core\Config\Schema\SchemaCheckTrait
  2. 10 core/lib/Drupal/Core/Config/Schema/SchemaCheckTrait.php \Drupal\Core\Config\Schema\SchemaCheckTrait
  3. 11.x core/lib/Drupal/Core/Config/Schema/SchemaCheckTrait.php \Drupal\Core\Config\Schema\SchemaCheckTrait

Provides a trait for checking configuration schema.

Hierarchy

3 files declare their use of SchemaCheckTrait
ConfigSchemaChecker.php in core/lib/Drupal/Core/Config/Development/ConfigSchemaChecker.php
SchemaCheckTestTrait.php in core/tests/Drupal/Tests/SchemaCheckTestTrait.php
SchemaCheckTraitTest.php in core/tests/Drupal/KernelTests/Core/Config/SchemaCheckTraitTest.php

File

core/lib/Drupal/Core/Config/Schema/SchemaCheckTrait.php, line 16

Namespace

Drupal\Core\Config\Schema
View source
trait SchemaCheckTrait {
    
    /**
     * The config schema wrapper object for the configuration object under test.
     *
     * @var \Drupal\Core\Config\Schema\Element
     */
    protected $schema;
    
    /**
     * The configuration object name under test.
     *
     * @var string
     */
    protected $configName;
    
    /**
     * Checks the TypedConfigManager has a valid schema for the configuration.
     *
     * @param \Drupal\Core\Config\TypedConfigManagerInterface $typed_config
     *   The TypedConfigManager.
     * @param string $config_name
     *   The configuration name.
     * @param array $config_data
     *   The configuration data, assumed to be data for a top-level config object.
     *
     * @return array|bool
     *   FALSE if no schema found. List of errors if any found. TRUE if fully
     *   valid.
     */
    public function checkConfigSchema(TypedConfigManagerInterface $typed_config, $config_name, $config_data) {
        // We'd like to verify that the top-level type is either config_base,
        // config_entity, or a derivative. The only thing we can really test though
        // is that the schema supports having langcode in it. So add 'langcode' to
        // the data if it doesn't already exist.
        if (!isset($config_data['langcode'])) {
            $config_data['langcode'] = 'en';
        }
        $this->configName = $config_name;
        if (!$typed_config->hasConfigSchema($config_name)) {
            return FALSE;
        }
        $this->schema = $typed_config->createFromNameAndData($config_name, $config_data);
        $errors = [];
        foreach ($config_data as $key => $value) {
            $errors = array_merge($errors, $this->checkValue($key, $value));
        }
        if (empty($errors)) {
            return TRUE;
        }
        return $errors;
    }
    
    /**
     * Helper method to check data type.
     *
     * @param string $key
     *   A string of configuration key.
     * @param mixed $value
     *   Value of given key.
     *
     * @return array
     *   List of errors found while checking with the corresponding schema.
     */
    protected function checkValue($key, $value) {
        $error_key = $this->configName . ':' . $key;
        $element = $this->schema
            ->get($key);
        if ($element instanceof Undefined) {
            return [
                $error_key => 'missing schema',
            ];
        }
        // Do not check value if it is defined to be ignored.
        if ($element && $element instanceof Ignore) {
            return [];
        }
        if ($element && is_scalar($value) || $value === NULL) {
            $success = FALSE;
            $type = gettype($value);
            if ($element instanceof PrimitiveInterface) {
                $success = $type == 'integer' && $element instanceof IntegerInterface || ($type == 'double' || $type == 'integer') && $element instanceof FloatInterface || $type == 'boolean' && $element instanceof BooleanInterface || $type == 'string' && $element instanceof StringInterface || $value === NULL;
            }
            elseif ($element instanceof ArrayElement && $element->isNullable() && $value === NULL) {
                $success = TRUE;
            }
            $class = get_class($element);
            if (!$success) {
                return [
                    $error_key => "variable type is {$type} but applied schema class is {$class}",
                ];
            }
        }
        else {
            $errors = [];
            if (!$element instanceof TraversableTypedDataInterface) {
                $errors[$error_key] = 'non-scalar value but not defined as an array (such as mapping or sequence)';
            }
            // Go on processing so we can get errors on all levels. Any non-scalar
            // value must be an array so cast to an array.
            if (!is_array($value)) {
                $value = (array) $value;
            }
            // Recurse into any nested keys.
            foreach ($value as $nested_value_key => $nested_value) {
                $errors = array_merge($errors, $this->checkValue($key . '.' . $nested_value_key, $nested_value));
            }
            return $errors;
        }
        // No errors found.
        return [];
    }

}

Members

Title Sort descending Modifiers Object type Summary
SchemaCheckTrait::$configName protected property The configuration object name under test.
SchemaCheckTrait::$schema protected property The config schema wrapper object for the configuration object under test.
SchemaCheckTrait::checkConfigSchema public function Checks the TypedConfigManager has a valid schema for the configuration.
SchemaCheckTrait::checkValue protected function Helper method to check data type.

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