diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TestServiceContainerRealRefPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TestServiceContainerRealRefPass.php index 09f272daa940..aed3b13404bd 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TestServiceContainerRealRefPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TestServiceContainerRealRefPass.php @@ -41,6 +41,9 @@ public function process(ContainerBuilder $container) if ($id !== $target) { $renamedIds[$id] = $target; } + if ($inner = $definitions[$target]->getTag('container.decorator')[0]['inner'] ?? null) { + $renamedIds[$id] = $inner; + } } else { unset($privateServices[$id]); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/TestServiceContainer/PrivateService.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/TestServiceContainer/PrivateService.php index 6a244cb40ce5..51168b7ea6c2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/TestServiceContainer/PrivateService.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/TestServiceContainer/PrivateService.php @@ -13,4 +13,5 @@ class PrivateService { + public $inner; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/KernelTestCaseTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/KernelTestCaseTest.php deleted file mode 100644 index aa12467829ed..000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/KernelTestCaseTest.php +++ /dev/null @@ -1,61 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; - -use Symfony\Bundle\FrameworkBundle\Test\TestContainer; -use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestServiceContainer\NonPublicService; -use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestServiceContainer\PrivateService; -use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestServiceContainer\PublicService; -use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestServiceContainer\UnusedPrivateService; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; - -class KernelTestCaseTest extends AbstractWebTestCase -{ - public function testThatPrivateServicesAreUnavailableIfTestConfigIsDisabled() - { - static::bootKernel(['test_case' => 'TestServiceContainer', 'root_config' => 'test_disabled.yml', 'environment' => 'test_disabled']); - - $this->expectException(\LogicException::class); - static::getContainer(); - } - - public function testThatPrivateServicesAreAvailableIfTestConfigIsEnabled() - { - static::bootKernel(['test_case' => 'TestServiceContainer']); - - $container = static::getContainer(); - $this->assertInstanceOf(ContainerInterface::class, $container); - $this->assertInstanceOf(TestContainer::class, $container); - $this->assertTrue($container->has(PublicService::class)); - $this->assertTrue($container->has(NonPublicService::class)); - $this->assertTrue($container->has(PrivateService::class)); - $this->assertTrue($container->has('private_service')); - $this->assertFalse($container->has(UnusedPrivateService::class)); - } - - public function testThatPrivateServicesCanBeSetIfTestConfigIsEnabled() - { - static::bootKernel(['test_case' => 'TestServiceContainer']); - - $container = static::getContainer(); - - $service = new \stdClass(); - - $container->set('private_service', $service); - $this->assertSame($service, $container->get('private_service')); - - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('The "private_service" service is already initialized, you cannot replace it.'); - $container->set('private_service', new \stdClass()); - } -} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/TestServiceContainerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/TestServiceContainerTest.php index 76a373c0c05a..fe7093081509 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/TestServiceContainerTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/TestServiceContainerTest.php @@ -16,6 +16,7 @@ use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestServiceContainer\PrivateService; use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestServiceContainer\PublicService; use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestServiceContainer\UnusedPrivateService; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; class TestServiceContainerTest extends AbstractWebTestCase { @@ -40,6 +41,33 @@ public function testThatPrivateServicesAreAvailableIfTestConfigIsEnabled() $this->assertFalse(static::getContainer()->has(UnusedPrivateService::class)); } + public function testThatPrivateServicesCanBeSetIfTestConfigIsEnabled() + { + static::bootKernel(['test_case' => 'TestServiceContainer']); + + $container = static::getContainer(); + + $service = new \stdClass(); + + $container->set('private_service', $service); + $this->assertSame($service, $container->get('private_service')); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('The "private_service" service is already initialized, you cannot replace it.'); + $container->set('private_service', new \stdClass()); + } + + public function testSetDecoratedService() + { + static::bootKernel(['test_case' => 'TestServiceContainer']); + + $container = static::getContainer(); + + $service = new PrivateService(); + $container->set('decorated', $service); + $this->assertSame($service, $container->get('decorated')->inner); + } + /** * @doesNotPerformAssertions */ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/TestServiceContainer/services.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/TestServiceContainer/services.yml index 523cca58d0b6..46cb7be6a8f6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/TestServiceContainer/services.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/TestServiceContainer/services.yml @@ -8,8 +8,18 @@ services: private_service: '@Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestServiceContainer\PrivateService' + decorated: + class: Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestServiceContainer\PrivateService + Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestServiceContainer\PublicService: public: true arguments: - '@Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestServiceContainer\NonPublicService' - '@Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestServiceContainer\PrivateService' + - '@decorated' + + decorator: + class: Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestServiceContainer\PrivateService + decorates: decorated + properties: + inner: '@.inner' diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index 9f594f254f03..0fcc602c3975 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -21,7 +21,7 @@ "ext-xml": "*", "symfony/cache": "^5.4|^6.0", "symfony/config": "^6.1", - "symfony/dependency-injection": "^6.3", + "symfony/dependency-injection": "^6.3.1", "symfony/deprecation-contracts": "^2.5|^3", "symfony/error-handler": "^6.1", "symfony/event-dispatcher": "^5.4|^6.0", diff --git a/src/Symfony/Component/DependencyInjection/Compiler/DecoratorServicePass.php b/src/Symfony/Component/DependencyInjection/Compiler/DecoratorServicePass.php index c38bfa774450..d05878fe8561 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/DecoratorServicePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/DecoratorServicePass.php @@ -42,6 +42,7 @@ public function process(ContainerBuilder $container) $definitions->insert([$id, $definition], [$decorated[2], --$order]); } $decoratingDefinitions = []; + $decoratedIds = []; $tagsToKeep = $container->hasParameter('container.behavior_describing_tags') ? $container->getParameter('container.behavior_describing_tags') @@ -58,6 +59,7 @@ public function process(ContainerBuilder $container) $renamedId = $id.'.inner'; } + $decoratedIds[$inner] ??= $renamedId; $this->currentId = $renamedId; $this->processValue($definition); @@ -114,7 +116,7 @@ public function process(ContainerBuilder $container) } foreach ($decoratingDefinitions as $inner => $definition) { - $definition->addTag('container.decorator', ['id' => $inner]); + $definition->addTag('container.decorator', ['id' => $inner, 'inner' => $decoratedIds[$inner]]); } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/DecoratorServicePassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/DecoratorServicePassTest.php index 8c8a158a7632..48ed32df6d63 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/DecoratorServicePassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/DecoratorServicePassTest.php @@ -161,7 +161,7 @@ public function testProcessWithInvalidDecorated() public function testProcessNoInnerAliasWithInvalidDecorated() { $container = new ContainerBuilder(); - $decoratorDefinition = $container + $container ->register('decorator') ->setDecoratedService('unknown_decorated', null, 0, ContainerInterface::NULL_ON_INVALID_REFERENCE) ; @@ -173,7 +173,7 @@ public function testProcessNoInnerAliasWithInvalidDecorated() public function testProcessWithInvalidDecoratedAndWrongBehavior() { $container = new ContainerBuilder(); - $decoratorDefinition = $container + $container ->register('decorator') ->setDecoratedService('unknown_decorated', null, 0, 12) ; @@ -198,7 +198,7 @@ public function testProcessMovesTagsFromDecoratedDefinitionToDecoratingDefinitio $this->process($container); $this->assertEmpty($container->getDefinition('baz.inner')->getTags()); - $this->assertEquals(['bar' => ['attr' => 'baz'], 'foobar' => ['attr' => 'bar'], 'container.decorator' => [['id' => 'foo']]], $container->getDefinition('baz')->getTags()); + $this->assertEquals(['bar' => ['attr' => 'baz'], 'foobar' => ['attr' => 'bar'], 'container.decorator' => [['id' => 'foo', 'inner' => 'baz.inner']]], $container->getDefinition('baz')->getTags()); } public function testProcessMovesTagsFromDecoratedDefinitionToDecoratingDefinitionMultipleTimes() @@ -221,7 +221,7 @@ public function testProcessMovesTagsFromDecoratedDefinitionToDecoratingDefinitio $this->process($container); $this->assertEmpty($container->getDefinition('deco1')->getTags()); - $this->assertEquals(['bar' => ['attr' => 'baz'], 'container.decorator' => [['id' => 'foo']]], $container->getDefinition('deco2')->getTags()); + $this->assertEquals(['bar' => ['attr' => 'baz'], 'container.decorator' => [['id' => 'foo', 'inner' => 'deco1.inner']]], $container->getDefinition('deco2')->getTags()); } public function testProcessLeavesServiceLocatorTagOnOriginalDefinition() @@ -240,7 +240,7 @@ public function testProcessLeavesServiceLocatorTagOnOriginalDefinition() $this->process($container); $this->assertEquals(['container.service_locator' => [0 => []]], $container->getDefinition('baz.inner')->getTags()); - $this->assertEquals(['bar' => ['attr' => 'baz'], 'foobar' => ['attr' => 'bar'], 'container.decorator' => [['id' => 'foo']]], $container->getDefinition('baz')->getTags()); + $this->assertEquals(['bar' => ['attr' => 'baz'], 'foobar' => ['attr' => 'bar'], 'container.decorator' => [['id' => 'foo', 'inner' => 'baz.inner']]], $container->getDefinition('baz')->getTags()); } public function testProcessLeavesServiceSubscriberTagOnOriginalDefinition() @@ -259,7 +259,7 @@ public function testProcessLeavesServiceSubscriberTagOnOriginalDefinition() $this->process($container); $this->assertEquals(['container.service_subscriber' => [], 'container.service_subscriber.locator' => []], $container->getDefinition('baz.inner')->getTags()); - $this->assertEquals(['bar' => ['attr' => 'baz'], 'foobar' => ['attr' => 'bar'], 'container.decorator' => [['id' => 'foo']]], $container->getDefinition('baz')->getTags()); + $this->assertEquals(['bar' => ['attr' => 'baz'], 'foobar' => ['attr' => 'bar'], 'container.decorator' => [['id' => 'foo', 'inner' => 'baz.inner']]], $container->getDefinition('baz')->getTags()); } public function testProcessLeavesProxyTagOnOriginalDefinition() @@ -278,7 +278,7 @@ public function testProcessLeavesProxyTagOnOriginalDefinition() $this->process($container); $this->assertEquals(['proxy' => 'foo'], $container->getDefinition('baz.inner')->getTags()); - $this->assertEquals(['bar' => ['attr' => 'baz'], 'foobar' => ['attr' => 'bar'], 'container.decorator' => [['id' => 'foo']]], $container->getDefinition('baz')->getTags()); + $this->assertEquals(['bar' => ['attr' => 'baz'], 'foobar' => ['attr' => 'bar'], 'container.decorator' => [['id' => 'foo', 'inner' => 'baz.inner']]], $container->getDefinition('baz')->getTags()); } public function testCannotDecorateSyntheticService() diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/anonymous.expected.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/anonymous.expected.yml index 9b1213fbcab8..7f36de38b001 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/anonymous.expected.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/anonymous.expected.yml @@ -16,5 +16,5 @@ services: class: Symfony\Component\DependencyInjection\Tests\Fixtures\StdClassDecorator public: true tags: - - container.decorator: { id: decorated } + - container.decorator: { id: decorated, inner: decorator42 } arguments: [!service { class: stdClass }] diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/child.expected.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/child.expected.yml index a4e4eb995c4b..44dbbd571b78 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/child.expected.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/child.expected.yml @@ -8,7 +8,7 @@ services: class: Class2 public: true tags: - - container.decorator: { id: bar } + - container.decorator: { id: bar, inner: b } file: file.php lazy: true arguments: [!service { class: Class1 }]
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: