This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
symfony/src/Symfony/Component/DependencyInjection/Compiler/ValidateEnvPlaceholdersPass.php
2018-03-27 08:02:00 +02:00

101 lines
3.7 KiB
PHP

<?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\Compiler;
use Symfony\Component\Config\Definition\BaseNode;
use Symfony\Component\Config\Definition\Processor;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterface;
use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
/**
* Validates environment variable placeholders used in extension configuration with dummy values.
*
* @author Roland Franssen <franssen.roland@gmail.com>
*/
class ValidateEnvPlaceholdersPass implements CompilerPassInterface
{
private static $typeFixtures = array('array' => array(), 'bool' => false, 'float' => 0.0, 'int' => 0, 'string' => '');
/**
* {@inheritdoc}
*/
public function process(ContainerBuilder $container)
{
if (!class_exists(BaseNode::class) || !$extensions = $container->getExtensions()) {
return;
}
$resolvingBag = $container->getParameterBag();
if (!$resolvingBag instanceof EnvPlaceholderParameterBag) {
return;
}
$defaultBag = new ParameterBag($container->getParameterBag()->all());
$envTypes = $resolvingBag->getProvidedTypes();
try {
foreach ($resolvingBag->getEnvPlaceholders() + $resolvingBag->getUnusedEnvPlaceholders() as $env => $placeholders) {
$prefix = (false === $i = strpos($env, ':')) ? 'string' : substr($env, 0, $i);
$types = $envTypes[$prefix] ?? array('string');
$default = ($hasEnv = (false === $i && $defaultBag->has("env($env)"))) ? $defaultBag->get("env($env)") : null;
if (null !== $default && !in_array($type = self::getType($default), $types, true)) {
throw new LogicException(sprintf('Invalid type for env parameter "env(%s)". Expected "%s", but got "%s".', $env, implode('", "', $types), $type));
}
$values = array();
foreach ($types as $type) {
$values[$type] = $hasEnv ? $default : self::$typeFixtures[$type] ?? null;
}
foreach ($placeholders as $placeholder) {
BaseNode::setPlaceholder($placeholder, $values);
}
}
$processor = new Processor();
foreach ($extensions as $name => $extension) {
if (!$extension instanceof ConfigurationExtensionInterface || !$config = $container->getExtensionConfig($name)) {
// this extension has no semantic configuration or was not called
continue;
}
$config = $resolvingBag->resolveValue($config);
if (null === $configuration = $extension->getConfiguration($config, $container)) {
continue;
}
$processor->processConfiguration($configuration, $config);
}
} finally {
BaseNode::resetPlaceholders();
}
}
private static function getType($value): string
{
switch ($type = \gettype($value)) {
case 'boolean':
return 'bool';
case 'double':
return 'float';
case 'integer':
return 'int';
}
return $type;
}
}