From 8d1e828d23cfaafe0ea159840b40ec09c597b9e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Lahmann?= <lahmann@users.noreply.github.com> Date: Wed, 8 Mar 2017 17:31:24 +0100 Subject: [PATCH] Config inheritance array merge setting (#921) --- config/vufind/config.ini | 6 ++ .../src/VuFind/Config/PluginFactory.php | 21 ++++++- .../VuFindTest/Config/PluginFactoryTest.php | 59 ++++++++++++++++++- 3 files changed, 83 insertions(+), 3 deletions(-) diff --git a/config/vufind/config.ini b/config/vufind/config.ini index b634dd5e73d..53cd47677c1 100644 --- a/config/vufind/config.ini +++ b/config/vufind/config.ini @@ -1135,6 +1135,12 @@ skip_numeric = true ; any sections not listed here will be merged on a section-by-section basis. ;override_full_sections = "Languages,AlphaBrowse_Types" +; This setting is for allowing arrays to be merged with the values of their parents +; arrays. If override_full_sections is set for a section the arrays will always be +; overridden. +; For legacy reasons merging of arrays is disabled by default. +;merge_array_settings = false + ; This section controls which language options are available to your users. ; If you offer more than one option, a control will appear in the user ; interface to allow user selection. If you only activate one language, diff --git a/module/VuFind/src/VuFind/Config/PluginFactory.php b/module/VuFind/src/VuFind/Config/PluginFactory.php index 60b36d01f5b..5fbd16913bb 100644 --- a/module/VuFind/src/VuFind/Config/PluginFactory.php +++ b/module/VuFind/src/VuFind/Config/PluginFactory.php @@ -113,6 +113,11 @@ class PluginFactory implements AbstractFactoryInterface ) : []; foreach ($child as $section => $contents) { + // Check if arrays in the current config file should be merged with + // preceding arrays from config files defined as Parent_Config. + $mergeArraySettings + = !empty($child->Parent_Config->merge_array_settings); + // Omit Parent_Config from the returned configuration; it is only // needed during loading, and its presence will cause problems in // config files that iterate through all of the sections (e.g. @@ -126,7 +131,21 @@ class PluginFactory implements AbstractFactoryInterface $config->$section = $child->$section; } else { foreach (array_keys($contents->toArray()) as $key) { - $config->$section->$key = $child->$section->$key; + // If a key is defined as key[] in the config file the key + // remains a Zend\Config\Config object. If the current + // section is not configured as an override section we try to + // merge the key[] values instead of overwriting them. + if (is_object($config->$section->$key) + && is_object($child->$section->$key) + && $mergeArraySettings + ) { + $config->$section->$key = array_merge( + $config->$section->$key->toArray(), + $child->$section->$key->toArray() + ); + } else { + $config->$section->$key = $child->$section->$key; + } } } } diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Config/PluginFactoryTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Config/PluginFactoryTest.php index 6dc109e172a..9d4c6b1650b 100644 --- a/module/VuFind/tests/unit-tests/src/VuFindTest/Config/PluginFactoryTest.php +++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Config/PluginFactoryTest.php @@ -75,20 +75,36 @@ class PluginFactoryTest extends \VuFindTest\Unit\TestCase . "[Section2]\n" . "d=4\ne=5\nf=6\n" . "[Section3]\n" - . "g=7\nh=8\ni=9\n"; + . "g=7\nh=8\ni=9\n" + . "[Section4]\n" + . "j[] = 1\nj[] = 2\nk[a] = 1\nk[b] = 2\n"; $childPath = Locator::getLocalConfigPath('unit-test-child.ini', null, true); $child = "[Section1]\n" . "j=10\nk=11\nl=12\n" . "[Section2]\n" . "m=13\nn=14\no=15\n" + . "[Section4]\n" + . "j[] = 3\nk[c] = 3\n" . "[Parent_Config]\n" . "path=\"{$parentPath}\"\n" . "override_full_sections=Section1\n"; + $child2Path = Locator::getLocalConfigPath('unit-test-child2.ini', null, true); + $child2 = "[Section1]\n" + . "j=10\nk=11\nl=12\n" + . "[Section2]\n" + . "m=13\nn=14\no=15\n" + . "[Section4]\n" + . "j[] = 3\nk[c] = 3\n" + . "[Parent_Config]\n" + . "path=\"{$parentPath}\"\n" + . "override_full_sections=Section1\n" + . "merge_array_settings=true\n"; // Fail if we are unable to write files: - if (null === $parentPath || null === $childPath + if (null === $parentPath || null === $childPath || null === $child2Path || !file_put_contents($parentPath, $parent) || !file_put_contents($childPath, $child) + || !file_put_contents($child2Path, $child2) ) { self::$writeFailed = true; return; @@ -175,6 +191,45 @@ class PluginFactoryTest extends \VuFindTest\Unit\TestCase // Make sure Section 3 was inherited; values from parent should exist. $this->assertEquals('7', $config->Section3->g); + + // Make sure Section 4 arrays were overwritten. + $this->assertEquals([3], $config->Section4->j->toArray()); + $this->assertEquals(['c' => 3], $config->Section4->k->toArray()); + } + + /** + * Test inheritance features with array merging turned on. + * + * @return void + */ + public function testInheritanceWithArrayMerging() + { + if (self::$writeFailed) { + $this->markTestSkipped('Could not write test configurations.'); + } + + // Make sure load succeeds: + $config = $this->getConfig('unit-test-child2'); + $this->assertTrue(is_object($config)); + + // Make sure Section 1 was overridden; values from parent should not be + // present. + $this->assertTrue(!isset($config->Section1->a)); + $this->assertEquals('10', $config->Section1->j); + + // Make sure Section 2 was merged; values from parent and child should + // both be present. + $this->assertEquals('4', $config->Section2->d); + $this->assertEquals('13', $config->Section2->m); + + // Make sure Section 3 was inherited; values from parent should exist. + $this->assertEquals('7', $config->Section3->g); + + // Make sure Section 4 arrays were overwritten. + $this->assertEquals([1, 2, 3], $config->Section4->j->toArray()); + $this->assertEquals( + ['a' => 1, 'b' => 2, 'c' => 3], $config->Section4->k->toArray() + ); } /** -- GitLab