Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e119aa6

Browse files
jderussenicolas-grekas
authored andcommitted
[DI] Fix EnvVar not loaded when Loader requires an env var
1 parent 642c7ff commit e119aa6

File tree

2 files changed

+68
-15
lines changed

2 files changed

+68
-15
lines changed

src/Symfony/Component/DependencyInjection/EnvVarProcessor.php

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,7 @@ class EnvVarProcessor implements EnvVarProcessorInterface
3030
public function __construct(ContainerInterface $container, \Traversable $loaders = null)
3131
{
3232
$this->container = $container;
33-
$this->loaders = new \IteratorIterator($loaders ?? new \ArrayIterator());
34-
$this->loaders = $this->loaders->getInnerIterator();
33+
$this->loaders = $loaders ?? new \ArrayIterator();
3534
}
3635

3736
/**
@@ -141,20 +140,32 @@ public function getEnv($prefix, $name, \Closure $getEnv)
141140
}
142141
}
143142

144-
$loaders = $this->loaders;
145-
$this->loaders = new \ArrayIterator();
146-
147-
try {
148-
while ((false === $env || null === $env) && $loaders->valid()) {
149-
$loader = $loaders->current();
150-
$loaders->next();
151-
$this->loadedVars[] = $vars = $loader->loadEnvVars();
152-
$env = $vars[$name] ?? false;
143+
if (false === $env || null === $env) {
144+
$loaders = $this->loaders;
145+
$this->loaders = new \ArrayIterator();
146+
147+
try {
148+
$i = 0;
149+
$ended = true;
150+
$count = $loaders instanceof \Countable ? $loaders->count() : 0;
151+
foreach ($loaders as $loader) {
152+
if (\count($this->loadedVars) > $i++) {
153+
continue;
154+
}
155+
$this->loadedVars[] = $vars = $loader->loadEnvVars();
156+
if (false !== $env = $vars[$name] ?? false) {
157+
$ended = false;
158+
break;
159+
}
160+
}
161+
if ($ended || $count === $i) {
162+
$loaders = $this->loaders;
163+
}
164+
} catch (ParameterCircularReferenceException $e) {
165+
// skip loaders that need an env var that is not defined
166+
} finally {
167+
$this->loaders = $loaders;
153168
}
154-
} catch (ParameterCircularReferenceException $e) {
155-
// skip loaders that need an env var that is not defined
156-
} finally {
157-
$this->loaders = $loaders;
158169
}
159170

160171
if (false === $env || null === $env) {

src/Symfony/Component/DependencyInjection/Tests/EnvVarProcessorTest.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33
namespace Symfony\Component\DependencyInjection\Tests;
44

55
use PHPUnit\Framework\TestCase;
6+
use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
67
use Symfony\Component\DependencyInjection\Container;
78
use Symfony\Component\DependencyInjection\ContainerBuilder;
89
use Symfony\Component\DependencyInjection\EnvVarLoaderInterface;
910
use Symfony\Component\DependencyInjection\EnvVarProcessor;
11+
use Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException;
1012

1113
class EnvVarProcessorTest extends TestCase
1214
{
@@ -553,4 +555,44 @@ public function loadEnvVars(): array
553555
$result = $processor->getEnv('string', 'FOO_ENV_LOADER', function () {});
554556
$this->assertSame('123', $result); // check twice
555557
}
558+
559+
public function testCircularEnvLoader()
560+
{
561+
$container = new ContainerBuilder();
562+
$container->setParameter('env(FOO_CONTAINER)', 'foo');
563+
$container->compile();
564+
565+
$index = 0;
566+
$loaders = function () use (&$index) {
567+
if (0 === $index++) {
568+
throw new ParameterCircularReferenceException(['FOO_CONTAINER']);
569+
}
570+
571+
yield new class() implements EnvVarLoaderInterface {
572+
public function loadEnvVars(): array
573+
{
574+
return [
575+
'FOO_ENV_LOADER' => '123',
576+
];
577+
}
578+
};
579+
};
580+
581+
$processor = new EnvVarProcessor($container, new RewindableGenerator($loaders, 1));
582+
583+
$result = $processor->getEnv('string', 'FOO_CONTAINER', function () {});
584+
$this->assertSame('foo', $result);
585+
586+
$result = $processor->getEnv('string', 'FOO_ENV_LOADER', function () {});
587+
$this->assertSame('123', $result);
588+
589+
$result = $processor->getEnv('default', ':BAR_CONTAINER', function ($name) use ($processor) {
590+
$this->assertSame('BAR_CONTAINER', $name);
591+
592+
return $processor->getEnv('string', $name, function () {});
593+
});
594+
$this->assertNull($result);
595+
596+
$this->assertSame(2, $index);
597+
}
556598
}

0 commit comments

Comments
 (0)