Commit af56f3c3 authored by webchick's avatar webchick

Issue #2259525 by alexpott: System.action.user_add_role_action.ROLE_ID does...

Issue #2259525 by alexpott: System.action.user_add_role_action.ROLE_ID does not match any config schema.
parent edaf10f2
...@@ -215,8 +215,11 @@ public function clearCachedDefinitions() { ...@@ -215,8 +215,11 @@ public function clearCachedDefinitions() {
* definition in below order: * definition in below order:
* breakpoint.breakpoint.module.toolbar.* * breakpoint.breakpoint.module.toolbar.*
* breakpoint.breakpoint.module.*.* * breakpoint.breakpoint.module.*.*
* breakpoint.breakpoint.module.*
* breakpoint.breakpoint.*.*.* * breakpoint.breakpoint.*.*.*
* breakpoint.breakpoint.*
* breakpoint.*.*.*.* * breakpoint.*.*.*.*
* breakpoint.*
* Returns null, if no matching element. * Returns null, if no matching element.
*/ */
protected function getFallbackName($name) { protected function getFallbackName($name) {
...@@ -227,8 +230,16 @@ protected function getFallbackName($name) { ...@@ -227,8 +230,16 @@ protected function getFallbackName($name) {
return $replaced; return $replaced;
} }
else { else {
// No definition for this level(for example, breakpoint.breakpoint.*), // No definition for this level. Collapse multiple wildcards to a single
// check for next level (which is, breakpoint.*.*). // wildcard to see if there is a greedy match. For example,
// breakpoint.breakpoint.*.* becomes
// breakpoint.breakpoint.*
$one_star = preg_replace('/\.([\.\*]*)$/', '.*', $replaced);
if ($one_star != $replaced && isset($this->definitions[$one_star])) {
return $one_star;
}
// Check for next level. For example, if breakpoint.breakpoint.* has
// been checked and no match found then check breakpoint.*.*
return $this->getFallbackName($replaced); return $this->getFallbackName($replaced);
} }
} }
......
...@@ -44,14 +44,14 @@ function testModuleInstallation() { ...@@ -44,14 +44,14 @@ function testModuleInstallation() {
// Ensure that schema provided by modules that are not installed is not // Ensure that schema provided by modules that are not installed is not
// available. // available.
$this->assertFalse(\Drupal::service('config.typed')->hasConfigSchema('config_test.schema_in_install'), 'Configuration schema for config_test.schema_in_install does not exist.'); $this->assertFalse(\Drupal::service('config.typed')->hasConfigSchema('config_schema_test.schema_in_install'), 'Configuration schema for config_schema_test.schema_in_install does not exist.');
// Install the test module. // Install the test module.
$this->enableModules(array('config_test')); $this->enableModules(array('config_test', 'config_schema_test'));
$this->installConfig(array('config_test')); $this->installConfig(array('config_test', 'config_schema_test'));
// After module installation the new schema should exist. // After module installation the new schema should exist.
$this->assertTrue(\Drupal::service('config.typed')->hasConfigSchema('config_test.schema_in_install'), 'Configuration schema for config_test.schema_in_install exists.'); $this->assertTrue(\Drupal::service('config.typed')->hasConfigSchema('config_schema_test.schema_in_install'), 'Configuration schema for config_schema_test.schema_in_install exists.');
// Verify that default module config exists. // Verify that default module config exists.
\Drupal::configFactory()->reset($default_config); \Drupal::configFactory()->reset($default_config);
...@@ -71,13 +71,13 @@ function testModuleInstallation() { ...@@ -71,13 +71,13 @@ function testModuleInstallation() {
$this->assertFalse(isset($GLOBALS['hook_config_test']['delete'])); $this->assertFalse(isset($GLOBALS['hook_config_test']['delete']));
// Ensure that data type casting is applied during config installation. // Ensure that data type casting is applied during config installation.
$config = \Drupal::config('config_test.schema_in_install'); $config = \Drupal::config('config_schema_test.schema_in_install');
$this->assertIdentical($config->get('integer'), 1); $this->assertIdentical($config->get('integer'), 1);
// Test that uninstalling configuration removes configuration schema. // Test that uninstalling configuration removes configuration schema.
\Drupal::config('core.extension')->set('module', array())->save(); \Drupal::config('core.extension')->set('module', array())->save();
\Drupal::service('config.manager')->uninstall('module', 'config_test'); \Drupal::service('config.manager')->uninstall('module', 'config_test');
$this->assertFalse(\Drupal::service('config.typed')->hasConfigSchema('config_test.schema_in_install'), 'Configuration schema for config_test.schema_in_install does not exist.'); $this->assertFalse(\Drupal::service('config.typed')->hasConfigSchema('config_schema_test.schema_in_install'), 'Configuration schema for config_schema_test.schema_in_install does not exist.');
} }
} }
...@@ -21,7 +21,7 @@ class ConfigSchemaTest extends DrupalUnitTestBase { ...@@ -21,7 +21,7 @@ class ConfigSchemaTest extends DrupalUnitTestBase {
* *
* @var array * @var array
*/ */
public static $modules = array('system', 'language', 'locale', 'field', 'image', 'config_test'); public static $modules = array('system', 'language', 'locale', 'field', 'image', 'config_schema_test');
public static function getInfo() { public static function getInfo() {
return array( return array(
...@@ -33,7 +33,7 @@ public static function getInfo() { ...@@ -33,7 +33,7 @@ public static function getInfo() {
public function setUp() { public function setUp() {
parent::setUp(); parent::setUp();
$this->installConfig(array('system', 'image', 'config_test')); $this->installConfig(array('system', 'image', 'config_schema_test'));
} }
/** /**
...@@ -41,21 +41,21 @@ public function setUp() { ...@@ -41,21 +41,21 @@ public function setUp() {
*/ */
function testSchemaMapping() { function testSchemaMapping() {
// Nonexistent configuration key will have Unknown as metadata. // Nonexistent configuration key will have Unknown as metadata.
$this->assertIdentical(FALSE, \Drupal::service('config.typed')->hasConfigSchema('config_test.no_such_key')); $this->assertIdentical(FALSE, \Drupal::service('config.typed')->hasConfigSchema('config_schema_test.no_such_key'));
$definition = \Drupal::service('config.typed')->getDefinition('config_test.no_such_key'); $definition = \Drupal::service('config.typed')->getDefinition('config_schema_test.no_such_key');
$expected = array(); $expected = array();
$expected['label'] = 'Unknown'; $expected['label'] = 'Unknown';
$expected['class'] = '\Drupal\Core\Config\Schema\Property'; $expected['class'] = '\Drupal\Core\Config\Schema\Property';
$this->assertEqual($definition, $expected, 'Retrieved the right metadata for nonexistent configuration.'); $this->assertEqual($definition, $expected, 'Retrieved the right metadata for nonexistent configuration.');
// Configuration file without schema will return Unknown as well. // Configuration file without schema will return Unknown as well.
$this->assertIdentical(FALSE, \Drupal::service('config.typed')->hasConfigSchema('config_test.noschema')); $this->assertIdentical(FALSE, \Drupal::service('config.typed')->hasConfigSchema('config_schema_test.noschema'));
$definition = \Drupal::service('config.typed')->getDefinition('config_test.noschema'); $definition = \Drupal::service('config.typed')->getDefinition('config_schema_test.noschema');
$this->assertEqual($definition, $expected, 'Retrieved the right metadata for configuration with no schema.'); $this->assertEqual($definition, $expected, 'Retrieved the right metadata for configuration with no schema.');
// Configuration file with only some schema. // Configuration file with only some schema.
$this->assertIdentical(TRUE, \Drupal::service('config.typed')->hasConfigSchema('config_test.someschema')); $this->assertIdentical(TRUE, \Drupal::service('config.typed')->hasConfigSchema('config_schema_test.someschema'));
$definition = \Drupal::service('config.typed')->getDefinition('config_test.someschema'); $definition = \Drupal::service('config.typed')->getDefinition('config_schema_test.someschema');
$expected = array(); $expected = array();
$expected['label'] = 'Schema test data'; $expected['label'] = 'Schema test data';
$expected['class'] = '\Drupal\Core\Config\Schema\Mapping'; $expected['class'] = '\Drupal\Core\Config\Schema\Mapping';
...@@ -64,7 +64,7 @@ function testSchemaMapping() { ...@@ -64,7 +64,7 @@ function testSchemaMapping() {
$this->assertEqual($definition, $expected, 'Retrieved the right metadata for configuration with only some schema.'); $this->assertEqual($definition, $expected, 'Retrieved the right metadata for configuration with only some schema.');
// Check type detection on elements with undefined types. // Check type detection on elements with undefined types.
$config = \Drupal::service('config.typed')->get('config_test.someschema'); $config = \Drupal::service('config.typed')->get('config_schema_test.someschema');
$definition = $config['testitem']->getDataDefinition(); $definition = $config['testitem']->getDataDefinition();
$expected = array(); $expected = array();
$expected['label'] = 'Test item'; $expected['label'] = 'Test item';
...@@ -139,8 +139,8 @@ function testSchemaMapping() { ...@@ -139,8 +139,8 @@ function testSchemaMapping() {
$this->assertEqual($definition, $expected, 'Retrieved the right metadata for the first effect of image.style.medium'); $this->assertEqual($definition, $expected, 'Retrieved the right metadata for the first effect of image.style.medium');
// More complex, multiple filesystem marker test. // More complex, multiple filesystem marker test.
$definition = \Drupal::service('config.typed')->getDefinition('config_test.someschema.somemodule.section_one.subsection'); $definition = \Drupal::service('config.typed')->getDefinition('config_schema_test.someschema.somemodule.section_one.subsection');
// This should be the schema of config_test.someschema.somemodule.*.*. // This should be the schema of config_schema_test.someschema.somemodule.*.*.
$expected = array(); $expected = array();
$expected['label'] = 'Schema multiple filesytem marker test'; $expected['label'] = 'Schema multiple filesytem marker test';
$expected['class'] = '\Drupal\Core\Config\Schema\Mapping'; $expected['class'] = '\Drupal\Core\Config\Schema\Mapping';
...@@ -149,24 +149,24 @@ function testSchemaMapping() { ...@@ -149,24 +149,24 @@ function testSchemaMapping() {
$expected['mapping']['testdescription']['type'] = 'text'; $expected['mapping']['testdescription']['type'] = 'text';
$expected['mapping']['testdescription']['label'] = 'Description'; $expected['mapping']['testdescription']['label'] = 'Description';
$this->assertEqual($definition, $expected, 'Retrieved the right metadata for config_test.someschema.somemodule.section_one.subsection'); $this->assertEqual($definition, $expected, 'Retrieved the right metadata for config_schema_test.someschema.somemodule.section_one.subsection');
$definition = \Drupal::service('config.typed')->getDefinition('config_test.someschema.somemodule.section_two.subsection'); $definition = \Drupal::service('config.typed')->getDefinition('config_schema_test.someschema.somemodule.section_two.subsection');
// The other file should have the same schema. // The other file should have the same schema.
$this->assertEqual($definition, $expected, 'Retrieved the right metadata for config_test.someschema.somemodule.section_two.subsection'); $this->assertEqual($definition, $expected, 'Retrieved the right metadata for config_schema_test.someschema.somemodule.section_two.subsection');
} }
/** /**
* Tests metadata retrieval with several levels of %parent indirection. * Tests metadata retrieval with several levels of %parent indirection.
*/ */
function testSchemaMappingWithParents() { function testSchemaMappingWithParents() {
$config_data = \Drupal::service('config.typed')->get('config_test.someschema.with_parents'); $config_data = \Drupal::service('config.typed')->get('config_schema_test.someschema.with_parents');
// Test fetching parent one level up. // Test fetching parent one level up.
$entry = $config_data->get('one_level'); $entry = $config_data->get('one_level');
$definition = $entry['testitem']->getDataDefinition(); $definition = $entry['testitem']->getDataDefinition();
$expected = array( $expected = array(
'type' => 'config_test.someschema.with_parents.key_1', 'type' => 'config_schema_test.someschema.with_parents.key_1',
'label' => 'Test item nested one level', 'label' => 'Test item nested one level',
'class' => '\Drupal\Core\TypedData\Plugin\DataType\String', 'class' => '\Drupal\Core\TypedData\Plugin\DataType\String',
); );
...@@ -176,7 +176,7 @@ function testSchemaMappingWithParents() { ...@@ -176,7 +176,7 @@ function testSchemaMappingWithParents() {
$entry = $config_data->get('two_levels'); $entry = $config_data->get('two_levels');
$definition = $entry['wrapper']['testitem']->getDataDefinition(); $definition = $entry['wrapper']['testitem']->getDataDefinition();
$expected = array( $expected = array(
'type' => 'config_test.someschema.with_parents.key_2', 'type' => 'config_schema_test.someschema.with_parents.key_2',
'label' => 'Test item nested two levels', 'label' => 'Test item nested two levels',
'class' => '\Drupal\Core\TypedData\Plugin\DataType\String', 'class' => '\Drupal\Core\TypedData\Plugin\DataType\String',
); );
...@@ -186,7 +186,7 @@ function testSchemaMappingWithParents() { ...@@ -186,7 +186,7 @@ function testSchemaMappingWithParents() {
$entry = $config_data->get('three_levels'); $entry = $config_data->get('three_levels');
$definition = $entry['wrapper_1']['wrapper_2']['testitem']->getDataDefinition(); $definition = $entry['wrapper_1']['wrapper_2']['testitem']->getDataDefinition();
$expected = array( $expected = array(
'type' => 'config_test.someschema.with_parents.key_3', 'type' => 'config_schema_test.someschema.with_parents.key_3',
'label' => 'Test item nested three levels', 'label' => 'Test item nested three levels',
'class' => '\Drupal\Core\TypedData\Plugin\DataType\String', 'class' => '\Drupal\Core\TypedData\Plugin\DataType\String',
); );
...@@ -265,8 +265,8 @@ public function testConfigSaveWithSchema() { ...@@ -265,8 +265,8 @@ public function testConfigSaveWithSchema() {
// Not in schema and therefore should be left untouched. // Not in schema and therefore should be left untouched.
'not_present_in_schema' => TRUE, 'not_present_in_schema' => TRUE,
// Test a custom type. // Test a custom type.
'config_test_integer' => '1', 'config_schema_test_integer' => '1',
'config_test_integer_empty_string' => '', 'config_schema_test_integer_empty_string' => '',
); );
$untyped_to_typed = $untyped_values; $untyped_to_typed = $untyped_values;
...@@ -285,21 +285,43 @@ public function testConfigSaveWithSchema() { ...@@ -285,21 +285,43 @@ public function testConfigSaveWithSchema() {
'null_float' => NULL, 'null_float' => NULL,
'sequence' => array (TRUE, FALSE, TRUE), 'sequence' => array (TRUE, FALSE, TRUE),
'not_present_in_schema' => TRUE, 'not_present_in_schema' => TRUE,
'config_test_integer' => 1, 'config_schema_test_integer' => 1,
'config_test_integer_empty_string' => NULL, 'config_schema_test_integer_empty_string' => NULL,
); );
// Save config which has a schema that enforces types. // Save config which has a schema that enforces types.
\Drupal::config('config_test.schema_data_types') \Drupal::config('config_schema_test.schema_data_types')
->setData($untyped_to_typed) ->setData($untyped_to_typed)
->save(); ->save();
$this->assertIdentical(\Drupal::config('config_test.schema_data_types')->get(), $typed_values); $this->assertIdentical(\Drupal::config('config_schema_test.schema_data_types')->get(), $typed_values);
// Save config which does not have a schema that enforces types. // Save config which does not have a schema that enforces types.
\Drupal::config('config_test.no_schema_data_types') \Drupal::config('config_schema_test.no_schema_data_types')
->setData($untyped_values) ->setData($untyped_values)
->save(); ->save();
$this->assertIdentical(\Drupal::config('config_test.no_schema_data_types')->get(), $untyped_values); $this->assertIdentical(\Drupal::config('config_schema_test.no_schema_data_types')->get(), $untyped_values);
}
/**
* Tests fallback to a greedy wildcard.
*/
function testSchemaFallback() {
$definition = \Drupal::service('config.typed')->getDefinition('config_schema_test.wildcard_fallback.something');
// This should be the schema of config_schema_test.wildcard_fallback.*.
$expected = array();
$expected['label'] = 'Schema wildcard fallback test';
$expected['class'] = '\Drupal\Core\Config\Schema\Mapping';
$expected['mapping']['testid']['type'] = 'string';
$expected['mapping']['testid']['label'] = 'ID';
$expected['mapping']['testdescription']['type'] = 'text';
$expected['mapping']['testdescription']['label'] = 'Description';
$this->assertEqual($definition, $expected, 'Retrieved the right metadata for config_schema_test.wildcard_fallback.something');
$definition2 = \Drupal::service('config.typed')->getDefinition('config_schema_test.wildcard_fallback.something.something');
// This should be the schema of config_schema_test.wildcard_fallback.* as
//well.
$this->assertIdentical($definition, $definition2);
} }
} }
...@@ -57,13 +57,9 @@ public function testDefaultConfig() { ...@@ -57,13 +57,9 @@ public function testDefaultConfig() {
continue; continue;
} }
// 1. config_test.noschema has to be skipped as it tests // Skip files provided by the config_schema_test module since that module
// TypedConfigManagerInterface::hasConfigSchema() method. // is explicitly for testing schema.
// 2. config.someschema has to be skipped as it tests schema default data if (strpos($config_name, 'config_schema_test') === 0) {
// type fallback.
// 3. config_test.schema_in_install is testing that schema are used during
// configuration installation.
if ($config_name == 'config_test.noschema' || $config_name == 'config_test.someschema' || $config_name == 'config_test.schema_in_install') {
continue; continue;
} }
......
# Schema for the configuration files of the Configuration Schema Test module.
config_schema_test.someschema:
type: mapping
label: 'Schema test data'
mapping:
testitem:
label: 'Test item'
testlist:
label: 'Test list'
config_schema_test.someschema.with_parents:
label: 'Schema test data with parenting'
type: mapping
mapping:
one_level:
label: 'Parenting one level up'
type: mapping
mapping:
target_key:
label: 'Key used in parent relation'
type: string
testitem:
type: config_schema_test.someschema.with_parents.[%parent.target_key]
two_levels:
label: 'Parenting two levels up'
type: mapping
mapping:
target_key:
label: 'Key used in parent relation'
type: string
wrapper:
label: 'Wrapper'
type: mapping
mapping:
testitem:
type: config_schema_test.someschema.with_parents.[%parent.%parent.target_key]
three_levels:
label: 'Parenting three levels up'
type: mapping
mapping:
target_key:
label: 'Key used in parent relation'
type: string
wrapper_1:
label: 'Wrapper 1'
type: mapping
mapping:
wrapper_2:
label: 'Wrapper 2'
type: mapping
mapping:
testitem:
type: config_schema_test.someschema.with_parents.[%parent.%parent.%parent.target_key]
config_schema_test.someschema.with_parents.key_1:
label: 'Test item nested one level'
type: string
config_schema_test.someschema.with_parents.key_2:
label: 'Test item nested two levels'
type: string
config_schema_test.someschema.with_parents.key_3:
label: 'Test item nested three levels'
type: string
config_schema_test.someschema.somemodule.*.*:
type: mapping
label: 'Schema multiple filesytem marker test'
mapping:
testid:
type: string
label: 'ID'
testdescription:
type: text
label: 'Description'
config_schema_test.wildcard_fallback.*:
type: mapping
label: 'Schema wildcard fallback test'
mapping:
testid:
type: string
label: 'ID'
testdescription:
type: text
label: 'Description'
config_schema_test.schema_data_types:
type: mapping
label: 'Config test schema'
mapping:
config_schema_test_integer:
type: config_schema_test_integer
config_schema_test_integer_empty_string:
type: config_schema_test_integer
integer:
type: integer
null_integer:
type: integer
float:
type: float
null_float:
type: float
string:
type: string
null_string:
type: string
empty_string:
type: string
boolean:
type: boolean
no_type:
label: 'No label'
mapping:
type: mapping
mapping:
string:
type: string
sequence:
type: sequence
sequence:
- type: boolean
config_schema_test.schema_in_install:
label: 'Schema test data with parenting'
type: mapping
mapping:
integer:
type: integer
label: 'Integer'
config_schema_test_integer:
type: integer
label: 'Config test integer'
name: 'Configuration schema test'
type: module
package: Testing
version: VERSION
core: 8.x
hidden: true
# Schema for the configuration files of the Configuration Test module. # Schema for the configuration files of the Configuration Test module.
config_test.someschema:
type: mapping
label: 'Schema test data'
mapping:
testitem:
label: 'Test item'
testlist:
label: 'Test list'
config_test.someschema.with_parents:
label: 'Schema test data with parenting'
type: mapping
mapping:
one_level:
label: 'Parenting one level up'
type: mapping
mapping:
target_key:
label: 'Key used in parent relation'
type: string
testitem:
type: config_test.someschema.with_parents.[%parent.target_key]
two_levels:
label: 'Parenting two levels up'
type: mapping
mapping:
target_key:
label: 'Key used in parent relation'
type: string
wrapper:
label: 'Wrapper'
type: mapping
mapping:
testitem:
type: config_test.someschema.with_parents.[%parent.%parent.target_key]
three_levels:
label: 'Parenting three levels up'
type: mapping
mapping:
target_key:
label: 'Key used in parent relation'
type: string
wrapper_1:
label: 'Wrapper 1'
type: mapping
mapping:
wrapper_2:
label: 'Wrapper 2'
type: mapping
mapping:
testitem:
type: config_test.someschema.with_parents.[%parent.%parent.%parent.target_key]
config_test.someschema.with_parents.key_1:
label: 'Test item nested one level'
type: string
config_test.someschema.with_parents.key_2:
label: 'Test item nested two levels'
type: string
config_test.someschema.with_parents.key_3:
label: 'Test item nested three levels'
type: string
config_test.someschema.somemodule.*.*:
type: mapping
label: 'Schema multiple filesytem marker test'
mapping:
testid:
type: string
label: 'ID'
testdescription:
type: text
label: 'Description'
config_test.dynamic.*: config_test.dynamic.*:
type: mapping type: mapping
label: 'Config test entity' label: 'Config test entity'
...@@ -94,54 +20,6 @@ config_test.dynamic.*: ...@@ -94,54 +20,6 @@ config_test.dynamic.*:
type: string type: string
label: 'Protected property' label: 'Protected property'