Skip to content

Commit

Permalink
[DependencyInjection] Reset env vars when resetting the container
Browse files Browse the repository at this point in the history
  • Loading branch information
faizanakram99 authored and fabpot committed May 2, 2024
1 parent ee8154c commit 429ca62
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ CHANGELOG
* [BC BREAK] When used in the `prependExtension()` method, the `ContainerConfigurator::import()` method now prepends the configuration instead of appending it
* Cast env vars to null or bool when referencing them using `#[Autowire(env: '...')]` depending on the signature of the corresponding parameter
* Add `#[AutowireInline]` attribute to allow service definition at the class level
* Add `StaticEnvVarLoader`

7.0
---
Expand Down
2 changes: 2 additions & 0 deletions Container.php
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,8 @@ public function reset(): void
continue;
}
}

$this->envCache = [];
}

/**
Expand Down
13 changes: 11 additions & 2 deletions EnvVarProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,18 @@
use Symfony\Component\DependencyInjection\Exception\EnvNotFoundException;
use Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Contracts\Service\ResetInterface;

/**
* @author Nicolas Grekas <p@tchwork.com>
*/
class EnvVarProcessor implements EnvVarProcessorInterface
class EnvVarProcessor implements EnvVarProcessorInterface, ResetInterface
{
private ContainerInterface $container;
/** @var \Traversable<EnvVarLoaderInterface> */
private \Traversable $loaders;
/** @var \Traversable<EnvVarLoaderInterface> */
private \Traversable $originalLoaders;
private array $loadedVars = [];

/**
Expand All @@ -31,7 +34,7 @@ class EnvVarProcessor implements EnvVarProcessorInterface
public function __construct(ContainerInterface $container, ?\Traversable $loaders = null)
{
$this->container = $container;
$this->loaders = $loaders ?? new \ArrayIterator();
$this->originalLoaders = $this->loaders = $loaders ?? new \ArrayIterator();
}

public static function getProvidedTypes(): array
Expand Down Expand Up @@ -366,4 +369,10 @@ public function getEnv(string $prefix, string $name, \Closure $getEnv): mixed

throw new RuntimeException(sprintf('Unsupported env var prefix "%s" for env name "%s".', $prefix, $name));
}

public function reset(): void
{
$this->loadedVars = [];
$this->loaders = $this->originalLoaders;
}
}
26 changes: 26 additions & 0 deletions StaticEnvVarLoader.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\DependencyInjection;

class StaticEnvVarLoader implements EnvVarLoaderInterface
{
private array $envVars;

public function __construct(private EnvVarLoaderInterface $envVarLoader)
{
}

public function loadEnvVars(): array
{
return $this->envVars ??= $this->envVarLoader->loadEnvVars();
}
}
64 changes: 63 additions & 1 deletion Tests/EnvVarProcessorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,68 @@ public function testGetEnvBool($value, $processed)
$this->assertSame($processed, $result);
}

public function testGetEnvCachesEnv()
{
$_ENV['FOO'] = '';

$GLOBALS['ENV_FOO'] = 'value';

$loaders = function () {
yield new class() implements EnvVarLoaderInterface {
public function loadEnvVars(): array
{
return ['FOO' => $GLOBALS['ENV_FOO']];
}
};
};

$processor = new EnvVarProcessor(new Container(), new RewindableGenerator($loaders, 1));

$noop = function () {};

$result = $processor->getEnv('string', 'FOO', $noop);
$this->assertSame('value', $result);

$GLOBALS['ENV_FOO'] = 'new value';

$result = $processor->getEnv('string', 'FOO', $noop);
$this->assertSame('value', $result);

unset($_ENV['FOO'], $GLOBALS['ENV_FOO']);
}

public function testReset()
{
$_ENV['FOO'] = '';

$GLOBALS['ENV_FOO'] = 'value';

$loaders = function () {
yield new class() implements EnvVarLoaderInterface {
public function loadEnvVars(): array
{
return ['FOO' => $GLOBALS['ENV_FOO']];
}
};
};

$processor = new EnvVarProcessor(new Container(), new RewindableGenerator($loaders, 1));

$noop = function () {};

$result = $processor->getEnv('string', 'FOO', $noop);
$this->assertSame('value', $result);

$GLOBALS['ENV_FOO'] = 'new value';

$processor->reset();

$result = $processor->getEnv('string', 'FOO', $noop);
$this->assertSame('new value', $result);

unset($_ENV['FOO'], $GLOBALS['ENV_FOO']);
}

/**
* @dataProvider validBools
*/
Expand Down Expand Up @@ -625,7 +687,7 @@ public static function validNullables()
['null', 'null'],
['Null', 'Null'],
['NULL', 'NULL'],
];
];
}

public function testRequireMissingFile()
Expand Down
40 changes: 40 additions & 0 deletions Tests/StaticEnvVarLoaderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\DependencyInjection\Tests;

use PHPUnit\Framework\TestCase;
use Symfony\Component\DependencyInjection\EnvVarLoaderInterface;
use Symfony\Component\DependencyInjection\StaticEnvVarLoader;

class StaticEnvVarLoaderTest extends TestCase
{
public function testLoadEnvVarsCachesInnerLoaderEnvVars()
{
$innerLoader = new class(['FOO' => 'BAR']) implements EnvVarLoaderInterface {
/** @param array<string, string> */
public function __construct(public array $envVars = [])
{
}

public function loadEnvVars(): array
{
return $this->envVars;
}
};

$loader = new StaticEnvVarLoader($innerLoader);
$this->assertSame(['FOO' => 'BAR'], $loader->loadEnvVars());

$innerLoader->envVars = ['BAR' => 'BAZ'];
$this->assertSame(['FOO' => 'BAR'], $loader->loadEnvVars());
}
}

0 comments on commit 429ca62

Please sign in to comment.