diff --git a/core/lib/Drupal/Core/Config/TypedConfigManager.php b/core/lib/Drupal/Core/Config/TypedConfigManager.php index c025a20..2416947 100644 --- a/core/lib/Drupal/Core/Config/TypedConfigManager.php +++ b/core/lib/Drupal/Core/Config/TypedConfigManager.php @@ -81,7 +81,8 @@ public function buildDataDefinition(array $definition, $value, $name = NULL, $pa // Add default values for data type and replace variables. $definition += array('type' => 'undefined'); - if (strpos($definition['type'], ']')) { + $type = $definition['type']; + if (strpos($type, ']')) { // Replace variable names in definition. $replace = is_array($value) ? $value : array(); if (isset($parent)) { @@ -90,10 +91,13 @@ public function buildDataDefinition(array $definition, $value, $name = NULL, $pa if (isset($name)) { $replace['%key'] = $name; } - $definition['type'] = $this->replaceName($definition['type'], $replace); + $type = $this->replaceName($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->getDefinition($definition['type']); + $definition += $this->getDefinition($type); $data_definition = $this->createDataDefinition($definition['type']); @@ -147,15 +151,16 @@ public function clearCachedDefinitions() { } /** - * Gets fallback metadata name. + * Gets fallback configuration schema name. * * @param string $name * Configuration name or key. * * @return null|string - * Same name with the last part(s) replaced by the filesystem marker. - * for example, breakpoint.breakpoint.module.toolbar.narrow check for - * definition in below order: + * The resolved schema name for the given configuration name or key. Returns + * null if there is no schema name to fallback to. For example, + * breakpoint.breakpoint.module.toolbar.narrow will check for definitions in + * the following order: * breakpoint.breakpoint.module.toolbar.* * breakpoint.breakpoint.module.*.* * breakpoint.breakpoint.module.* @@ -163,12 +168,18 @@ public function clearCachedDefinitions() { * breakpoint.breakpoint.* * breakpoint.*.*.*.* * breakpoint.* - * Returns null, if no matching element. + * Colons are also used, for example, + * block.settings.system_menu_block:footer will check for definitions in the + * following order: + * block.settings.system_menu_block* + * block.settings.* + * block.*.* + * block.* */ protected function getFallbackName($name) { // Check for definition of $name with filesystem marker. - $replaced = preg_replace('/(\.[^\.]+)([\.\*]*)$/', '.*\2', $name); - if ($replaced != $name ) { + $replaced = preg_replace('/:?([^\.:]+)([\.:\*]*)$/', '*\2', $name); + if ($replaced != $name) { if (isset($this->definitions[$replaced])) { return $replaced; } diff --git a/core/modules/config/src/Tests/ConfigSchemaTest.php b/core/modules/config/src/Tests/ConfigSchemaTest.php index 7401247..5e8f47b 100644 --- a/core/modules/config/src/Tests/ConfigSchemaTest.php +++ b/core/modules/config/src/Tests/ConfigSchemaTest.php @@ -397,4 +397,37 @@ function testSchemaFallback() { $this->assertIdentical($definition, $definition2); } + /** + * Tests use of colons in schema type determination. + * + * @see \Drupal\Core\Config\TypedConfigManager::getFallbackName() + */ + function testColonsInSchemaTypeDetermination() { + $tests = \Drupal::service('config.typed')->get('config_schema_test.plugin_types')->get('tests'); + $definition = $tests[0]->getDataDefinition()->toArray(); + $this->assertEqual($definition['type'], 'test.plugin_types.boolean'); + + $definition = $tests[1]->getDataDefinition()->toArray(); + $this->assertEqual($definition['type'], 'test.plugin_types.boolean*'); + + $definition = $tests[2]->getDataDefinition()->toArray(); + $this->assertEqual($definition['type'], 'test.plugin_types.*'); + + $definition = $tests[3]->getDataDefinition()->toArray(); + $this->assertEqual($definition['type'], 'test.plugin_types.*'); + + $tests = \Drupal::service('config.typed')->get('config_schema_test.plugin_types')->get('test_with_parents'); + $definition = $tests[0]['settings']->getDataDefinition()->toArray(); + $this->assertEqual($definition['type'], 'test_with_parents.plugin_types.boolean'); + + $definition = $tests[1]['settings']->getDataDefinition()->toArray(); + $this->assertEqual($definition['type'], 'test_with_parents.plugin_types.boolean*'); + + $definition = $tests[2]['settings']->getDataDefinition()->toArray(); + $this->assertEqual($definition['type'], 'test_with_parents.plugin_types.*'); + + $definition = $tests[3]['settings']->getDataDefinition()->toArray(); + $this->assertEqual($definition['type'], 'test_with_parents.plugin_types.*'); + } + } diff --git a/core/modules/config/tests/config_schema_test/config/install/config_schema_test.plugin_types.yml b/core/modules/config/tests/config_schema_test/config/install/config_schema_test.plugin_types.yml new file mode 100644 index 0000000..ab06fba --- /dev/null +++ b/core/modules/config/tests/config_schema_test/config/install/config_schema_test.plugin_types.yml @@ -0,0 +1,30 @@ +tests: + - + plugin_id: boolean + value: TRUE + - + plugin_id: boolean:derivative + value: TRUE + - + plugin_id: string + value: 'Foo' + - + plugin_id: string:derivative + value: 'Foo' +test_with_parents: + - + plugin_id: boolean + settings: + value: TRUE + - + plugin_id: boolean:derivative + settings: + value: TRUE + - + plugin_id: string + settings: + value: 'Foo' + - + plugin_id: string:derivative + settings: + value: 'Foo' diff --git a/core/modules/config/tests/config_schema_test/config/schema/config_schema_test.schema.yml b/core/modules/config/tests/config_schema_test/config/schema/config_schema_test.schema.yml index 34c6089..bcca468 100644 --- a/core/modules/config/tests/config_schema_test/config/schema/config_schema_test.schema.yml +++ b/core/modules/config/tests/config_schema_test/config/schema/config_schema_test.schema.yml @@ -149,3 +149,60 @@ config_schema_test.ignore: weight: type: integer label: 'Weight' + +config_schema_test.plugin_types: + type: mapping + mapping: + tests: + type: sequence + sequence: + - type: test.plugin_types.[plugin_id] + test_with_parents: + type: sequence + sequence: + - type: mapping + mapping: + plugin_id: + type: string + settings: + type: test_with_parents.plugin_types.[%parent.plugin_id] + +test.plugin_types: + type: mapping + mapping: + plugin_id: + type: string + +test.plugin_types.boolean: + type: mapping + mapping: + plugin_id: + type: string + value: + type: boolean + +test.plugin_types.boolean*: + type: test.plugin_types.boolean + +test_with_parents.plugin_types.boolean: + type: mapping + mapping: + value: + type: boolean + +test_with_parents.plugin_types.boolean*: + type: test_with_parents.plugin_types.boolean + +test.plugin_types.*: + type: mapping + mapping: + plugin_id: + type: string + value: + type: string + +test_with_parents.plugin_types.*: + type: mapping + mapping: + value: + type: string