From eed3cf817838aa3e18eeeefb6cf4cf09a8d1783a Mon Sep 17 00:00:00 2001 From: ashraf Date: Thu, 12 Dec 2024 16:28:55 +0100 Subject: [PATCH] OXDEV-8715 Environment loader --- CHANGELOG-7.3.md | 1 + composer.json | 1 + .../Internal/Framework/Env/DotenvLoader.php | 33 ++++++++ source/bootstrap.php | 4 + tests/ContainerTrait.php | 9 +++ tests/EnvTrait.php | 30 ++++++++ .../Internal/Framework/Env/EnvLoaderTest.php | 76 +++++++++++++++++++ .../Env/Fixtures/EnvLoader/services.yaml | 2 + tests/bootstrap.php | 3 + 9 files changed, 159 insertions(+) create mode 100644 source/Internal/Framework/Env/DotenvLoader.php create mode 100644 tests/EnvTrait.php create mode 100644 tests/Integration/Internal/Framework/Env/EnvLoaderTest.php create mode 100644 tests/Integration/Internal/Framework/Env/Fixtures/EnvLoader/services.yaml diff --git a/CHANGELOG-7.3.md b/CHANGELOG-7.3.md index 0a595c3ce5..0863301ce6 100644 --- a/CHANGELOG-7.3.md +++ b/CHANGELOG-7.3.md @@ -5,6 +5,7 @@ ### Added - PHPUnit v11 support - Category detail page codeception test +- Registration of environment variables via .env file ### Fixed - Shop ID resolution considers SSL language URLs diff --git a/composer.json b/composer.json index dfd5d82b69..2ea37498ed 100644 --- a/composer.json +++ b/composer.json @@ -32,6 +32,7 @@ "symfony/config": "^6.4", "symfony/console": "^6.4", "symfony/dependency-injection": "^6.4", + "symfony/dotenv": "^6.4", "symfony/event-dispatcher": "^6.4", "symfony/expression-language": "^6.4", "symfony/filesystem": "^6.4", diff --git a/source/Internal/Framework/Env/DotenvLoader.php b/source/Internal/Framework/Env/DotenvLoader.php new file mode 100644 index 0000000000..6eb9e2dadf --- /dev/null +++ b/source/Internal/Framework/Env/DotenvLoader.php @@ -0,0 +1,33 @@ +envKey); + $dotEnv + ->usePutenv() + ->loadEnv( + Path::join($this->pathToEnvFiles, $this->envFile) + ); + } +} \ No newline at end of file diff --git a/source/bootstrap.php b/source/bootstrap.php index 5db849c9c2..660c0750b5 100644 --- a/source/bootstrap.php +++ b/source/bootstrap.php @@ -5,6 +5,8 @@ * See LICENSE file for license details. */ +use OxidEsales\EshopCommunity\Internal\Framework\Env\DotenvLoader; + define('INSTALLATION_ROOT_PATH', dirname(__DIR__)); define('OX_BASE_PATH', INSTALLATION_ROOT_PATH . DIRECTORY_SEPARATOR . 'source' . DIRECTORY_SEPARATOR); define('OX_LOG_FILE', OX_BASE_PATH . 'log' . DIRECTORY_SEPARATOR . 'oxideshop.log'); @@ -219,3 +221,5 @@ public function isDebugMode() ini_set('session.use_cookies', 0); ini_set('session.use_trans_sid', 0); ini_set('url_rewriter.tags', ''); + +(new DotenvLoader(INSTALLATION_ROOT_PATH))->loadEnvironmentVariables(); diff --git a/tests/ContainerTrait.php b/tests/ContainerTrait.php index f7c44af44b..b29126bc1c 100644 --- a/tests/ContainerTrait.php +++ b/tests/ContainerTrait.php @@ -11,7 +11,10 @@ use OxidEsales\EshopCommunity\Internal\Container\ContainerFactory; use ReflectionClass; +use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\Container; +use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; +use Symfony\Component\Filesystem\Path; use UnitEnum; /** @@ -73,4 +76,10 @@ private function attachContainerToContainerFactory(): void $reflectionProperty = $reflectionClass->getProperty('symfonyContainer'); $reflectionProperty->setValue(ContainerFactory::getInstance(), $this->container); } + + private function loadYamlFixture(string $fixtureDir): void + { + $loader = new YamlFileLoader($this->container, new FileLocator(__DIR__)); + $loader->load(Path::join($fixtureDir, 'services.yaml')); + } } diff --git a/tests/EnvTrait.php b/tests/EnvTrait.php new file mode 100644 index 0000000000..dff24fc1ec --- /dev/null +++ b/tests/EnvTrait.php @@ -0,0 +1,30 @@ +dumpFile($fixtureFile, implode("\n", $envFileLines),); + (new DotenvLoader($fixtureDir))->loadEnvironmentVariables(); + $filesystem->remove($fixtureFile); + } +} \ No newline at end of file diff --git a/tests/Integration/Internal/Framework/Env/EnvLoaderTest.php b/tests/Integration/Internal/Framework/Env/EnvLoaderTest.php new file mode 100644 index 0000000000..2797bef788 --- /dev/null +++ b/tests/Integration/Internal/Framework/Env/EnvLoaderTest.php @@ -0,0 +1,76 @@ +dotEnvFixture = Path::join($this->fixtures, '.env'); + } + + public function tearDown(): void + { + (new Filesystem())->remove($this->dotEnvFixture); + parent::tearDown(); + } + + public function testApplicationEnvironmentIsDefined(): void + { + $currentEnvironment = getenv($this->appEnvKey); + + $this->assertNotEmpty($currentEnvironment); + } + + public function testApplicationEnvironmentCanBeRedefined(): void + { + $someValue = uniqid('some-value', true); + $this->loadEnvFixture($this->fixtures, ["$this->appEnvKey=$someValue"]); + + $currentEnvironment = getenv($this->appEnvKey); + + $this->assertEquals($someValue, $currentEnvironment); + } + + public function testJsonDSNsWithSpecialCharactersWillBeParsedAsArray(): void + { + $somePassword = '"\[(üÄ\\" *123,.;)::""'; + $dsnString = "mysql://username:$somePassword@123.255.255.255:3306/db-name?charset=utf8&driverOptions[1002]=\"SET @@SESSION.sql_mode=\"\"\""; + $serializedValue = json_encode( + [$dsnString, $dsnString, $dsnString], + JSON_THROW_ON_ERROR + ); + $this->loadEnvFixture($this->fixtures, ["$this->serializedEnvKey='$serializedValue'"]); + $this->createContainer(); + $this->loadYamlFixture($this->fixtures); + $this->compileContainer(); + + $containerParameter = $this->getParameter($this->serializedParameterKey); + + $this->assertEquals($dsnString, $containerParameter[2]); + } +} \ No newline at end of file diff --git a/tests/Integration/Internal/Framework/Env/Fixtures/EnvLoader/services.yaml b/tests/Integration/Internal/Framework/Env/Fixtures/EnvLoader/services.yaml new file mode 100644 index 0000000000..97bc475202 --- /dev/null +++ b/tests/Integration/Internal/Framework/Env/Fixtures/EnvLoader/services.yaml @@ -0,0 +1,2 @@ +parameters: + serialized_value_key: '%env(json:SERIALIZED_VALUE_KEY)%' \ No newline at end of file diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 2a27831eb5..e7e2c62f17 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -8,6 +8,7 @@ use OxidEsales\Eshop\Core\ConfigFile; use OxidEsales\Eshop\Core\Registry; use \Symfony\Component\Filesystem\Path; +use OxidEsales\EshopCommunity\Internal\Framework\Env\DotenvLoader; # Yes, adding a directory separator is stupid, but that's how the code expects it define('OX_BASE_PATH', Path::join(INSTALLATION_ROOT_PATH, 'source') . DIRECTORY_SEPARATOR); @@ -41,3 +42,5 @@ // Configure Registry $configFile = new ConfigFile(Path::join(OX_BASE_PATH, 'config.inc.php')); Registry::set(ConfigFile::class, $configFile); + +(new DotenvLoader(INSTALLATION_ROOT_PATH))->loadEnvironmentVariables(); \ No newline at end of file