Skip to content

Commit

Permalink
OXDEV-8715 Environment loader
Browse files Browse the repository at this point in the history
  • Loading branch information
AshrafOxid committed Dec 13, 2024
1 parent 5a2023e commit e3af1f4
Show file tree
Hide file tree
Showing 10 changed files with 162 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .env.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
OXID_ENV=prod
OXID_DEBUG=false
1 change: 1 addition & 0 deletions CHANGELOG-7.3.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
### Added
- PHPUnit v11 support
- Category detail page codeception test
- Registration of environment variables via Symfony Dotenv Component

### Fixed
- Shop ID resolution considers SSL language URLs
Expand Down
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
34 changes: 34 additions & 0 deletions source/Internal/Framework/Env/DotenvLoader.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

/**
* Copyright © OXID eSales AG. All rights reserved.
* See LICENSE file for license details.
*/

declare(strict_types=1);

namespace OxidEsales\EshopCommunity\Internal\Framework\Env;

use Symfony\Component\Dotenv\Dotenv;
use Symfony\Component\Filesystem\Path;

class DotenvLoader
{
private string $envKey = 'OXID_ENV';
private string $debugKey = 'OXID_DEBUG';
private string $envFile = '.env';

public function __construct(private readonly string $pathToEnvFiles)
{
}

public function loadEnvironmentVariables(): void
{
$dotEnv = new Dotenv($this->envKey, $this->debugKey);
$dotEnv
->usePutenv()
->loadEnv(
Path::join($this->pathToEnvFiles, $this->envFile)
);
}
}
4 changes: 4 additions & 0 deletions source/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down Expand Up @@ -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();
9 changes: 9 additions & 0 deletions tests/ContainerTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
Expand Down Expand Up @@ -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'));
}
}
30 changes: 30 additions & 0 deletions tests/EnvTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

/**
* Copyright © OXID eSales AG. All rights reserved.
* See LICENSE file for license details.
*/

declare(strict_types=1);

namespace OxidEsales\EshopCommunity\Tests;

use OxidEsales\EshopCommunity\Internal\Framework\Env\DotenvLoader;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Filesystem\Path;

/**
* Run tests that modify env values in a separate process
* to avoid discrepancy between getenv('value') and $_ENV['value']
*/
trait EnvTrait
{
private function loadEnvFixture(string $fixtureDir, array $envFileLines): void
{
$filesystem = new Filesystem();
$fixtureFile = Path::join($fixtureDir, '.env');
$filesystem->dumpFile($fixtureFile, implode("\n", $envFileLines),);
(new DotenvLoader($fixtureDir))->loadEnvironmentVariables();
$filesystem->remove($fixtureFile);
}
}
76 changes: 76 additions & 0 deletions tests/Integration/Internal/Framework/Env/EnvLoaderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php

/**
* Copyright © OXID eSales AG. All rights reserved.
* See LICENSE file for license details.
*/

declare(strict_types=1);

namespace OxidEsales\EshopCommunity\Tests\Integration\Internal\Framework\Env;

use OxidEsales\EshopCommunity\Tests\ContainerTrait;
use OxidEsales\EshopCommunity\Tests\EnvTrait;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Filesystem\Path;

final class EnvLoaderTest extends TestCase
{
use ContainerTrait;
use EnvTrait;

private string $dotEnvFixture = '';
private string $fixtures = __DIR__ . '/Fixtures/EnvLoader';
private string $appEnvKey = 'OXID_ENV';
private string $serializedEnvKey = 'SERIALIZED_VALUE_KEY';
private string $serializedParameterKey = 'serialized_value_key';


public function setUp(): void
{
parent::setUp();
$this->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]);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
parameters:
serialized_value_key: '%env(json:SERIALIZED_VALUE_KEY)%'
3 changes: 3 additions & 0 deletions tests/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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();

0 comments on commit e3af1f4

Please sign in to comment.