diff --git a/core/lib/Drupal/Core/Config/Config.php b/core/lib/Drupal/Core/Config/Config.php index bdeeba1..b3b51c2 100644 --- a/core/lib/Drupal/Core/Config/Config.php +++ b/core/lib/Drupal/Core/Config/Config.php @@ -110,7 +110,7 @@ public function get($key = '') { * {@inheritdoc} */ public function setData(array $data) { - $this->data = $data; + parent::setData($data); $this->resetOverriddenData(); return $this; } diff --git a/core/lib/Drupal/Core/Config/ConfigBase.php b/core/lib/Drupal/Core/Config/ConfigBase.php index 3508611..37e0d80 100644 --- a/core/lib/Drupal/Core/Config/ConfigBase.php +++ b/core/lib/Drupal/Core/Config/ConfigBase.php @@ -160,13 +160,39 @@ public function get($key = '') { * * @return $this * The configuration object. + * + * @throws \Drupal\Core\Config\ConfigValueException + * If any key in $data in any depth contains a dot. */ public function setData(array $data) { + $this->validateKeys($data); $this->data = $data; return $this; } /** + * Validate all keys in a passed in config array structure. + * + * @param array $data + * Configuration array structure. + * + * @return null + * + * @throws \Drupal\Core\Config\ConfigValueException + * If any key in $data in any depth contains a dot. + */ + protected function validateKeys(array $data) { + foreach ($data as $key => $value) { + if (strpos($key, '.') !== FALSE) { + throw new ConfigValueException(String::format('@key key contains a dot which is not supported.', array('@key' => $key))); + } + if (is_array($value)) { + $this->validateKeys($value); + } + } + } + + /** * Sets a value in this configuration object. * * @param string $key @@ -176,10 +202,16 @@ public function setData(array $data) { * * @return $this * The configuration object. + * + * @throws \Drupal\Core\Config\ConfigValueException + * If $value is an array and any of its keys in any depth contains a dot. */ public function set($key, $value) { // The dot/period is a reserved character; it may appear between keys, but // not within keys. + if (is_array($value)) { + $this->validateKeys($value); + } $parts = explode('.', $key); if (count($parts) == 1) { $this->data[$key] = $value; diff --git a/core/lib/Drupal/Core/Config/ConfigValueException.php b/core/lib/Drupal/Core/Config/ConfigValueException.php new file mode 100644 index 0000000..9802228 --- /dev/null +++ b/core/lib/Drupal/Core/Config/ConfigValueException.php @@ -0,0 +1,13 @@ +setData(array('key.value' => 12))->save(); + $this->fail($message); + } + catch (ConfigValueException $e) { + $this->pass($message); + } + + // Verify that set() will catch dotted keys. + $message = 'Expected ConfigValueException was thrown from set() for value with dotted keys.'; + try { + \Drupal::config('namespace.object')->set('foo', array('key.value' => 12))->save(); + $this->fail($message); + } + catch (ConfigValueException $e) { + $this->pass($message); + } + } + + /** * Tests data type handling. */ public function testDataTypes() { diff --git a/core/modules/options/src/Tests/OptionsFieldUITest.php b/core/modules/options/src/Tests/OptionsFieldUITest.php index c69e797..0eac490 100644 --- a/core/modules/options/src/Tests/OptionsFieldUITest.php +++ b/core/modules/options/src/Tests/OptionsFieldUITest.php @@ -94,6 +94,11 @@ function testOptionsAllowedValuesInteger() { $string = "0|Zero"; $array = array('0' => 'Zero'); $this->assertAllowedValuesInput($string, $array, 'Values not in use can be removed.'); + + // Check that the same key can only be used once. + $string = "0|Zero\n0|One"; + $array = array('0' => 'One'); + $this->assertAllowedValuesInput($string, $array, 'Same value cannot be used multiple times.'); } /** @@ -144,6 +149,16 @@ function testOptionsAllowedValuesFloat() { $string = "0|Zero"; $array = array('0' => 'Zero'); $this->assertAllowedValuesInput($string, $array, 'Values not in use can be removed.'); + + // Check that the same key can only be used once. + $string = "0.5|Point five\n0.5|Half"; + $array = array('0.5' => 'Half'); + $this->assertAllowedValuesInput($string, $array, 'Same value cannot be used multiple times.'); + + // Check that different forms of the same float value cannot be used. + $string = "0|Zero\n.5|Point five\n0.5|Half"; + $array = array('0' => 'Zero', '0.5' => 'Half'); + $this->assertAllowedValuesInput($string, $array, 'Different forms of the same value cannot be used.'); } /** @@ -199,6 +214,16 @@ function testOptionsAllowedValuesText() { $string = "Zero"; $array = array('Zero' => 'Zero'); $this->assertAllowedValuesInput($string, $array, 'Values not in use can be removed.'); + + // Check that string values with dots can be used. + $string = "Zero\nexample.com|Example"; + $array = array('Zero' => 'Zero', 'example.com' => 'Example'); + $this->assertAllowedValuesInput($string, $array, 'String value with dot is supported.'); + + // Check that the same key can only be used once. + $string = "zero|Zero\nzero|One"; + $array = array('zero' => 'One'); + $this->assertAllowedValuesInput($string, $array, 'Same value cannot be used multiple times.'); } /**