diff --git a/src/Symfony/Component/DependencyInjection/Attribute/When.php b/src/Symfony/Component/DependencyInjection/Attribute/When.php index 8cb01c87e1..3114115fd2 100644 --- a/src/Symfony/Component/DependencyInjection/Attribute/When.php +++ b/src/Symfony/Component/DependencyInjection/Attribute/When.php @@ -16,7 +16,7 @@ namespace Symfony\Component\DependencyInjection\Attribute; * * @author Nicolas Grekas */ -#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::IS_REPEATABLE)] +#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)] class When { public function __construct( diff --git a/src/Symfony/Component/DependencyInjection/Loader/PhpFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/PhpFileLoader.php index 43a379778b..007ab1b248 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/PhpFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/PhpFileLoader.php @@ -15,6 +15,7 @@ use Symfony\Component\Config\Builder\ConfigBuilderGenerator; use Symfony\Component\Config\Builder\ConfigBuilderGeneratorInterface; use Symfony\Component\Config\Builder\ConfigBuilderInterface; use Symfony\Component\Config\FileLocatorInterface; +use Symfony\Component\DependencyInjection\Attribute\When; use Symfony\Component\DependencyInjection\Container; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; @@ -55,12 +56,12 @@ class PhpFileLoader extends FileLoader $this->container->fileExists($path); // the closure forbids access to the private scope in the included file - $load = \Closure::bind(function ($path) use ($container, $loader, $resource, $type) { + $load = \Closure::bind(function ($path, $env) use ($container, $loader, $resource, $type) { return include $path; }, $this, ProtectedPhpFileLoader::class); try { - $callback = $load($path); + $callback = $load($path, $this->env); if (\is_object($callback) && \is_callable($callback)) { $this->executeCallback($callback, new ContainerConfigurator($this->container, $this, $this->instanceof, $path, $resource, $this->env), $path); @@ -98,8 +99,22 @@ class PhpFileLoader extends FileLoader $arguments = []; $configBuilders = []; - $parameters = (new \ReflectionFunction($callback))->getParameters(); - foreach ($parameters as $parameter) { + $r = new \ReflectionFunction($callback); + + if (\PHP_VERSION_ID >= 80000) { + $attribute = null; + foreach ($r->getAttributes(When::class) as $attribute) { + if ($this->env === $attribute->newInstance()->env) { + $attribute = null; + break; + } + } + if (null !== $attribute) { + return; + } + } + + foreach ($r->getParameters() as $parameter) { $reflectionType = $parameter->getType(); if (!$reflectionType instanceof \ReflectionNamedType) { throw new \InvalidArgumentException(sprintf('Could not resolve argument "$%s" for "%s". You must typehint it (for example with "%s" or "%s").', $parameter->getName(), $path, ContainerConfigurator::class, ContainerBuilder::class)); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/config_builder.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/config_builder.php index 71f5e58910..02772e64cc 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/config_builder.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/config_builder.php @@ -2,6 +2,10 @@ use Symfony\Component\DependencyInjection\Tests\Fixtures\AcmeConfig; -return static function (AcmeConfig $config) { +if ('prod' !== $env) { + return; +} + +return function (AcmeConfig $config) { $config->color('blue'); }; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/env_configurator.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/env_configurator.php index 1c6a3b9038..15434bcfd8 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/env_configurator.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/env_configurator.php @@ -2,7 +2,7 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator; -return static function (ContainerConfigurator $configurator): void { +return function (ContainerConfigurator $configurator): void { $services = $configurator->services(); $services diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/nested_bundle_config.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/nested_bundle_config.php index ba1e5de40d..f343eab3d6 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/nested_bundle_config.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/nested_bundle_config.php @@ -2,6 +2,6 @@ use Symfony\Config\AcmeConfig\NestedConfig; -return static function (NestedConfig $config) { +return function (NestedConfig $config) { throw new RuntimeException('This code should not be run.'); }; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/when_env.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/when_env.php new file mode 100644 index 0000000000..318e9e1cfb --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/when_env.php @@ -0,0 +1,7 @@ +load($fixtures.'/config/nested_bundle_config.php'); } + + /** + * @requires PHP 8 + */ + public function testWhenEnv() + { + $fixtures = realpath(__DIR__.'/../Fixtures'); + $container = new ContainerBuilder(); + $loader = new PhpFileLoader($container, new FileLocator(), 'dev', new ConfigBuilderGenerator(sys_get_temp_dir())); + + $loader->load($fixtures.'/config/when_env.php'); + } }