diff --git a/core/lib/Drupal/Core/Config/Schema/Mapping.php b/core/lib/Drupal/Core/Config/Schema/Mapping.php index 5729390..a85fac4 100644 --- a/core/lib/Drupal/Core/Config/Schema/Mapping.php +++ b/core/lib/Drupal/Core/Config/Schema/Mapping.php @@ -27,22 +27,18 @@ class Mapping extends ArrayElement implements ComplexDataInterface { protected $propertyDefinitions; /** - * Overrides ArrayElement::parse() - * - * Note this only returns elements that have a data definition. + * {@inheritdoc} */ protected function parse() { $elements = array(); foreach ($this->getPropertyDefinitions() as $key => $definition) { - if (isset($this->value[$key]) || array_key_exists($key, $this->value)) { - $elements[$key] = $this->parseElement($key, $this->value[$key], $definition); - } + $elements[$key] = $this->parseElement($key, $this->value[$key], $definition); } return $elements; } /** - * Implements Drupal\Core\TypedData\ComplexDataInterface::get(). + * {@inheritdoc} * * Since all configuration objects are mappings the function will except a dot * delimited key to access nested values, for example, 'page.front'. @@ -53,19 +49,22 @@ public function get($property_name) { $elements = $this->getElements(); if (isset($elements[$root_key])) { $element = $elements[$root_key]; + // If $property_name contained a dot recurse into the keys. + while ($element && ($key = array_shift($parts)) !== NULL) { + if (method_exists($element, 'get')) { + $element = $element->get($key); + } + else { + $element = NULL; + } + } } - else { - throw new SchemaIncompleteException(String::format("The configuration property @key doesn't exist.", array('@key' => $property_name))); + if (isset($element)) { + return $element; } - - // If $property_name contained a dot recurse into the keys. - foreach ($parts as $key) { - if (!is_object($element) || !method_exists($element, 'get')) { - throw new SchemaIncompleteException(String::format("The configuration property @key does not exist.", array('@key' => $property_name))); - } - $element = $element->get($key); + else { + throw new \InvalidArgumentException(String::format("The configuration property @key doesn't exist.", array('@key' => $property_name))); } - return $element; } /** @@ -130,9 +129,9 @@ public function getPropertyDefinition($name) { public function getPropertyDefinitions() { if (!isset($this->propertyDefinitions)) { $this->propertyDefinitions = array(); - foreach ($this->definition['mapping'] as $key => $definition) { - $value = isset($this->value[$key]) ? $this->value[$key] : NULL; - $this->propertyDefinitions[$key] = $this->buildDataDefinition($definition, $value, $key); + foreach ($this->getAllKeys() as $key) { + $definition = isset($this->definition['mapping'][$key]) ? $this->definition['mapping'][$key] : array(); + $this->propertyDefinitions[$key] = $this->buildDataDefinition($definition, $this->value[$key], $key); } } return $this->propertyDefinitions; diff --git a/core/lib/Drupal/Core/Config/Schema/SchemaCheckTrait.php b/core/lib/Drupal/Core/Config/Schema/SchemaCheckTrait.php index 4348316..0836eaf 100644 --- a/core/lib/Drupal/Core/Config/Schema/SchemaCheckTrait.php +++ b/core/lib/Drupal/Core/Config/Schema/SchemaCheckTrait.php @@ -78,15 +78,11 @@ public function checkConfigSchema(TypedConfigManagerInterface $typed_config, $co */ protected function checkValue($key, $value) { $error_key = $this->configName . ':' . $key; - $element = FALSE; - try { - $element = $this->schema->get($key); - } - catch (SchemaIncompleteException $e) { - if (is_scalar($value) || $value === NULL) { - return array($error_key => 'Missing schema'); - } + $element = $this->schema->get($key); + if ($element instanceof Undefined) { + return array($error_key => 'Missing schema.'); } + // Do not check value if it is defined to be ignored. if ($element && $element instanceof Ignore) { return array(); @@ -112,7 +108,7 @@ protected function checkValue($key, $value) { else { $errors = array(); if (!$element instanceof ArrayElement) { - $errors[$error_key] = 'Non-scalar value but not defined as an array (such as mapping or sequence)'; + $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 diff --git a/core/lib/Drupal/Core/Config/StorableConfigBase.php b/core/lib/Drupal/Core/Config/StorableConfigBase.php index b2610f7..24bc4d2 100644 --- a/core/lib/Drupal/Core/Config/StorableConfigBase.php +++ b/core/lib/Drupal/Core/Config/StorableConfigBase.php @@ -9,7 +9,6 @@ use Drupal\Component\Utility\String; use Drupal\Core\Config\Schema\Ignore; -use Drupal\Core\Config\Schema\SchemaIncompleteException; use Drupal\Core\TypedData\PrimitiveInterface; use Drupal\Core\TypedData\Type\FloatInterface; use Drupal\Core\TypedData\Type\IntegerInterface; @@ -170,16 +169,7 @@ protected function validateValue($key, $value) { * Exception on unsupported/undefined data type deducted. */ protected function castValue($key, $value) { - $element = FALSE; - try { - $element = $this->getSchemaWrapper()->get($key); - } - catch (SchemaIncompleteException $e) { - // @todo Consider making schema handling more strict by throwing - // SchemaIncompleteException for all incomplete schema conditions *and* - // throwing it forward. See https://drupal.org/node/2183983. - // Until then, we need to handle the Undefined case below. - } + $element = $this->getSchemaWrapper()->get($key); // Do not cast value if it is unknown or defined to be ignored. if ($element && ($element instanceof Undefined || $element instanceof Ignore)) { return $value; diff --git a/core/modules/config/src/Tests/SchemaCheckTraitTest.php b/core/modules/config/src/Tests/SchemaCheckTraitTest.php index 3b5793a..5620422 100644 --- a/core/modules/config/src/Tests/SchemaCheckTraitTest.php +++ b/core/modules/config/src/Tests/SchemaCheckTraitTest.php @@ -64,12 +64,15 @@ public function testTrait() { $ret = $this->checkConfigSchema($this->typedConfig, 'config_test.types', $config_data); $this->assertIdentical($ret, TRUE); - // Add a new key and new array to test the error messages. + // Add a new key, a new array and overwrite boolean with array to test the + // error messages. $config_data = array('new_key' => 'new_value', 'new_array' => array()) + $config_data; + $config_data['boolean'] = array(); $ret = $this->checkConfigSchema($this->typedConfig, 'config_test.types', $config_data); $expected = array( - 'config_test.types:new_key' => 'Missing schema', - 'config_test.types:new_array' => 'Non-scalar value but not defined as an array (such as mapping or sequence)', + 'config_test.types:new_key' => 'Missing schema.', + 'config_test.types:new_array' => 'Missing schema.', + 'config_test.types:boolean' => 'Non-scalar value but not defined as an array (such as mapping or sequence).', ); $this->assertIdentical($ret, $expected); } diff --git a/core/modules/link/src/Tests/LinkFieldTest.php b/core/modules/link/src/Tests/LinkFieldTest.php index 1a5f155..99976bc 100644 --- a/core/modules/link/src/Tests/LinkFieldTest.php +++ b/core/modules/link/src/Tests/LinkFieldTest.php @@ -376,10 +376,10 @@ function testLinkFormatter() { 'rel' => array(NULL, 'nofollow'), 'target' => array(NULL, '_blank'), 'url_only' => array( - array('url_only' => array(FALSE)), - array('url_only' => array(FALSE), 'url_plain' => TRUE), - array('url_only' => array(TRUE)), - array('url_only' => array(TRUE), 'url_plain' => TRUE), + array('url_only' => FALSE), + array('url_only' => FALSE, 'url_plain' => TRUE), + array('url_only' => TRUE), + array('url_only' => TRUE, 'url_plain' => TRUE), ), ); foreach ($options as $setting => $values) { diff --git a/core/modules/migrate_drupal/src/Tests/d6/MigrateConfigSchemaBase.php b/core/modules/migrate_drupal/src/Tests/d6/MigrateConfigSchemaBase.php index 7af563f..b5d0a3e 100644 --- a/core/modules/migrate_drupal/src/Tests/d6/MigrateConfigSchemaBase.php +++ b/core/modules/migrate_drupal/src/Tests/d6/MigrateConfigSchemaBase.php @@ -8,11 +8,11 @@ namespace Drupal\migrate_drupal\Tests\d6; use Drupal\Core\Config\Schema\ArrayElement; +use Drupal\Core\Config\Schema\Undefined; use Drupal\Core\Config\TypedConfigManagerInterface; use Drupal\Core\TypedData\Type\BooleanInterface; use Drupal\Core\TypedData\Type\StringInterface; use Drupal\Component\Utility\String; -use Drupal\Core\Config\Schema\SchemaIncompleteException; use Drupal\Core\TypedData\PrimitiveInterface; use Drupal\Core\TypedData\Type\FloatInterface; use Drupal\Core\TypedData\Type\IntegerInterface; @@ -85,14 +85,10 @@ public function assertConfigSchema(TypedConfigManagerInterface $typed_config, $c * Returns mixed value. */ protected function checkValue($key, $value) { - $element = FALSE; - try { - $element = $this->schema->get($key); - } - catch (SchemaIncompleteException $e) { - if (is_scalar($value) || $value === NULL) { - $this->fail("{$this->configName}:$key has no schema."); - } + $element = $this->schema->get($key); + if ($element instanceof Undefined) { + $this->fail("{$this->configName}:$key has no schema."); + return; } // Do not check value if it is defined to be ignored. if ($element && $element instanceof Ignore) { diff --git a/core/modules/update/tests/modules/update_test/config/schema/update_test.schema.yml b/core/modules/update/tests/modules/update_test/config/schema/update_test.schema.yml index 2235f2b..e7f5eef 100644 --- a/core/modules/update/tests/modules/update_test/config/schema/update_test.schema.yml +++ b/core/modules/update/tests/modules/update_test/config/schema/update_test.schema.yml @@ -8,8 +8,11 @@ update_test.settings: type: sequence label: 'System info' sequence: - - type: string - label: 'Value' + - type: sequence + label: 'Items' + sequence: + - type: string + label: 'Item' update_status: type: sequence label: 'Update status' diff --git a/core/modules/user/config/schema/user.views.schema.yml b/core/modules/user/config/schema/user.views.schema.yml index 55ea1c4..fc8a7fd 100644 --- a/core/modules/user/config/schema/user.views.schema.yml +++ b/core/modules/user/config/schema/user.views.schema.yml @@ -9,11 +9,15 @@ views.access.perm: label: 'Permission' views.access.role: - type: sequence - label: 'Role' - sequence: - - type: string - label: 'Role' + type: mapping + label: 'Roles' + mapping: + role: + type: sequence + label: 'List of roles' + sequence: + - type: string + label: 'Role' views.argument.user_uid: type: views.argument.numeric