diff --git a/UPGRADE-6.3.md b/UPGRADE-6.3.md index 77c7858198d80..58949b88e408d 100644 --- a/UPGRADE-6.3.md +++ b/UPGRADE-6.3.md @@ -5,6 +5,7 @@ DependencyInjection ------------------- * Deprecate `PhpDumper` options `inline_factories_parameter` and `inline_class_loader_parameter`, use `inline_factories` and `inline_class_loader` instead + * Deprecate undefined and numeric keys with `service_locator` config, use string aliases instead HttpKernel ---------- diff --git a/src/Symfony/Component/DependencyInjection/CHANGELOG.md b/src/Symfony/Component/DependencyInjection/CHANGELOG.md index 6f0f9c1056b83..e1d0dda20d6ff 100644 --- a/src/Symfony/Component/DependencyInjection/CHANGELOG.md +++ b/src/Symfony/Component/DependencyInjection/CHANGELOG.md @@ -8,6 +8,7 @@ CHANGELOG * Deprecate `PhpDumper` options `inline_factories_parameter` and `inline_class_loader_parameter` * Add `RemoveBuildParametersPass`, which removes parameters starting with a dot during compilation * Add support for nesting autowiring-related attributes into `#[Autowire(...)]` + * Deprecate undefined and numeric keys with `service_locator` config 6.2 --- diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/ContainerConfigurator.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/ContainerConfigurator.php index 3065a94b3bff0..91acd9a10ea7d 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/Configurator/ContainerConfigurator.php +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/ContainerConfigurator.php @@ -123,7 +123,13 @@ function inline_service(string $class = null): InlineServiceConfigurator */ function service_locator(array $values): ServiceLocatorArgument { - return new ServiceLocatorArgument(AbstractConfigurator::processValue($values, true)); + $values = AbstractConfigurator::processValue($values, true); + + if (isset($values[0])) { + trigger_deprecation('symfony/dependency-injection', '6.3', 'Using integers as keys in a "service_locator()" argument is deprecated. The keys will default to the IDs of the original services in 7.0.'); + } + + return new ServiceLocatorArgument($values); } /** diff --git a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php index ab76eb9e0df08..7c0ea3261300b 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php @@ -526,6 +526,11 @@ private function getArgumentsAsPhp(\DOMElement $node, string $name, string $file break; case 'service_locator': $arg = $this->getArgumentsAsPhp($arg, $name, $file); + + if (isset($arg[0])) { + trigger_deprecation('symfony/dependency-injection', '6.3', 'Skipping "key" argument or using integers as values in a "service_locator" tag is deprecated. The keys will default to the IDs of the original services in 7.0.'); + } + $arguments[$key] = new ServiceLocatorArgument($arg); break; case 'tagged': diff --git a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php index 80a58d39f4f6b..ad61c14437d1a 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php @@ -814,6 +814,10 @@ private function resolveServices(mixed $value, string $file, bool $isParameter = $argument = $this->resolveServices($argument, $file, $isParameter); + if (isset($argument[0])) { + trigger_deprecation('symfony/dependency-injection', '6.3', 'Using integers as keys in a "!service_locator" tag is deprecated. The keys will default to the IDs of the original services in 7.0.'); + } + return new ServiceLocatorArgument($argument); } if (\in_array($value->getTag(), ['tagged', 'tagged_iterator', 'tagged_locator'], true)) { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/services_with_service_locator_argument.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/services_with_service_locator_argument.php new file mode 100644 index 0000000000000..58757abc4b326 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/services_with_service_locator_argument.php @@ -0,0 +1,29 @@ +services()->defaults()->public(); + + $services->set('foo_service', \stdClass::class); + + $services->set('bar_service', \stdClass::class); + + $services->set('locator_dependent_service_indexed', \ArrayObject::class) + ->args([service_locator([ + 'foo' => service('foo_service'), + 'bar' => service('bar_service'), + ])]); + + $services->set('locator_dependent_service_not_indexed', \ArrayObject::class) + ->args([service_locator([ + service('foo_service'), + service('bar_service'), + ])]); + + $services->set('locator_dependent_service_mixed', \ArrayObject::class) + ->args([service_locator([ + 'foo' => service('foo_service'), + service('bar_service'), + ])]); +}; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_with_service_locator_argument.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_with_service_locator_argument.xml new file mode 100644 index 0000000000000..f98ca9e5a01d9 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_with_service_locator_argument.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_with_service_locator_argument.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_with_service_locator_argument.yml new file mode 100644 index 0000000000000..b0309d3eeab9a --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_with_service_locator_argument.yml @@ -0,0 +1,28 @@ + +services: + foo_service: + class: stdClass + + bar_service: + class: stdClass + + locator_dependent_service_indexed: + class: ArrayObject + arguments: + - !service_locator + 'foo': '@foo_service' + 'bar': '@bar_service' + + locator_dependent_service_not_indexed: + class: ArrayObject + arguments: + - !service_locator + - '@foo_service' + - '@bar_service' + + locator_dependent_service_mixed: + class: ArrayObject + arguments: + - !service_locator + 'foo': '@foo_service' + '0': '@bar_service' diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php index ef153e178bc03..15f88324dccfa 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php @@ -14,18 +14,23 @@ require_once __DIR__.'/../Fixtures/includes/AcmeExtension.php'; use PHPUnit\Framework\TestCase; +use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Component\Config\Builder\ConfigBuilderGenerator; use Symfony\Component\Config\FileLocator; +use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Dumper\PhpDumper; use Symfony\Component\DependencyInjection\Dumper\YamlDumper; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; +use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithEnumAttribute; use Symfony\Component\DependencyInjection\Tests\Fixtures\FooUnitEnum; class PhpFileLoaderTest extends TestCase { + use ExpectDeprecationTrait; + public function testSupports() { $loader = new PhpFileLoader(new ContainerBuilder(), new FileLocator()); @@ -200,4 +205,25 @@ public function testWhenEnv() $loader->load($fixtures.'/config/when_env.php'); } + + /** + * @group legacy + */ + public function testServiceWithServiceLocatorArgument() + { + $this->expectDeprecation('Since symfony/dependency-injection 6.3: Using integers as keys in a "service_locator()" argument is deprecated. The keys will default to the IDs of the original services in 7.0.'); + + $fixtures = realpath(__DIR__.'/../Fixtures'); + $loader = new PhpFileLoader($container = new ContainerBuilder(), new FileLocator()); + $loader->load($fixtures.'/config/services_with_service_locator_argument.php'); + + $values = ['foo' => new Reference('foo_service'), 'bar' => new Reference('bar_service')]; + $this->assertEquals([new ServiceLocatorArgument($values)], $container->getDefinition('locator_dependent_service_indexed')->getArguments()); + + $values = [new Reference('foo_service'), new Reference('bar_service')]; + $this->assertEquals([new ServiceLocatorArgument($values)], $container->getDefinition('locator_dependent_service_not_indexed')->getArguments()); + + $values = ['foo' => new Reference('foo_service'), 0 => new Reference('bar_service')]; + $this->assertEquals([new ServiceLocatorArgument($values)], $container->getDefinition('locator_dependent_service_mixed')->getArguments()); + } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php index 9207742bc25f1..56a5fe0be4871 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\DependencyInjection\Tests\Loader; use PHPUnit\Framework\TestCase; +use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Component\Config\Exception\FileLocatorFileNotFoundException; use Symfony\Component\Config\Exception\LoaderLoadException; use Symfony\Component\Config\FileLocator; @@ -47,6 +48,8 @@ class XmlFileLoaderTest extends TestCase { + use ExpectDeprecationTrait; + protected static $fixturesPath; public static function setUpBeforeClass(): void @@ -421,6 +424,27 @@ public function testParseTaggedArgumentsWithIndexBy() $this->assertEquals(new ServiceLocatorArgument($taggedIterator3), $container->getDefinition('foo3_tagged_locator')->getArgument(0)); } + /** + * @group legacy + */ + public function testServiceWithServiceLocatorArgument() + { + $this->expectDeprecation('Since symfony/dependency-injection 6.3: Skipping "key" argument or using integers as values in a "service_locator" tag is deprecated. The keys will default to the IDs of the original services in 7.0.'); + + $container = new ContainerBuilder(); + $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); + $loader->load('services_with_service_locator_argument.xml'); + + $values = ['foo' => new Reference('foo_service'), 'bar' => new Reference('bar_service')]; + $this->assertEquals([new ServiceLocatorArgument($values)], $container->getDefinition('locator_dependent_service_indexed')->getArguments()); + + $values = [new Reference('foo_service'), new Reference('bar_service')]; + $this->assertEquals([new ServiceLocatorArgument($values)], $container->getDefinition('locator_dependent_service_not_indexed')->getArguments()); + + $values = ['foo' => new Reference('foo_service'), 0 => new Reference('bar_service')]; + $this->assertEquals([new ServiceLocatorArgument($values)], $container->getDefinition('locator_dependent_service_mixed')->getArguments()); + } + public function testParseServiceClosure() { $container = new ContainerBuilder(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php index 952b2dc3fbb2c..9515bfee92099 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\DependencyInjection\Tests\Loader; use PHPUnit\Framework\TestCase; +use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Component\Config\Exception\FileLocatorFileNotFoundException; use Symfony\Component\Config\Exception\LoaderLoadException; use Symfony\Component\Config\FileLocator; @@ -45,6 +46,8 @@ class YamlFileLoaderTest extends TestCase { + use ExpectDeprecationTrait; + protected static $fixturesPath; public static function setUpBeforeClass(): void @@ -408,6 +411,27 @@ public function testTaggedArgumentsWithIndex() $this->assertEquals(new ServiceLocatorArgument($taggedIterator), $container->getDefinition('bar_service_tagged_locator')->getArgument(0)); } + /** + * @group legacy + */ + public function testServiceWithServiceLocatorArgument() + { + $this->expectDeprecation('Since symfony/dependency-injection 6.3: Using integers as keys in a "!service_locator" tag is deprecated. The keys will default to the IDs of the original services in 7.0.'); + + $container = new ContainerBuilder(); + $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')); + $loader->load('services_with_service_locator_argument.yml'); + + $values = ['foo' => new Reference('foo_service'), 'bar' => new Reference('bar_service')]; + $this->assertEquals([new ServiceLocatorArgument($values)], $container->getDefinition('locator_dependent_service_indexed')->getArguments()); + + $values = [new Reference('foo_service'), new Reference('bar_service')]; + $this->assertEquals([new ServiceLocatorArgument($values)], $container->getDefinition('locator_dependent_service_not_indexed')->getArguments()); + + $values = ['foo' => new Reference('foo_service'), 0 => new Reference('bar_service')]; + $this->assertEquals([new ServiceLocatorArgument($values)], $container->getDefinition('locator_dependent_service_mixed')->getArguments()); + } + public function testParseServiceClosure() { $container = new ContainerBuilder();