Skip to content

Commit

Permalink
[DI][FrameworkBundle] add EnvVarLoaderInterface - remove SecretEnvVar…
Browse files Browse the repository at this point in the history
…Processor
  • Loading branch information
nicolas-grekas committed Nov 8, 2019
1 parent 4f493e1 commit d1659b9
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 6 deletions.
2 changes: 1 addition & 1 deletion Compiler/CheckTypeDeclarationsPass.php
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ private function checkType(Definition $checkedDefinition, $value, \ReflectionPar
$checkFunction = sprintf('is_%s', $parameter->getType()->getName());

if (!$parameter->getType()->isBuiltin() || !$checkFunction($value)) {
throw new InvalidParameterTypeException($this->currentId, \gettype($value), $parameter);
throw new InvalidParameterTypeException($this->currentId, \is_object($value) ? \get_class($value) : \gettype($value), $parameter);
}
}
}
25 changes: 25 additions & 0 deletions EnvVarLoaderInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?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;

/**
* EnvVarLoaderInterface objects return key/value pairs that are added to the list of available env vars.
*
* @author Nicolas Grekas <p@tchwork.com>
*/
interface EnvVarLoaderInterface
{
/**
* @return string[] Key/value pairs that can be accessed using the regular "%env()%" syntax
*/
public function loadEnvVars(): array;
}
37 changes: 32 additions & 5 deletions EnvVarProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
namespace Symfony\Component\DependencyInjection;

use Symfony\Component\DependencyInjection\Exception\EnvNotFoundException;
use Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;

/**
Expand All @@ -20,10 +21,17 @@
class EnvVarProcessor implements EnvVarProcessorInterface
{
private $container;
private $loaders;
private $loadedVars = [];

public function __construct(ContainerInterface $container)
/**
* @param EnvVarLoaderInterface[] $loaders
*/
public function __construct(ContainerInterface $container, \Traversable $loaders = null)
{
$this->container = $container;
$this->loaders = new \IteratorIterator($loaders ?? new \ArrayIterator());
$this->loaders = $this->loaders->getInnerIterator();
}

/**
Expand Down Expand Up @@ -127,12 +135,31 @@ public function getEnv($prefix, $name, \Closure $getEnv)
} elseif (isset($_SERVER[$name]) && 0 !== strpos($name, 'HTTP_')) {
$env = $_SERVER[$name];
} elseif (false === ($env = getenv($name)) || null === $env) { // null is a possible value because of thread safety issues
if (!$this->container->hasParameter("env($name)")) {
throw new EnvNotFoundException(sprintf('Environment variable not found: "%s".', $name));
foreach ($this->loadedVars as $vars) {
if (false !== $env = ($vars[$name] ?? false)) {
break;
}
}

if (null === $env = $this->container->getParameter("env($name)")) {
return null;
try {
while ((false === $env || null === $env) && $this->loaders->valid()) {
$loader = $this->loaders->current();
$this->loaders->next();
$this->loadedVars[] = $vars = $loader->loadEnvVars();
$env = $vars[$name] ?? false;
}
} catch (ParameterCircularReferenceException $e) {
// skip loaders that need an env var that is not defined
}

if (false === $env || null === $env) {
if (!$this->container->hasParameter("env($name)")) {
throw new EnvNotFoundException(sprintf('Environment variable not found: "%s".', $name));
}

if (null === $env = $this->container->getParameter("env($name)")) {
return null;
}
}
}

Expand Down
36 changes: 36 additions & 0 deletions Tests/EnvVarProcessorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use PHPUnit\Framework\TestCase;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\EnvVarLoaderInterface;
use Symfony\Component\DependencyInjection\EnvVarProcessor;

class EnvVarProcessorTest extends TestCase
Expand Down Expand Up @@ -517,4 +518,39 @@ public function validCsv()
[null, null],
];
}

public function testEnvLoader()
{
$loaders = function () {
yield new class() implements EnvVarLoaderInterface {
public function loadEnvVars(): array
{
return [
'FOO_ENV_LOADER' => '123',
];
}
};

yield new class() implements EnvVarLoaderInterface {
public function loadEnvVars(): array
{
return [
'FOO_ENV_LOADER' => '234',
'BAR_ENV_LOADER' => '456',
];
}
};
};

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

$result = $processor->getEnv('string', 'FOO_ENV_LOADER', function () {});
$this->assertSame('123', $result);

$result = $processor->getEnv('string', 'BAR_ENV_LOADER', function () {});
$this->assertSame('456', $result);

$result = $processor->getEnv('string', 'FOO_ENV_LOADER', function () {});
$this->assertSame('123', $result); // check twice
}
}

0 comments on commit d1659b9

Please sign in to comment.