bug #19870 [DI] Fix setting synthetic services on ContainerBuilder (nicolas-grekas)

This PR was merged into the 2.7 branch.

Discussion
----------

[DI] Fix setting synthetic services on ContainerBuilder

| Q             | A
| ------------- | ---
| Branch?       | 2.7
| Bug fix?      | yes
| Tests pass?   | yes
| Fixed tickets | #19858
| License       | MIT

`ContainerBuilder` doesn't allow setting a service while it's frozen and has no corresponding definition.
Yet, the base `Container` doesn't have this limitation.

See linked issue for some context.

Commits
-------

42244f2 [DI] Fix setting synthetic services on ContainerBuilder
This commit is contained in:
Fabien Potencier 2016-09-06 08:43:09 -07:00
commit 42b26411f1
3 changed files with 7 additions and 16 deletions

View File

@ -362,21 +362,14 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
public function set($id, $service, $scope = self::SCOPE_CONTAINER) public function set($id, $service, $scope = self::SCOPE_CONTAINER)
{ {
$id = strtolower($id); $id = strtolower($id);
$set = isset($this->definitions[$id]);
if ($this->isFrozen()) { if ($this->isFrozen() && ($set || isset($this->obsoleteDefinitions[$id])) && !$this->{$set ? 'definitions' : 'obsoleteDefinitions'}[$id]->isSynthetic()) {
// setting a synthetic service on a frozen container is alright // setting a synthetic service on a frozen container is alright
if ( throw new BadMethodCallException(sprintf('Setting service "%s" on a frozen container is not allowed.', $id));
(!isset($this->definitions[$id]) && !isset($this->obsoleteDefinitions[$id]))
||
(isset($this->definitions[$id]) && !$this->definitions[$id]->isSynthetic())
||
(isset($this->obsoleteDefinitions[$id]) && !$this->obsoleteDefinitions[$id]->isSynthetic())
) {
throw new BadMethodCallException(sprintf('Setting service "%s" on a frozen container is not allowed.', $id));
}
} }
if (isset($this->definitions[$id])) { if ($set) {
$this->obsoleteDefinitions[$id] = $this->definitions[$id]; $this->obsoleteDefinitions[$id] = $this->definitions[$id];
} }

View File

@ -637,14 +637,12 @@ class ContainerBuilderTest extends \PHPUnit_Framework_TestCase
$container->set('a', new \stdClass()); $container->set('a', new \stdClass());
} }
/**
* @expectedException \BadMethodCallException
*/
public function testThrowsExceptionWhenAddServiceOnAFrozenContainer() public function testThrowsExceptionWhenAddServiceOnAFrozenContainer()
{ {
$container = new ContainerBuilder(); $container = new ContainerBuilder();
$container->compile(); $container->compile();
$container->set('a', new \stdClass()); $container->set('a', $foo = new \stdClass());
$this->assertSame($foo, $container->get('a'));
} }
public function testNoExceptionWhenSetSyntheticServiceOnAFrozenContainer() public function testNoExceptionWhenSetSyntheticServiceOnAFrozenContainer()

View File

@ -258,7 +258,7 @@ class ContainerTest extends \PHPUnit_Framework_TestCase
/** /**
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
* @expectedExcepionMessage You have requested a synthetic service ("request"). The DIC does not know how to construct this service. * @expectedExceptionMessage You have requested a synthetic service ("request"). The DIC does not know how to construct this service.
*/ */
public function testGetSyntheticServiceAlwaysThrows() public function testGetSyntheticServiceAlwaysThrows()
{ {