function TypedConfigManager::buildDataDefinition

Same name in other branches
  1. 9 core/lib/Drupal/Core/Config/TypedConfigManager.php \Drupal\Core\Config\TypedConfigManager::buildDataDefinition()
  2. 8.9.x core/lib/Drupal/Core/Config/TypedConfigManager.php \Drupal\Core\Config\TypedConfigManager::buildDataDefinition()
  3. 11.x core/lib/Drupal/Core/Config/TypedConfigManager.php \Drupal\Core\Config\TypedConfigManager::buildDataDefinition()
1 call to TypedConfigManager::buildDataDefinition()
TypedConfigManager::createFromNameAndData in core/lib/Drupal/Core/Config/TypedConfigManager.php

File

core/lib/Drupal/Core/Config/TypedConfigManager.php, line 93

Class

TypedConfigManager
Manages config schema type plugins.

Namespace

Drupal\Core\Config

Code

public function buildDataDefinition(array $definition, $value, $name = NULL, $parent = NULL) {
    // Add default values for data type and replace variables.
    $definition += [
        'type' => 'undefined',
    ];
    $replace = [];
    $type = $definition['type'];
    if (strpos($type, ']')) {
        // Replace variable names in definition.
        $replace = is_array($value) ? $value : [];
        if (isset($parent)) {
            $replace['%parent'] = $parent;
        }
        if (isset($name)) {
            $replace['%key'] = $name;
        }
        $type = TypeResolver::resolveDynamicTypeName($type, $replace);
        // Remove the type from the definition so that it is replaced with the
        // concrete type from schema definitions.
        unset($definition['type']);
    }
    // Add default values from type definition.
    $definition += $this->getDefinitionWithReplacements($type, $replace);
    $data_definition = $this->createDataDefinition($definition['type']);
    // Pass remaining values from definition array to data definition.
    foreach ($definition as $key => $value) {
        if (!isset($data_definition[$key])) {
            $data_definition[$key] = $value;
        }
    }
    // All values are optional by default (meaning they can be NULL), except for
    // mappings and sequences. A sequence can only be NULL when `nullable: true`
    // is set on the config schema type definition. This is unintuitive and
    // contradicts Drupal core's documentation.
    // @see https://www.drupal.org/node/2264179
    // @see https://www.drupal.org/node/1978714
    // To gradually evolve configuration schemas in the Drupal ecosystem to be
    // validatable, this needs to be clarified in a non-disruptive way. Any
    // config schema type definition — that is, a top-level entry in a
    // *.schema.yml file — can opt into stricter behavior, whereby a property
    // cannot be NULL unless it specifies `nullable: true`, by adding
    // `FullyValidatable` as a top-level validation constraint.
    // @see https://www.drupal.org/node/3364108
    // @see https://www.drupal.org/node/3364109
    // @see \Drupal\Core\TypedData\TypedDataManager::getDefaultConstraints()
    if ($parent) {
        $root_type = $parent->getRoot()
            ->getDataDefinition()
            ->getDataType();
        $root_type_has_opted_in = FALSE;
        foreach ($parent->getRoot()
            ->getConstraints() as $constraint) {
            if ($constraint instanceof FullyValidatableConstraint) {
                $root_type_has_opted_in = TRUE;
                break;
            }
        }
        // If this is a dynamically typed property path, then not only must the
        // (absolute) root type be considered, but also the (relative) static root
        // type: the resolved type.
        // For example, `block.block.*:settings` has a dynamic type defined:
        // `block.settings.[%parent.plugin]`, but `block.block.*:plugin` does not.
        // Consequently, the value at the `plugin` property path depends only on
        // the `block.block.*` config schema type and hence only that config
        // schema type must have the `FullyValidatable` constraint, because it
        // defines which value are required.
        // In contrast, the `block.block.*:settings` property path depends on
        // whichever dynamic type `block.settings.[%parent.plugin]` resolved to,
        // to be able to know which values are required. Therefore that resolved
        // type determines which values are required and whether it is fully
        // validatable.
        // So for example the `block.settings.system_branding_block` config schema
        // type would also need to have the `FullyValidatable` constraint to
        // consider its schema-defined keys to require values:
        // - use_site_logo
        // - use_site_name
        // - use_site_slogan
        $static_type_root = TypedConfigManager::getStaticTypeRoot($parent);
        $static_type_root_type = $static_type_root->getDataDefinition()
            ->getDataType();
        if ($root_type !== $static_type_root_type) {
            $root_type_has_opted_in = FALSE;
            foreach ($static_type_root->getConstraints() as $c) {
                if ($c instanceof FullyValidatableConstraint) {
                    $root_type_has_opted_in = TRUE;
                    break;
                }
            }
        }
        if ($root_type_has_opted_in) {
            $data_definition->setRequired(!isset($data_definition['nullable']) || $data_definition['nullable'] === FALSE);
        }
    }
    return $data_definition;
}

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