diff --git a/core/lib/Drupal/Core/Config/TypedConfigManager.php b/core/lib/Drupal/Core/Config/TypedConfigManager.php index 6775aab..e55865e 100644 --- a/core/lib/Drupal/Core/Config/TypedConfigManager.php +++ b/core/lib/Drupal/Core/Config/TypedConfigManager.php @@ -135,9 +135,15 @@ public function getDefinition($base_plugin_id, $exception_on_invalid = TRUE) { $definition = $definitions[$type]; // Check whether this type is an extension of another one and compile it. if (isset($definition['type'])) { + // Replace the extended type's wildcards with the values of the original + // type's wildcards. $extended_type = preg_replace_callback('/\*/', function() use ($wildcard_values) { static $wildcard_index = 0; - return $wildcard_values[$wildcard_index++]; + + $wildcard_value = isset($wildcard_values[$wildcard_index]) ? $wildcard_values[$wildcard_index] : '*'; + $wildcard_index++; + + return $wildcard_value; }, $definition['type']); $merge = $this->getDefinition($extended_type, $exception_on_invalid); // Preserve integer keys on merge, so sequence item types can override diff --git a/core/tests/Drupal/Tests/Core/Config/TypedConfigManagerTest.php b/core/tests/Drupal/Tests/Core/Config/TypedConfigManagerTest.php new file mode 100644 index 0000000..dc1dafe --- /dev/null +++ b/core/tests/Drupal/Tests/Core/Config/TypedConfigManagerTest.php @@ -0,0 +1,156 @@ +cacheBackend = $this->getMock(CacheBackendInterface::class); + $this->configStorage = $this->getMock(StorageInterface::class); + $this->moduleHandler = $this->getMock(ModuleHandlerInterface::class); + $this->schemaStorage = $this->getMock(StorageInterface::class); + + $this->sut = new TypedConfigManager($this->configStorage, $this->schemaStorage, $this->cacheBackend, $this->moduleHandler); + } + + /** + * @covers ::getDefinition + * @covers ::getFallbackName + * + * @dataProvider providerGetDefinition + * + * @param mixed[] $expected_definition + * The expected schema definition. + * @param string $schema_id + * The ID of the expected schema. + * @param array[] $schema_definitions + * All available schema definitions. + */ + public function testGetDefinition(array $expected_definition, $schema_id, array $schema_definitions) { + $this->schemaStorage->expects($this->atLeastOnce()) + ->method('listAll') + ->willReturn([]); + $this->schemaStorage->expects($this->atLeastOnce()) + ->method('readMultiple') + ->willReturn([$schema_definitions]); + + $this->assertSame($expected_definition, $this->sut->getDefinition($schema_id)); + } + + /** + * Provides data to self::testGetDefinition(). + */ + public function providerGetDefinition() { + $undefined_schema_definition = [ + 'definition_class' => DataDefinition::class, + 'check' => 'Undefined', + ]; + $simple_schema_definition = [ + 'definition_class' => DataDefinition::class, + 'check' => 'Simple', + ]; + $fallback_schema_definition = [ + 'definition_class' => DataDefinition::class, + 'check' => 'Fallback', + ]; + $fallback_resolved_schema_definition = [ + 'definition_class' => DataDefinition::class, + 'check' => 'FallbackResolved', + ]; + $fallback_alias_schema_definition = [ + 'type' => 'fallback.*', + // We do not need a check item, because this is an alias. + ]; + $schema_definitions = [ + 'simple' => $simple_schema_definition, + 'undefined' => $undefined_schema_definition, + 'fallback.*' => $fallback_schema_definition, + 'fallback.resolved' => $fallback_resolved_schema_definition, + 'fallback_alias.*' => $fallback_alias_schema_definition, + ]; + + return [ + // A non-existent schema ID. + [$undefined_schema_definition + [ + 'type' => 'undefined', + ], 'non_existent', $schema_definitions], + // A schema with an ID without wildcards. + [$simple_schema_definition + [ + 'type' => 'simple', + ], 'simple', $schema_definitions], + // A non-existent schema ID for which a direct fallback exists. + [$fallback_schema_definition + [ + 'type' => 'fallback.*', + ], 'fallback.non_existent', $schema_definitions], + // A schema ID for which a direct, unused fallback exists. + [$fallback_resolved_schema_definition + [ + 'type' => 'fallback.resolved', + ], 'fallback.resolved', $schema_definitions], + // An aliased schema ID. + [$fallback_schema_definition + [ + 'type' => 'fallback_alias.*', + ], 'fallback_alias.*', $schema_definitions], + // An aliased schema ID with a resolved wildcard. + [$fallback_resolved_schema_definition + [ + 'type' => 'fallback_alias.*', + ], 'fallback_alias.resolved', $schema_definitions], + ]; + } + +}