From 169d32f0ba7bc17d67f8133016c44624d54a0c97 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 23 May 2023 17:24:39 +0200 Subject: [PATCH 01/14] [7.0] Bump to PHP 8.2 minimum --- composer.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/composer.json b/composer.json index 42cdbb2..02d1c2f 100644 --- a/composer.json +++ b/composer.json @@ -16,18 +16,18 @@ } ], "require": { - "php": ">=8.1", + "php": ">=8.2", "composer-plugin-api": "^1.0|^2.0" }, "require-dev": { "composer/composer": "^1.0.2|^2.0", - "symfony/console": "^5.4|^6.0|^7.0", - "symfony/dotenv": "^5.4|^6.0|^7.0", - "symfony/http-foundation": "^5.4|^6.0|^7.0", - "symfony/http-kernel": "^5.4|^6.0|^7.0" + "symfony/console": "^6.4|^7.0", + "symfony/dotenv": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0" }, "conflict": { - "symfony/dotenv": "<5.4" + "symfony/dotenv": "<6.4" }, "autoload": { "psr-4": { From fa4fae1684550afbfc8c43322e2e19df767f7520 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Tue, 13 Jun 2023 13:07:33 +0200 Subject: [PATCH 02/14] [Console] Remove deprecations across the component --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 02d1c2f..fa9c2cb 100644 --- a/composer.json +++ b/composer.json @@ -20,7 +20,7 @@ "composer-plugin-api": "^1.0|^2.0" }, "require-dev": { - "composer/composer": "^1.0.2|^2.0", + "composer/composer": "^2.6", "symfony/console": "^6.4|^7.0", "symfony/dotenv": "^6.4|^7.0", "symfony/http-foundation": "^6.4|^7.0", From 111d506d054150afda5f8adefa6432b18e7e8bae Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 21 Jul 2023 15:36:26 +0200 Subject: [PATCH 03/14] Add types to public and protected properties --- GenericRuntime.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GenericRuntime.php b/GenericRuntime.php index f1b3254..acec065 100644 --- a/GenericRuntime.php +++ b/GenericRuntime.php @@ -46,7 +46,7 @@ class_exists(ClosureResolver::class); */ class GenericRuntime implements RuntimeInterface { - protected $options; + protected array $options; /** * @param array { From ca3e5c6a515f36b1fc2996b12ec04e512a3457b8 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Thu, 20 Jun 2024 17:52:34 +0200 Subject: [PATCH 04/14] Prefix all sprintf() calls --- GenericRuntime.php | 6 +++--- Internal/ComposerPlugin.php | 2 +- Resolver/DebugClosureResolver.php | 2 +- Runner/ClosureRunner.php | 2 +- SymfonyRuntime.php | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/GenericRuntime.php b/GenericRuntime.php index 789d0bc..4a318b6 100644 --- a/GenericRuntime.php +++ b/GenericRuntime.php @@ -125,14 +125,14 @@ public function getRunner(?object $application): RunnerInterface } if (!\is_callable($application)) { - throw new \LogicException(sprintf('"%s" doesn\'t know how to handle apps of type "%s".', get_debug_type($this), get_debug_type($application))); + throw new \LogicException(\sprintf('"%s" doesn\'t know how to handle apps of type "%s".', get_debug_type($this), get_debug_type($application))); } $application = $application(...); } if ($_SERVER[$this->options['debug_var_name']] && ($r = new \ReflectionFunction($application)) && $r->getNumberOfRequiredParameters()) { - throw new \ArgumentCountError(sprintf('Zero argument should be required by the runner callable, but at least one is in "%s" on line "%d.', $r->getFileName(), $r->getStartLine())); + throw new \ArgumentCountError(\sprintf('Zero argument should be required by the runner callable, but at least one is in "%s" on line "%d.', $r->getFileName(), $r->getStartLine())); } return new ClosureRunner($application); @@ -171,7 +171,7 @@ protected function getArgument(\ReflectionParameter $parameter, ?string $type): if (!$runtime = $this->getRuntime($type)) { $r = $parameter->getDeclaringFunction(); - throw new \InvalidArgumentException(sprintf('Cannot resolve argument "%s $%s" in "%s" on line "%d": "%s" supports only arguments "array $context", "array $argv" and "array $request", or a runtime named "Symfony\Runtime\%1$sRuntime".', $type, $parameter->name, $r->getFileName(), $r->getStartLine(), get_debug_type($this))); + throw new \InvalidArgumentException(\sprintf('Cannot resolve argument "%s $%s" in "%s" on line "%d": "%s" supports only arguments "array $context", "array $argv" and "array $request", or a runtime named "Symfony\Runtime\%1$sRuntime".', $type, $parameter->name, $r->getFileName(), $r->getStartLine(), get_debug_type($this))); } return $runtime->getArgument($parameter, $type); diff --git a/Internal/ComposerPlugin.php b/Internal/ComposerPlugin.php index 4f49e2b..cad8d85 100644 --- a/Internal/ComposerPlugin.php +++ b/Internal/ComposerPlugin.php @@ -70,7 +70,7 @@ public function updateAutoloadFile(): void } if (!is_file($autoloadTemplate)) { - throw new \InvalidArgumentException(sprintf('File "%s" defined under "extra.runtime.autoload_template" in your composer.json file not found.', $this->composer->getPackage()->getExtra()['runtime']['autoload_template'])); + throw new \InvalidArgumentException(\sprintf('File "%s" defined under "extra.runtime.autoload_template" in your composer.json file not found.', $this->composer->getPackage()->getExtra()['runtime']['autoload_template'])); } } diff --git a/Resolver/DebugClosureResolver.php b/Resolver/DebugClosureResolver.php index 923ae90..026b273 100644 --- a/Resolver/DebugClosureResolver.php +++ b/Resolver/DebugClosureResolver.php @@ -28,7 +28,7 @@ static function (...$arguments) use ($closure) { $r = new \ReflectionFunction($closure); - throw new \TypeError(sprintf('Unexpected value of type "%s" returned, "object" expected from "%s" on line "%d".', get_debug_type($app), $r->getFileName(), $r->getStartLine())); + throw new \TypeError(\sprintf('Unexpected value of type "%s" returned, "object" expected from "%s" on line "%d".', get_debug_type($app), $r->getFileName(), $r->getStartLine())); }, $arguments, ]; diff --git a/Runner/ClosureRunner.php b/Runner/ClosureRunner.php index 4b12ff1..2b54f5a 100644 --- a/Runner/ClosureRunner.php +++ b/Runner/ClosureRunner.php @@ -36,7 +36,7 @@ public function run(): int if (null !== $exitStatus && !\is_int($exitStatus)) { $r = new \ReflectionFunction($this->closure); - throw new \TypeError(sprintf('Unexpected value of type "%s" returned, "string|int|null" expected from "%s" on line "%d".', get_debug_type($exitStatus), $r->getFileName(), $r->getStartLine())); + throw new \TypeError(\sprintf('Unexpected value of type "%s" returned, "string|int|null" expected from "%s" on line "%d".', get_debug_type($exitStatus), $r->getFileName(), $r->getStartLine())); } return $exitStatus ?? 0; diff --git a/SymfonyRuntime.php b/SymfonyRuntime.php index e88e1e0..8534abf 100644 --- a/SymfonyRuntime.php +++ b/SymfonyRuntime.php @@ -108,7 +108,7 @@ public function __construct(array $options = []) if (isset($this->input) && ($options['dotenv_overload'] ?? false)) { if ($this->input->getParameterOption(['--env', '-e'], $_SERVER[$envKey], true) !== $_SERVER[$envKey]) { - throw new \LogicException(sprintf('Cannot use "--env" or "-e" when the "%s" file defines "%s" and the "dotenv_overload" runtime option is true.', $options['dotenv_path'] ?? '.env', $envKey)); + throw new \LogicException(\sprintf('Cannot use "--env" or "-e" when the "%s" file defines "%s" and the "dotenv_overload" runtime option is true.', $options['dotenv_path'] ?? '.env', $envKey)); } if ($_SERVER[$debugKey] && $this->input->hasParameterOption('--no-debug', true)) { From 356c3772b10e6d7fe79cad4001eec4b9e0113da4 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sat, 6 Jul 2024 09:57:16 +0200 Subject: [PATCH 05/14] Update .gitattributes --- .gitattributes | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitattributes b/.gitattributes index 84c7add..14c3c35 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,3 @@ /Tests export-ignore /phpunit.xml.dist export-ignore -/.gitattributes export-ignore -/.gitignore export-ignore +/.git* export-ignore From 289c26cce7b180a91443dddf03825e7fff04946a Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Mon, 5 Aug 2024 09:12:25 +0200 Subject: [PATCH 06/14] Fix multiple CS errors --- Internal/ComposerPlugin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Internal/ComposerPlugin.php b/Internal/ComposerPlugin.php index cad8d85..2cd07ad 100644 --- a/Internal/ComposerPlugin.php +++ b/Internal/ComposerPlugin.php @@ -83,7 +83,7 @@ public function updateAutoloadFile(): void } if (!$nestingLevel) { - $projectDir = '__'.'DIR__.'.var_export('/'.$projectDir, true); + $projectDir = '__DIR__.'.var_export('/'.$projectDir, true); } else { $projectDir = 'dirname(__'."DIR__, $nestingLevel)".('' !== $projectDir ? '.'.var_export('/'.$projectDir, true) : ''); } From 41696a16731a3af780ffe8ffe2ec35b72b960987 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Thu, 22 Aug 2024 16:27:58 +0200 Subject: [PATCH 07/14] [Runtime] fix ComposerPlugin --- Internal/ComposerPlugin.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Internal/ComposerPlugin.php b/Internal/ComposerPlugin.php index 2cd07ad..471aada 100644 --- a/Internal/ComposerPlugin.php +++ b/Internal/ComposerPlugin.php @@ -82,8 +82,9 @@ public function updateAutoloadFile(): void $projectDir = substr($projectDir, 3); } + // the hack about __DIR__ is required because composer pre-processes plugins if (!$nestingLevel) { - $projectDir = '__DIR__.'.var_export('/'.$projectDir, true); + $projectDir = '__'.'DIR__.'.var_export('/'.$projectDir, true); } else { $projectDir = 'dirname(__'."DIR__, $nestingLevel)".('' !== $projectDir ? '.'.var_export('/'.$projectDir, true) : ''); } From b09e81869cab6046382e701f32b3d24a20ba5994 Mon Sep 17 00:00:00 2001 From: Wouter de Jong Date: Thu, 19 Sep 2024 14:29:18 +0200 Subject: [PATCH 08/14] [Console] Add silent verbosity mode suppressing all output, including errors --- Tests/phpt/command_list.phpt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/phpt/command_list.phpt b/Tests/phpt/command_list.phpt index ff1b6b3..da9d055 100644 --- a/Tests/phpt/command_list.phpt +++ b/Tests/phpt/command_list.phpt @@ -23,8 +23,8 @@ Usage: command [options] [arguments] Options: - -h, --help Display %s - -q, --quiet Do not output any message + -h, --help Display %A + -q, --quiet %s -V, --version Display this application version --ansi%A -n, --no-interaction Do not ask any interactive question From 06fa5c812ce91fad1789571f0239906823996cc2 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Sun, 27 Oct 2024 07:46:44 +0100 Subject: [PATCH 09/14] Don't use `die()` in PHPT `--SKIPIF--` Unlocks a performance optimization in PHPUnit 11.x see https://staabm.github.io/2024/10/19/phpunit-codesprint-munich.html --- Tests/phpt/dotenv_overload.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/phpt/dotenv_overload.phpt b/Tests/phpt/dotenv_overload.phpt index eb39d68..c1523a8 100644 --- a/Tests/phpt/dotenv_overload.phpt +++ b/Tests/phpt/dotenv_overload.phpt @@ -1,7 +1,7 @@ --TEST-- Test Dotenv overload --SKIPIF-- - (new \ReflectionMethod(\Symfony\Component\Dotenv\Dotenv::class, 'bootEnv'))->getNumberOfParameters()) die('Skip because Dotenv version is too low'); + (new \ReflectionMethod(\Symfony\Component\Dotenv\Dotenv::class, 'bootEnv'))->getNumberOfParameters()) echo 'Skip because Dotenv version is too low'; --INI-- display_errors=1 --FILE-- From 2c350568f3eaccb25fbbbf962bd67cde273121a7 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 6 Nov 2024 12:43:25 +0100 Subject: [PATCH 10/14] [Runtime] Negate register_argc_argv when its On --- SymfonyRuntime.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/SymfonyRuntime.php b/SymfonyRuntime.php index 9dfac46..d26fac0 100644 --- a/SymfonyRuntime.php +++ b/SymfonyRuntime.php @@ -93,6 +93,12 @@ public function __construct(array $options = []) $envKey = $options['env_var_name'] ??= 'APP_ENV'; $debugKey = $options['debug_var_name'] ??= 'APP_DEBUG'; + if (isset($_SERVER['argv']) && !empty($_GET)) { + // register_argc_argv=On is too risky in web servers + $_SERVER['argv'] = []; + $_SERVER['argc'] = 0; + } + if (isset($options['env'])) { $_SERVER[$envKey] = $options['env']; } elseif (empty($_GET) && isset($_SERVER['argv']) && class_exists(ArgvInput::class)) { @@ -203,10 +209,6 @@ protected static function register(GenericRuntime $runtime): GenericRuntime private function getInput(): ArgvInput { - if (!empty($_GET) && filter_var(ini_get('register_argc_argv'), \FILTER_VALIDATE_BOOL)) { - throw new \Exception('CLI applications cannot be run safely on non-CLI SAPIs with register_argc_argv=On.'); - } - if (isset($this->input)) { return $this->input; } From 8e8d09bd69b7f6c0260dd3d58f37bd4fbdeab5ad Mon Sep 17 00:00:00 2001 From: Duncan de Boer Date: Sun, 29 Dec 2024 22:18:48 +0100 Subject: [PATCH 11/14] Removing the warning on incorrect PHP_SAPI value As per the comments in the issue symfony/symfony#58729 I'm proposing a change to remove the check on this specific point as it also in my opinion is not necessary. --- SymfonyRuntime.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/SymfonyRuntime.php b/SymfonyRuntime.php index d26fac0..c66035f 100644 --- a/SymfonyRuntime.php +++ b/SymfonyRuntime.php @@ -160,10 +160,6 @@ public function getRunner(?object $application): RunnerInterface } if ($application instanceof Application) { - if (!\in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], true)) { - echo 'Warning: The console should be invoked via the CLI version of PHP, not the '.\PHP_SAPI.' SAPI'.\PHP_EOL; - } - set_time_limit(0); $defaultEnv = !isset($this->options['env']) ? ($_SERVER[$this->options['env_var_name']] ?? 'dev') : null; $output = $this->output ??= new ConsoleOutput(); From b3ee8b71dfefcd6ee8c37cc73a36500b6f11883b Mon Sep 17 00:00:00 2001 From: Dariusz Ruminski Date: Fri, 10 Jan 2025 17:38:20 +0100 Subject: [PATCH 12/14] chore: PHP CS Fixer fixes --- Tests/phpt/kernel.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Tests/phpt/kernel.php b/Tests/phpt/kernel.php index f664967..7326849 100644 --- a/Tests/phpt/kernel.php +++ b/Tests/phpt/kernel.php @@ -15,8 +15,7 @@ require __DIR__.'/autoload.php'; -class TestKernel implements HttpKernelInterface -{ +return fn (array $context) => new class($context['APP_ENV'], $context['SOME_VAR']) implements HttpKernelInterface { private string $env; private string $var; @@ -30,6 +29,4 @@ public function handle(Request $request, $type = self::MAIN_REQUEST, $catch = tr { return new Response('OK Kernel (env='.$this->env.') '.$this->var); } -} - -return fn (array $context) => new TestKernel($context['APP_ENV'], $context['SOME_VAR']); +}; From b495af904d1a9e56f4b1b6f2730460e4122ae68d Mon Sep 17 00:00:00 2001 From: Yonel Ceruto Date: Fri, 28 Mar 2025 09:22:25 -0400 Subject: [PATCH 13/14] Deprecate returning a non-integer value from a `\Closure` function set via `Command::setCode()` --- Tests/phpt/application.php | 4 +++- Tests/phpt/command.php | 4 +++- Tests/phpt/dotenv_overload_command_debug_exists_0_to_1.php | 4 +++- Tests/phpt/dotenv_overload_command_debug_exists_1_to_0.php | 4 +++- Tests/phpt/dotenv_overload_command_env_exists.php | 4 +++- Tests/phpt/dotenv_overload_command_no_debug.php | 4 +++- 6 files changed, 18 insertions(+), 6 deletions(-) diff --git a/Tests/phpt/application.php b/Tests/phpt/application.php index 1e1014e..ca2de55 100644 --- a/Tests/phpt/application.php +++ b/Tests/phpt/application.php @@ -18,8 +18,10 @@ return function (array $context) { $command = new Command('go'); - $command->setCode(function (InputInterface $input, OutputInterface $output) use ($context) { + $command->setCode(function (InputInterface $input, OutputInterface $output) use ($context): int { $output->write('OK Application '.$context['SOME_VAR']); + + return 0; }); $app = new Application(); diff --git a/Tests/phpt/command.php b/Tests/phpt/command.php index 3a5fa11..e307d19 100644 --- a/Tests/phpt/command.php +++ b/Tests/phpt/command.php @@ -19,7 +19,9 @@ return function (Command $command, InputInterface $input, OutputInterface $output, array $context) { $command->addOption('hello', 'e', InputOption::VALUE_REQUIRED, 'How should I greet?', 'OK'); - return $command->setCode(function () use ($input, $output, $context) { + return $command->setCode(function () use ($input, $output, $context): int { $output->write($input->getOption('hello').' Command '.$context['SOME_VAR']); + + return 0; }); }; diff --git a/Tests/phpt/dotenv_overload_command_debug_exists_0_to_1.php b/Tests/phpt/dotenv_overload_command_debug_exists_0_to_1.php index af6409d..2968e37 100644 --- a/Tests/phpt/dotenv_overload_command_debug_exists_0_to_1.php +++ b/Tests/phpt/dotenv_overload_command_debug_exists_0_to_1.php @@ -20,6 +20,8 @@ require __DIR__.'/autoload.php'; -return static fn (Command $command, OutputInterface $output, array $context): Command => $command->setCode(static function () use ($output, $context): void { +return static fn (Command $command, OutputInterface $output, array $context): Command => $command->setCode(static function () use ($output, $context): int { $output->writeln($context['DEBUG_ENABLED']); + + return 0; }); diff --git a/Tests/phpt/dotenv_overload_command_debug_exists_1_to_0.php b/Tests/phpt/dotenv_overload_command_debug_exists_1_to_0.php index 78a0bf2..1f2fa35 100644 --- a/Tests/phpt/dotenv_overload_command_debug_exists_1_to_0.php +++ b/Tests/phpt/dotenv_overload_command_debug_exists_1_to_0.php @@ -20,6 +20,8 @@ require __DIR__.'/autoload.php'; -return static fn (Command $command, OutputInterface $output, array $context): Command => $command->setCode(static function () use ($output, $context): void { +return static fn (Command $command, OutputInterface $output, array $context): Command => $command->setCode(static function () use ($output, $context): int { $output->writeln($context['DEBUG_MODE']); + + return 0; }); diff --git a/Tests/phpt/dotenv_overload_command_env_exists.php b/Tests/phpt/dotenv_overload_command_env_exists.php index 3e72372..8587f20 100644 --- a/Tests/phpt/dotenv_overload_command_env_exists.php +++ b/Tests/phpt/dotenv_overload_command_env_exists.php @@ -20,6 +20,8 @@ require __DIR__.'/autoload.php'; -return static fn (Command $command, OutputInterface $output, array $context): Command => $command->setCode(static function () use ($output, $context): void { +return static fn (Command $command, OutputInterface $output, array $context): Command => $command->setCode(static function () use ($output, $context): int { $output->writeln($context['ENV_MODE']); + + return 0; }); diff --git a/Tests/phpt/dotenv_overload_command_no_debug.php b/Tests/phpt/dotenv_overload_command_no_debug.php index 3fe4f44..4ab7694 100644 --- a/Tests/phpt/dotenv_overload_command_no_debug.php +++ b/Tests/phpt/dotenv_overload_command_no_debug.php @@ -19,6 +19,8 @@ require __DIR__.'/autoload.php'; -return static fn (Command $command, OutputInterface $output, array $context): Command => $command->setCode(static function () use ($output, $context): void { +return static fn (Command $command, OutputInterface $output, array $context): Command => $command->setCode(static function () use ($output, $context): int { $output->writeln($context['DEBUG_ENABLED']); + + return 0; }); From fda552ee63dce9f3365f9c397efe7a80c8abac0a Mon Sep 17 00:00:00 2001 From: nathanpage Date: Fri, 4 Apr 2025 16:43:58 +1100 Subject: [PATCH 14/14] [Runtime] Support extra dot-env files --- SymfonyRuntime.php | 20 ++++++++++++++++---- Tests/phpt/.env.extra | 1 + Tests/phpt/dotenv_extra_load.php | 25 +++++++++++++++++++++++++ Tests/phpt/dotenv_extra_load.phpt | 12 ++++++++++++ Tests/phpt/dotenv_extra_overload.php | 25 +++++++++++++++++++++++++ Tests/phpt/dotenv_extra_overload.phpt | 12 ++++++++++++ 6 files changed, 91 insertions(+), 4 deletions(-) create mode 100644 Tests/phpt/.env.extra create mode 100644 Tests/phpt/dotenv_extra_load.php create mode 100644 Tests/phpt/dotenv_extra_load.phpt create mode 100644 Tests/phpt/dotenv_extra_overload.php create mode 100644 Tests/phpt/dotenv_extra_overload.phpt diff --git a/SymfonyRuntime.php b/SymfonyRuntime.php index c66035f..4035f28 100644 --- a/SymfonyRuntime.php +++ b/SymfonyRuntime.php @@ -41,6 +41,7 @@ class_exists(MissingDotenv::class, false) || class_exists(Dotenv::class) || clas * - "test_envs" to define the names of the test envs - defaults to ["test"]; * - "use_putenv" to tell Dotenv to set env vars using putenv() (NOT RECOMMENDED.) * - "dotenv_overload" to tell Dotenv to override existing vars + * - "dotenv_extra_paths" to define a list of additional dot-env files * * When the "debug" / "env" options are not defined, they will fallback to the * "APP_DEBUG" / "APP_ENV" environment variables, and to the "--env|-e" / "--no-debug" @@ -86,6 +87,7 @@ class SymfonyRuntime extends GenericRuntime * env_var_name?: string, * debug_var_name?: string, * dotenv_overload?: ?bool, + * dotenv_extra_paths?: ?string[], * } $options */ public function __construct(array $options = []) @@ -107,12 +109,22 @@ public function __construct(array $options = []) } if (!($options['disable_dotenv'] ?? false) && isset($options['project_dir']) && !class_exists(MissingDotenv::class, false)) { - (new Dotenv($envKey, $debugKey)) + $overrideExistingVars = $options['dotenv_overload'] ?? false; + $dotenv = (new Dotenv($envKey, $debugKey)) ->setProdEnvs((array) ($options['prod_envs'] ?? ['prod'])) - ->usePutenv($options['use_putenv'] ?? false) - ->bootEnv($options['project_dir'].'/'.($options['dotenv_path'] ?? '.env'), 'dev', (array) ($options['test_envs'] ?? ['test']), $options['dotenv_overload'] ?? false); + ->usePutenv($options['use_putenv'] ?? false); - if (isset($this->input) && ($options['dotenv_overload'] ?? false)) { + $dotenv->bootEnv($options['project_dir'].'/'.($options['dotenv_path'] ?? '.env'), 'dev', (array) ($options['test_envs'] ?? ['test']), $overrideExistingVars); + + if (\is_array($options['dotenv_extra_paths'] ?? null) && $options['dotenv_extra_paths']) { + $options['dotenv_extra_paths'] = array_map(fn (string $path) => $options['project_dir'].'/'.$path, $options['dotenv_extra_paths']); + + $overrideExistingVars + ? $dotenv->overload(...$options['dotenv_extra_paths']) + : $dotenv->load(...$options['dotenv_extra_paths']); + } + + if (isset($this->input) && $overrideExistingVars) { if ($this->input->getParameterOption(['--env', '-e'], $_SERVER[$envKey], true) !== $_SERVER[$envKey]) { throw new \LogicException(\sprintf('Cannot use "--env" or "-e" when the "%s" file defines "%s" and the "dotenv_overload" runtime option is true.', $options['dotenv_path'] ?? '.env', $envKey)); } diff --git a/Tests/phpt/.env.extra b/Tests/phpt/.env.extra new file mode 100644 index 0000000..0e7e46a --- /dev/null +++ b/Tests/phpt/.env.extra @@ -0,0 +1 @@ +SOME_VAR=foo_bar_extra diff --git a/Tests/phpt/dotenv_extra_load.php b/Tests/phpt/dotenv_extra_load.php new file mode 100644 index 0000000..3564499 --- /dev/null +++ b/Tests/phpt/dotenv_extra_load.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; + +$_SERVER['SOME_VAR'] = 'ccc'; +$_SERVER['APP_RUNTIME_OPTIONS'] = [ + 'dotenv_extra_paths' => [ + '.env.extra', + ], + 'dotenv_overload' => false, +]; + +require __DIR__.'/autoload.php'; + +return fn (Request $request, array $context) => new Response('OK Request '.$context['SOME_VAR']); diff --git a/Tests/phpt/dotenv_extra_load.phpt b/Tests/phpt/dotenv_extra_load.phpt new file mode 100644 index 0000000..89da5c2 --- /dev/null +++ b/Tests/phpt/dotenv_extra_load.phpt @@ -0,0 +1,12 @@ +--TEST-- +Test Dotenv extra paths load +--INI-- +display_errors=1 +--FILE-- + +--EXPECTF-- +OK Request ccc diff --git a/Tests/phpt/dotenv_extra_overload.php b/Tests/phpt/dotenv_extra_overload.php new file mode 100644 index 0000000..e834257 --- /dev/null +++ b/Tests/phpt/dotenv_extra_overload.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; + +$_SERVER['SOME_VAR'] = 'ccc'; +$_SERVER['APP_RUNTIME_OPTIONS'] = [ + 'dotenv_extra_paths' => [ + '.env.extra', + ], + 'dotenv_overload' => true, +]; + +require __DIR__.'/autoload.php'; + +return fn (Request $request, array $context) => new Response('OK Request '.$context['SOME_VAR']); diff --git a/Tests/phpt/dotenv_extra_overload.phpt b/Tests/phpt/dotenv_extra_overload.phpt new file mode 100644 index 0000000..88fa4c5 --- /dev/null +++ b/Tests/phpt/dotenv_extra_overload.phpt @@ -0,0 +1,12 @@ +--TEST-- +Test Dotenv extra paths overload +--INI-- +display_errors=1 +--FILE-- + +--EXPECTF-- +OK Request foo_bar_extra