Skip to content

Commit

Permalink
bug #33670 [DI] Service locators can't be decorated (malarzm)
Browse files Browse the repository at this point in the history
This PR was squashed before being merged into the 4.3 branch.

Discussion
----------

[DI] Service locators can't be decorated

| Q             | A
| ------------- | ---
| Branch?       | 4.3
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Tickets       | n/a
| License       | MIT
| Doc PR        | n/a

This popped up while I was trying to update my work project as we have decorated the `messenger.receiver_locator` service. Not sure if this is a regression in DI or a change in messenger that caused the issue thus I'm not marking this as a BC break.

Exception while trying to compile the container:

```
Invalid definition for service "Symfony\Component\DependencyInjection\Tests\Compiler\DecoratedServiceLocator": an array of references is expected as first argument when the "container.service_locator" tag is set.
```

Expected result: service locator can be decorated.

Commits
-------

343282b [DI] Service locators can't be decorated
  • Loading branch information
nicolas-grekas committed Dec 17, 2019
2 parents 624f2e3 + 343282b commit 672fbf5
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 3 deletions.
Expand Up @@ -52,14 +52,14 @@ public function __construct()
new ValidateEnvPlaceholdersPass(),
new ResolveChildDefinitionsPass(),
new RegisterServiceSubscribersPass(),
new DecoratorServicePass(),
new ResolveParameterPlaceHoldersPass(false),
new ResolveFactoryClassPass(),
new ResolveNamedArgumentsPass(),
new AutowireRequiredMethodsPass(),
new ResolveBindingsPass(),
new ServiceLocatorTagPass(),
new CheckDefinitionValidityPass(),
new DecoratorServicePass(),
new ResolveFactoryClassPass(),
new AutowireRequiredMethodsPass(),
new AutowirePass(false),
new ResolveTaggedIteratorArgumentPass(),
new ResolveServiceSubscribersPass(),
Expand Down
Expand Up @@ -24,6 +24,7 @@
use Symfony\Component\DependencyInjection\Tests\Fixtures\BarTagClass;
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooBarTaggedClass;
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooTagClass;
use Symfony\Contracts\Service\ServiceProviderInterface;

/**
* This class tests the integration of the different compiler passes.
Expand Down Expand Up @@ -142,6 +143,29 @@ public function testCanDecorateServiceSubscriber()
$this->assertInstanceOf(DecoratedServiceSubscriber::class, $container->get(ServiceSubscriberStub::class));
}

public function testCanDecorateServiceLocator()
{
$container = new ContainerBuilder();

$container->register('foo', 'stdClass')->setPublic(true);

$container->register(ServiceLocator::class)
->addTag('container.service_locator')
->setArguments([[new Reference('foo')]])
;

$container->register(DecoratedServiceLocator::class)
->setDecoratedService(ServiceLocator::class)
->setPublic(true)
->setArguments([new Reference(DecoratedServiceLocator::class.'.inner')])
;

$container->compile();

$this->assertInstanceOf(DecoratedServiceLocator::class, $container->get(DecoratedServiceLocator::class));
$this->assertSame($container->get('foo'), $container->get(DecoratedServiceLocator::class)->get('foo'));
}

/**
* @dataProvider getYamlCompileTests
*/
Expand Down Expand Up @@ -416,6 +440,34 @@ class DecoratedServiceSubscriber
{
}

class DecoratedServiceLocator implements ServiceProviderInterface
{
/**
* @var ServiceLocator
*/
private $locator;

public function __construct(ServiceLocator $locator)
{
$this->locator = $locator;
}

public function get($id)
{
return $this->locator->get($id);
}

public function has($id): bool
{
return $this->locator->has($id);
}

public function getProvidedServices(): array
{
return $this->locator->getProvidedServices();
}
}

class IntegrationTestStub extends IntegrationTestStubParent
{
}
Expand Down

0 comments on commit 672fbf5

Please sign in to comment.