Commit af608d70 authored by webchick's avatar webchick

Issue #1825466 by justafish, sun, alexpott: Allow...

Issue #1825466 by justafish, sun, alexpott: Allow NestedArray::mergeDeepArray() to preserve integer keys for the purpose of merging config data.
parent 560d935c
......@@ -12,6 +12,7 @@
use Drupal\Core\Config\FileStorage;
use Drupal\Core\Config\ConfigException;
use Drupal\Component\Uuid\Uuid;
use Drupal\Component\Utility\NestedArray;
/**
* Minimum schema version of Drupal 7 required for upgrade to Drupal 8.
......@@ -1218,18 +1219,15 @@ function update_variables_to_config($config_name, array $variable_map) {
}
$default_data = $file->read($config_name);
// Apply the default values.
$config->setData($default_data);
// Merge any possibly existing original data into default values.
// Only relevant when being called repetitively on the same config object.
if (!empty($original_data)) {
$data = drupal_array_merge_deep($default_data, $original_data);
}
else {
$data = $default_data;
$config->merge($original_data);
}
// Apply the default values.
$config->setData($data);
// Fetch existing variables.
$variables = db_query('SELECT name, value FROM {variable} WHERE name IN (:variables)', array(':variables' => array_keys($variable_map)))->fetchAllKeyed();
......
......@@ -289,6 +289,10 @@ public static function keyExists(array $array, array $parents) {
* @param array ...
* Arrays to merge.
*
* @param bool $preserve_integer_keys
* (optional) If given, integer keys will be preserved and merged instead of
* appended.
*
* @return array
* The merged array.
*
......@@ -315,19 +319,19 @@ public static function mergeDeep() {
*
* @see NestedArray::mergeDeep()
*/
public static function mergeDeepArray(array $arrays) {
public static function mergeDeepArray(array $arrays, $preserve_integer_keys = FALSE) {
$result = array();
foreach ($arrays as $array) {
foreach ($array as $key => $value) {
// Renumber integer keys as array_merge_recursive() does. Note that PHP
// automatically converts array keys that are integer strings (e.g., '1')
// to integers.
if (is_integer($key)) {
// Renumber integer keys as array_merge_recursive() does unless
// $preserve_integer_keys is set to TRUE. Note that PHP automatically
// converts array keys that are integer strings (e.g., '1') to integers.
if (is_integer($key) && !$preserve_integer_keys) {
$result[] = $value;
}
// Recurse when both values are arrays.
elseif (isset($result[$key]) && is_array($result[$key]) && is_array($value)) {
$result[$key] = self::mergeDeepArray(array($result[$key], $value));
$result[$key] = self::mergeDeepArray(array($result[$key], $value), $preserve_integer_keys);
}
// Otherwise, use the latter value, overriding any previous value.
else {
......
......@@ -196,7 +196,7 @@ public function setData(array $data) {
* The configuration object.
*/
public function setOverride(array $data) {
$this->overrides = NestedArray::mergeDeepArray(array($this->overrides, $data));
$this->overrides = NestedArray::mergeDeepArray(array($this->overrides, $data), TRUE);
$this->resetOverriddenData();
return $this;
}
......@@ -212,7 +212,7 @@ public function setOverride(array $data) {
protected function setOverriddenData() {
$this->overriddenData = $this->data;
if (!empty($this->overrides)) {
$this->overriddenData = NestedArray::mergeDeepArray(array($this->overriddenData, $this->overrides));
$this->overriddenData = NestedArray::mergeDeepArray(array($this->overriddenData, $this->overrides), TRUE);
}
return $this;
}
......@@ -388,7 +388,7 @@ public function delete() {
/**
* Retrieve the storage used to load and save this configuration object.
*
* @return Drupal\Core\Config\StorageInterface
* @return \Drupal\Core\Config\StorageInterface
* The configuration storage object.
*/
public function getStorage() {
......@@ -401,4 +401,19 @@ public function getStorage() {
protected function notify($config_event_name) {
$this->eventDispatcher->dispatch('config.' . $config_event_name, new ConfigEvent($this));
}
/*
* Merges data into a configuration object.
*
* @param array $data_to_merge
* An array containing data to merge.
*
* @return \Drupal\Core\Config\Config
* The configuration object.
*/
public function merge(array $data_to_merge) {
// Preserve integer keys so that config keys are not changed.
$this->data = NestedArray::mergeDeepArray(array($this->data, $data_to_merge), TRUE);
return $this;
}
}
......@@ -90,6 +90,17 @@ function testCRUD() {
$renamed_config = config($new_name);
$this->assertIdentical($renamed_config->get(), $config->get());
$this->assertIdentical($renamed_config->isNew(), FALSE);
// Merge data into the configuration object.
$new_config = config($new_name);
$expected_values = array(
'value' => 'herp',
'404' => 'derp',
);
$new_config->merge($expected_values);
$new_config->save();
$this->assertIdentical($new_config->get('value'), $expected_values['value']);
$this->assertIdentical($new_config->get('404'), $expected_values['404']);
}
}
......@@ -43,21 +43,25 @@ function testConfOverride() {
$expected_original_data = array(
'foo' => 'bar',
'baz' => NULL,
'404' => 'herp',
);
// Verify that the original configuration data exists.
$config = config('config_test.system');
$this->assertIdentical($config->get('foo'), $expected_original_data['foo']);
$this->assertIdentical($config->get('baz'), $expected_original_data['baz']);
$this->assertIdentical($config->get('404'), $expected_original_data['404']);
// Apply the overridden data.
$conf['config_test.system']['foo'] = 'overridden';
$conf['config_test.system']['baz'] = 'injected';
$conf['config_test.system']['404'] = 'derp';
// Verify that the in-memory configuration object still contains the
// original data.
$this->assertIdentical($config->get('foo'), $expected_original_data['foo']);
$this->assertIdentical($config->get('baz'), $expected_original_data['baz']);
$this->assertIdentical($config->get('404'), $expected_original_data['404']);
// Reload the configuration object.
$config = config('config_test.system');
......@@ -65,14 +69,20 @@ function testConfOverride() {
// Verify that it contains the overridden data from $conf.
$this->assertIdentical($config->get('foo'), $conf['config_test.system']['foo']);
$this->assertIdentical($config->get('baz'), $conf['config_test.system']['baz']);
$this->assertIdentical($config->get('404'), $conf['config_test.system']['404']);
// Set the value for 'baz' (on the original data).
$expected_original_data['baz'] = 'original baz';
$config->set('baz', $expected_original_data['baz']);
// Set the value for '404' (on the original data).
$expected_original_data['404'] = 'original 404';
$config->set('404', $expected_original_data['404']);
// Verify that it still contains the overridden data from $conf.
$this->assertIdentical($config->get('foo'), $conf['config_test.system']['foo']);
$this->assertIdentical($config->get('baz'), $conf['config_test.system']['baz']);
$this->assertIdentical($config->get('404'), $conf['config_test.system']['404']);
// Save the configuration object (having overrides applied).
$config->save();
......@@ -81,6 +91,7 @@ function testConfOverride() {
$config = config('config_test.system');
$this->assertIdentical($config->get('foo'), $conf['config_test.system']['foo']);
$this->assertIdentical($config->get('baz'), $conf['config_test.system']['baz']);
$this->assertIdentical($config->get('404'), $conf['config_test.system']['404']);
// Remove the $conf overrides.
unset($conf['config_test.system']);
......@@ -89,6 +100,7 @@ function testConfOverride() {
$config = config('config_test.system');
$this->assertIdentical($config->get('foo'), $expected_original_data['foo']);
$this->assertIdentical($config->get('baz'), $expected_original_data['baz']);
$this->assertIdentical($config->get('404'), $expected_original_data['404']);
}
}
......@@ -98,5 +98,26 @@ function testConfigurationUpdate() {
catch (ConfigException $e) {
$this->pass('Exception was thrown on missing default module configuration file.');
}
// For this test it is essential that update_variables_to_config has already
// run on the config object.
config('config_upgrade.test')
->set('numeric_keys.403', '')
->set('numeric_keys.404', '')
->save();
db_insert('variable')
->fields(array('name', 'value'))
->values(array('config_upgrade_403', serialize('custom403')))
->values(array('config_upgrade_404', serialize('custom404')))
->execute();
// Perform migration.
update_variables_to_config('config_upgrade.test', array(
'config_upgrade_403' => 'numeric_keys.403',
'config_upgrade_404' => 'numeric_keys.404',
));
$this->assertIdentical(config('config_upgrade.test')->get('numeric_keys'), array(403 => 'custom403', 404 => 'custom404'));
}
}
......@@ -2,3 +2,6 @@ parent:
bar: Bar
baz: Baz
foo: Foo
numeric_keys:
403: ''
404: ''
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment