diff --git a/core/lib/Drupal/Core/Config/Config.php b/core/lib/Drupal/Core/Config/Config.php index 7c150e9..ead66ce 100644 --- a/core/lib/Drupal/Core/Config/Config.php +++ b/core/lib/Drupal/Core/Config/Config.php @@ -302,18 +302,24 @@ public function castValue($value) { * Unsets value in this config object. * * @param string $key - * Name of the key whose value should be unset. + * (optional) The name of the key whose value should be unset. If omitted, + * the entire config object is emptied. * * @return Drupal\Core\Config\Config * The configuration object. */ - public function clear($key) { - $parts = explode('.', $key); - if (count($parts) == 1) { - unset($this->data[$key]); + public function clear($key = NULL) { + if (!isset($key)) { + $this->data = array(); } else { - NestedArray::unsetValue($this->data, $parts); + $parts = explode('.', $key); + if (count($parts) == 1) { + unset($this->data[$key]); + } + else { + NestedArray::unsetValue($this->data, $parts); + } } $this->resetOverriddenData(); return $this; @@ -346,7 +352,6 @@ public function load() { * The configuration object. */ public function save() { - $this->sortByKey($this->data); $this->storage->write($this->name, $this->data); $this->isNew = FALSE; $this->notify('save'); @@ -370,26 +375,6 @@ public function rename($new_name) { } /** - * Sorts all keys in configuration data. - * - * Ensures that re-inserted keys appear in the same location as before, in - * order to ensure an identical order regardless of storage controller. - * A consistent order is important for any storage that allows any kind of - * diff operation. - * - * @param array $data - * An associative array to sort recursively by key name. - */ - public function sortByKey(array &$data) { - ksort($data); - foreach ($data as &$value) { - if (is_array($value)) { - $this->sortByKey($value); - } - } - } - - /** * Deletes the configuration object. * * @return Drupal\Core\Config\Config diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php b/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php index e82eb7f..b007968 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php @@ -274,6 +274,10 @@ public function save(EntityInterface $entity) { $this->preSave($entity); $this->invokeHook('presave', $entity); + // Clear out any possibly existing keys in an existing configuration object, + // so any potentially stale keys are removed. + $config->clear(); + // Configuration objects do not have a schema. Extract all key names from // class properties. $class_info = new \ReflectionClass($entity); diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigCRUDTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigCRUDTest.php index 9eea495..e0bc6a9 100644 --- a/core/modules/config/lib/Drupal/config/Tests/ConfigCRUDTest.php +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigCRUDTest.php @@ -93,7 +93,7 @@ function testCRUD() { } /** - * Tests Drupal\Core\Config\Config::sortByKey(). + * Tests key injection order. */ function testDataKeySort() { $config = config('config_test.keysort'); @@ -106,8 +106,6 @@ function testDataKeySort() { // Load the configuration data into a new object. $new_config = config('config_test.keysort'); - // Clear the 'new' key that came first. - $new_config->clear('new'); // Add a new 'new' key and save. $new_config->set('new', 'Value to be replaced'); $new_config->save(); diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigEntityTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigEntityTest.php index 532979c..58cb605 100644 --- a/core/modules/config/lib/Drupal/config/Tests/ConfigEntityTest.php +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigEntityTest.php @@ -85,6 +85,19 @@ function testCRUD() { $this->assertResponse(200); $this->assertNoText($label1); $this->assertText($label3); + $id = $edit['id']; + + // Add an orphan key to the configuration entity's object. + $config = config('config_test.dynamic.' . $id); + $config->set('foo', 'bar')->save(); + + // Re-save the configuration entity. + $this->drupalPost('admin/structure/config_test/manage/' . $id, array(), 'Save'); + $this->assertResponse(200); + + // Verify that the orphan key was destroyed. + $config = config('config_test.dynamic.' . $id); + $this->assertNull($config->get('foo')); } } diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigImportTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigImportTest.php index 9316962..2266732 100644 --- a/core/modules/config/lib/Drupal/config/Tests/ConfigImportTest.php +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigImportTest.php @@ -128,10 +128,10 @@ function testNew() { $staging->write($name, $original_name_data); $original_dynamic_data = array( 'id' => 'new', + 'uuid' => '30df59bd-7b03-4cf7-bb35-d42fc49f0651', 'label' => 'New', - 'langcode' => 'und', 'style' => '', - 'uuid' => '30df59bd-7b03-4cf7-bb35-d42fc49f0651', + 'langcode' => 'und', ); $staging->write($dynamic_name, $original_dynamic_data); $this->assertIdentical($staging->exists($name), TRUE, $name . ' found.');