diff --git a/changelog/unreleased/40413 b/changelog/unreleased/40413 new file mode 100644 index 000000000000..ad82c5b612ee --- /dev/null +++ b/changelog/unreleased/40413 @@ -0,0 +1,11 @@ +Enhancement: Setting for recursive extra config.php search + +Before this change extra config.php files were required to be placed directly in the config folder. +This change allows to have nested folders configuration structure, +enabled by config value OC_CONFIG_EXTRA_RECURSIVE_SEARCH, that can be useful in some deployments. + +NOTE: due to the fact that `config_extra_recursive_search` setting controls the configuration itself, +it is only possible to enable this via environment variable. It is not possible to enable it with *.config.php file. + +https://github.com/owncloud/core/pull/40413 +https://github.com/owncloud/enterprise/issues/5406 diff --git a/lib/private/Config.php b/lib/private/Config.php index 2e7ff9357c53..dd5d7251c45f 100644 --- a/lib/private/Config.php +++ b/lib/private/Config.php @@ -216,6 +216,33 @@ protected function delete($key) { ], 'config', 'deletevalue'); } + /** + * This function scans for extra config.php files. + * + * NOTE: due to the fact that `config_extra_recursive_search` setting controls the configuration itself, + * it is only possible to enable this via environment variable. It is not possible to enable it with *.config.php file. + * + * @return string[] paths to extra config.php files + */ + private function findExtraConfigFiles() { + if ($this->getValue('config_extra_recursive_search', false) === 'true') { + $foundConfigFiles = []; + $configItr = new \RecursiveDirectoryIterator($this->configDir); + foreach (new \RecursiveIteratorIterator($configItr) as $file) { + // find all extra config files matching config file name, + // except for default config filepath + if (\preg_match("/{$this->configFileName}\$/", $file->getFileName()) && + $file->getPathName() !== $this->configFilePath) { + $foundConfigFiles[] = $file->getPathName(); + } + } + return $foundConfigFiles; + } else { + // default is to search in config directory (as of owncloud 10.11) + return \glob($this->configDir . '*.' . $this->configFileName); + } + } + /** * Loads the config file * @@ -228,7 +255,7 @@ private function readData() { $configFiles = [$this->configFilePath]; // Add all files in the config dir ending with the same file name - $extra = \glob($this->configDir.'*.'.$this->configFileName); + $extra = $this->findExtraConfigFiles(); if (\is_array($extra)) { \natsort($extra); $configFiles = \array_merge($configFiles, $extra); diff --git a/tests/lib/ConfigTest.php b/tests/lib/ConfigTest.php index c0b93cd79b4c..24e8dd2aa9bf 100644 --- a/tests/lib/ConfigTest.php +++ b/tests/lib/ConfigTest.php @@ -266,6 +266,48 @@ public function testConfigMerge() { \unlink($additionalConfigPath); } + public function providerNestedConfig() { + return [ + [true], + [false] + ]; + } + + /** + * @dataProvider providerNestedConfig + * + * @param boolean $configExtraRecursiveSearchEnabled + */ + public function testNestedConfig($configExtraRecursiveSearchEnabled) { + // enable recursive search for extra config files + if ($configExtraRecursiveSearchEnabled) { + \putenv('OC_config_extra_recursive_search=true'); + } + + // Create additional config in nested dir + \mkdir($this->randomTmpDir.'nested1', 0755, true); + $additionalConfig = '"totallyOutdated");'; + $additionalConfigPath = $this->randomTmpDir.'nested1/additionalConfig.testconfig.php'; + \file_put_contents($additionalConfigPath, $additionalConfig); + + // Reinstantiate the config to force a read-in of the additional configs + $this->config = new \OC\Config($this->randomTmpDir, 'testconfig.php'); + + if ($configExtraRecursiveSearchEnabled) { + // nested config got correctly read + $this->assertSame('totallyOutdated', $this->config->getValue('php53', 'defaultValue')); + $this->assertStringEqualsFile($this->configFile, self::TESTCONTENT); + } else { + // nested config got ignored + $this->assertSame('defaultValue', $this->config->getValue('php53', 'defaultValue')); + $this->assertStringEqualsFile($this->configFile, self::TESTCONTENT); + } + + // Cleanup + \putenv('OC_config_extra_recursive_search'); + \unlink($additionalConfigPath); + } + private function checkConfigMatchesExpected($expectedConfig) { foreach ($expectedConfig as $key => $value) { $this->assertEquals($value, $this->config->getValue($key));