Skip to content

Commit 429ca62

Browse files
faizanakram99fabpot
authored andcommitted
[DependencyInjection] Reset env vars when resetting the container
1 parent ee8154c commit 429ca62

File tree

6 files changed

+143
-3
lines changed

6 files changed

+143
-3
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ CHANGELOG
1414
* [BC BREAK] When used in the `prependExtension()` method, the `ContainerConfigurator::import()` method now prepends the configuration instead of appending it
1515
* Cast env vars to null or bool when referencing them using `#[Autowire(env: '...')]` depending on the signature of the corresponding parameter
1616
* Add `#[AutowireInline]` attribute to allow service definition at the class level
17+
* Add `StaticEnvVarLoader`
1718

1819
7.0
1920
---

Container.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,8 @@ public function reset(): void
287287
continue;
288288
}
289289
}
290+
291+
$this->envCache = [];
290292
}
291293

292294
/**

EnvVarProcessor.php

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,18 @@
1414
use Symfony\Component\DependencyInjection\Exception\EnvNotFoundException;
1515
use Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException;
1616
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
17+
use Symfony\Contracts\Service\ResetInterface;
1718

1819
/**
1920
* @author Nicolas Grekas <[email protected]>
2021
*/
21-
class EnvVarProcessor implements EnvVarProcessorInterface
22+
class EnvVarProcessor implements EnvVarProcessorInterface, ResetInterface
2223
{
2324
private ContainerInterface $container;
2425
/** @var \Traversable<EnvVarLoaderInterface> */
2526
private \Traversable $loaders;
27+
/** @var \Traversable<EnvVarLoaderInterface> */
28+
private \Traversable $originalLoaders;
2629
private array $loadedVars = [];
2730

2831
/**
@@ -31,7 +34,7 @@ class EnvVarProcessor implements EnvVarProcessorInterface
3134
public function __construct(ContainerInterface $container, ?\Traversable $loaders = null)
3235
{
3336
$this->container = $container;
34-
$this->loaders = $loaders ?? new \ArrayIterator();
37+
$this->originalLoaders = $this->loaders = $loaders ?? new \ArrayIterator();
3538
}
3639

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

367370
throw new RuntimeException(sprintf('Unsupported env var prefix "%s" for env name "%s".', $prefix, $name));
368371
}
372+
373+
public function reset(): void
374+
{
375+
$this->loadedVars = [];
376+
$this->loaders = $this->originalLoaders;
377+
}
369378
}

StaticEnvVarLoader.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\DependencyInjection;
13+
14+
class StaticEnvVarLoader implements EnvVarLoaderInterface
15+
{
16+
private array $envVars;
17+
18+
public function __construct(private EnvVarLoaderInterface $envVarLoader)
19+
{
20+
}
21+
22+
public function loadEnvVars(): array
23+
{
24+
return $this->envVars ??= $this->envVarLoader->loadEnvVars();
25+
}
26+
}

Tests/EnvVarProcessorTest.php

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,68 @@ public function testGetEnvBool($value, $processed)
136136
$this->assertSame($processed, $result);
137137
}
138138

139+
public function testGetEnvCachesEnv()
140+
{
141+
$_ENV['FOO'] = '';
142+
143+
$GLOBALS['ENV_FOO'] = 'value';
144+
145+
$loaders = function () {
146+
yield new class() implements EnvVarLoaderInterface {
147+
public function loadEnvVars(): array
148+
{
149+
return ['FOO' => $GLOBALS['ENV_FOO']];
150+
}
151+
};
152+
};
153+
154+
$processor = new EnvVarProcessor(new Container(), new RewindableGenerator($loaders, 1));
155+
156+
$noop = function () {};
157+
158+
$result = $processor->getEnv('string', 'FOO', $noop);
159+
$this->assertSame('value', $result);
160+
161+
$GLOBALS['ENV_FOO'] = 'new value';
162+
163+
$result = $processor->getEnv('string', 'FOO', $noop);
164+
$this->assertSame('value', $result);
165+
166+
unset($_ENV['FOO'], $GLOBALS['ENV_FOO']);
167+
}
168+
169+
public function testReset()
170+
{
171+
$_ENV['FOO'] = '';
172+
173+
$GLOBALS['ENV_FOO'] = 'value';
174+
175+
$loaders = function () {
176+
yield new class() implements EnvVarLoaderInterface {
177+
public function loadEnvVars(): array
178+
{
179+
return ['FOO' => $GLOBALS['ENV_FOO']];
180+
}
181+
};
182+
};
183+
184+
$processor = new EnvVarProcessor(new Container(), new RewindableGenerator($loaders, 1));
185+
186+
$noop = function () {};
187+
188+
$result = $processor->getEnv('string', 'FOO', $noop);
189+
$this->assertSame('value', $result);
190+
191+
$GLOBALS['ENV_FOO'] = 'new value';
192+
193+
$processor->reset();
194+
195+
$result = $processor->getEnv('string', 'FOO', $noop);
196+
$this->assertSame('new value', $result);
197+
198+
unset($_ENV['FOO'], $GLOBALS['ENV_FOO']);
199+
}
200+
139201
/**
140202
* @dataProvider validBools
141203
*/
@@ -625,7 +687,7 @@ public static function validNullables()
625687
['null', 'null'],
626688
['Null', 'Null'],
627689
['NULL', 'NULL'],
628-
];
690+
];
629691
}
630692

631693
public function testRequireMissingFile()

Tests/StaticEnvVarLoaderTest.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\DependencyInjection\Tests;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\DependencyInjection\EnvVarLoaderInterface;
16+
use Symfony\Component\DependencyInjection\StaticEnvVarLoader;
17+
18+
class StaticEnvVarLoaderTest extends TestCase
19+
{
20+
public function testLoadEnvVarsCachesInnerLoaderEnvVars()
21+
{
22+
$innerLoader = new class(['FOO' => 'BAR']) implements EnvVarLoaderInterface {
23+
/** @param array<string, string> */
24+
public function __construct(public array $envVars = [])
25+
{
26+
}
27+
28+
public function loadEnvVars(): array
29+
{
30+
return $this->envVars;
31+
}
32+
};
33+
34+
$loader = new StaticEnvVarLoader($innerLoader);
35+
$this->assertSame(['FOO' => 'BAR'], $loader->loadEnvVars());
36+
37+
$innerLoader->envVars = ['BAR' => 'BAZ'];
38+
$this->assertSame(['FOO' => 'BAR'], $loader->loadEnvVars());
39+
}
40+
}

0 commit comments

Comments
 (0)