EnvVarProcessor.php 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\DependencyInjection;
  11. use Symfony\Component\Config\Util\XmlUtils;
  12. use Symfony\Component\DependencyInjection\Exception\EnvNotFoundException;
  13. use Symfony\Component\DependencyInjection\Exception\RuntimeException;
  14. /**
  15. * @author Nicolas Grekas <p@tchwork.com>
  16. */
  17. class EnvVarProcessor implements EnvVarProcessorInterface
  18. {
  19. private $container;
  20. public function __construct(ContainerInterface $container)
  21. {
  22. $this->container = $container;
  23. }
  24. /**
  25. * {@inheritdoc}
  26. */
  27. public static function getProvidedTypes()
  28. {
  29. return array(
  30. 'base64' => 'string',
  31. 'bool' => 'bool',
  32. 'const' => 'bool|int|float|string|array',
  33. 'file' => 'string',
  34. 'float' => 'float',
  35. 'int' => 'int',
  36. 'json' => 'array',
  37. 'resolve' => 'string',
  38. 'string' => 'string',
  39. );
  40. }
  41. /**
  42. * {@inheritdoc}
  43. */
  44. public function getEnv($prefix, $name, \Closure $getEnv)
  45. {
  46. $i = strpos($name, ':');
  47. if ('file' === $prefix) {
  48. if (!is_scalar($file = $getEnv($name))) {
  49. throw new RuntimeException(sprintf('Invalid file name: env var "%s" is non-scalar.', $name));
  50. }
  51. if (!file_exists($file)) {
  52. throw new RuntimeException(sprintf('Env "file:%s" not found: %s does not exist.', $name, $file));
  53. }
  54. return file_get_contents($file);
  55. }
  56. if (false !== $i || 'string' !== $prefix) {
  57. if (null === $env = $getEnv($name)) {
  58. return;
  59. }
  60. } elseif (isset($_ENV[$name])) {
  61. $env = $_ENV[$name];
  62. } elseif (isset($_SERVER[$name]) && 0 !== strpos($name, 'HTTP_')) {
  63. $env = $_SERVER[$name];
  64. } elseif (false === ($env = getenv($name)) || null === $env) { // null is a possible value because of thread safety issues
  65. if (!$this->container->hasParameter("env($name)")) {
  66. throw new EnvNotFoundException($name);
  67. }
  68. if (null === $env = $this->container->getParameter("env($name)")) {
  69. return;
  70. }
  71. }
  72. if (!is_scalar($env)) {
  73. throw new RuntimeException(sprintf('Non-scalar env var "%s" cannot be cast to %s.', $name, $prefix));
  74. }
  75. if ('string' === $prefix) {
  76. return (string) $env;
  77. }
  78. if ('bool' === $prefix) {
  79. return (bool) self::phpize($env);
  80. }
  81. if ('int' === $prefix) {
  82. if (!is_numeric($env = self::phpize($env))) {
  83. throw new RuntimeException(sprintf('Non-numeric env var "%s" cannot be cast to int.', $name));
  84. }
  85. return (int) $env;
  86. }
  87. if ('float' === $prefix) {
  88. if (!is_numeric($env = self::phpize($env))) {
  89. throw new RuntimeException(sprintf('Non-numeric env var "%s" cannot be cast to float.', $name));
  90. }
  91. return (float) $env;
  92. }
  93. if ('const' === $prefix) {
  94. if (!defined($env)) {
  95. throw new RuntimeException(sprintf('Env var "%s" maps to undefined constant "%s".', $name, $env));
  96. }
  97. return constant($env);
  98. }
  99. if ('base64' === $prefix) {
  100. return base64_decode($env);
  101. }
  102. if ('json' === $prefix) {
  103. $env = json_decode($env, true);
  104. if (JSON_ERROR_NONE !== json_last_error()) {
  105. throw new RuntimeException(sprintf('Invalid JSON in env var "%s": '.json_last_error_msg(), $name));
  106. }
  107. if (!is_array($env)) {
  108. throw new RuntimeException(sprintf('Invalid JSON env var "%s": array expected, %s given.', $name, gettype($env)));
  109. }
  110. return $env;
  111. }
  112. if ('resolve' === $prefix) {
  113. return preg_replace_callback('/%%|%([^%\s]+)%/', function ($match) use ($name) {
  114. if (!isset($match[1])) {
  115. return '%';
  116. }
  117. $value = $this->container->getParameter($match[1]);
  118. if (!is_scalar($value)) {
  119. throw new RuntimeException(sprintf('Parameter "%s" found when resolving env var "%s" must be scalar, "%s" given.', $match[1], $name, gettype($value)));
  120. }
  121. return $value;
  122. }, $env);
  123. }
  124. throw new RuntimeException(sprintf('Unsupported env var prefix "%s".', $prefix));
  125. }
  126. private static function phpize($value)
  127. {
  128. if (!class_exists(XmlUtils::class)) {
  129. throw new RuntimeException('The Symfony Config component is required to cast env vars to "bool", "int" or "float".');
  130. }
  131. return XmlUtils::phpize($value);
  132. }
  133. }