Skip to content

Commit

Permalink
bug #24418 [DI] Allow setting any public non-initialized services (ni…
Browse files Browse the repository at this point in the history
…colas-grekas)

This PR was merged into the 3.3 branch.

Discussion
----------

[DI] Allow setting any public non-initialized services

| Q             | A
| ------------- | ---
| Branch?       | 3.3
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #23311, #23772
| License       | MIT
| Doc PR        | -

I think we went a but too far with this deprecation and that we should relax the rule: setting a pre-defined service is OK *if* it has not already been initialized.
This will allow setting them in test cases, as reported several times (see linked issues).

Commits
-------

d314b1f [DI] Allow setting any public non-initialized services
  • Loading branch information
nicolas-grekas committed Oct 4, 2017
2 parents b87a395 + d314b1f commit b7f1daa
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 9 deletions.
7 changes: 4 additions & 3 deletions src/Symfony/Component/DependencyInjection/Container.php
Expand Up @@ -190,6 +190,7 @@ public function set($id, $service)
unset($this->aliases[$id]);
}

$wasSet = isset($this->services[$id]);
$this->services[$id] = $service;

if (null === $service) {
Expand All @@ -203,11 +204,11 @@ public function set($id, $service)
} else {
@trigger_error(sprintf('Setting the "%s" private service is deprecated since Symfony 3.2 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED);
}
} elseif (isset($this->methodMap[$id])) {
} elseif ($wasSet && isset($this->methodMap[$id])) {
if (null === $service) {
@trigger_error(sprintf('Unsetting the "%s" pre-defined service is deprecated since Symfony 3.3 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED);
@trigger_error(sprintf('Unsetting the "%s" service after it\'s been initialized is deprecated since Symfony 3.3 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED);
} else {
@trigger_error(sprintf('Setting the "%s" pre-defined service is deprecated since Symfony 3.3 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED);
@trigger_error(sprintf('Setting the "%s" service after it\'s been initialized is deprecated since Symfony 3.3 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED);
}
}
}
Expand Down
20 changes: 17 additions & 3 deletions src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php
Expand Up @@ -186,15 +186,29 @@ public function testSetReplacesAlias()

/**
* @group legacy
* @expectedDeprecation Unsetting the "bar" pre-defined service is deprecated since Symfony 3.3 and won't be supported anymore in Symfony 4.0.
* @expectedDeprecation Unsetting the "bar" service after it's been initialized is deprecated since Symfony 3.3 and won't be supported anymore in Symfony 4.0.
*/
public function testSetWithNullResetPredefinedService()
public function testSetWithNullOnInitializedPredefinedService()
{
$sc = new Container();
$sc->set('foo', new \stdClass());
$sc->set('foo', null);
$this->assertFalse($sc->has('foo'), '->set() with null service resets the service');

$sc = new ProjectServiceContainer();
$sc->get('bar');
$sc->set('bar', null);
$this->assertTrue($sc->has('bar'), '->set() with null service resets the pre-defined service');
}

public function testSetWithNullOnUninitializedPredefinedService()
{
$sc = new Container();
$sc->set('foo', new \stdClass());
$sc->get('foo', null);
$sc->set('foo', null);
$this->assertFalse($sc->has('foo'), '->set() with null service resets the service');

$sc = new ProjectServiceContainer();
$sc->set('bar', null);
$this->assertTrue($sc->has('bar'), '->set() with null service resets the pre-defined service');
Expand Down Expand Up @@ -481,7 +495,7 @@ public function testRequestAnInternalSharedPrivateServiceIsDeprecated()

/**
* @group legacy
* @expectedDeprecation Setting the "bar" pre-defined service is deprecated since Symfony 3.3 and won't be supported anymore in Symfony 4.0.
* @expectedDeprecation Setting the "bar" service after it's been initialized is deprecated since Symfony 3.3 and won't be supported anymore in Symfony 4.0.
*/
public function testReplacingAPreDefinedServiceIsDeprecated()
{
Expand Down
Expand Up @@ -269,23 +269,24 @@ public function testFrozenContainerWithoutAliases()

/**
* @group legacy
* @expectedDeprecation Setting the "bar" pre-defined service is deprecated since Symfony 3.3 and won't be supported anymore in Symfony 4.0.
* @expectedDeprecation Setting the "bar" service after it's been initialized is deprecated since Symfony 3.3 and won't be supported anymore in Symfony 4.0.
*/
public function testOverrideServiceWhenUsingADumpedContainer()
{
require_once self::$fixturesPath.'/php/services9.php';
require_once self::$fixturesPath.'/includes/foo.php';

$container = new \ProjectServiceContainer();
$container->set('bar', $bar = new \stdClass());
$container->setParameter('foo_bar', 'foo_bar');
$container->get('bar');
$container->set('bar', $bar = new \stdClass());

$this->assertSame($bar, $container->get('bar'), '->set() overrides an already defined service');
}

/**
* @group legacy
* @expectedDeprecation Setting the "bar" pre-defined service is deprecated since Symfony 3.3 and won't be supported anymore in Symfony 4.0.
* @expectedDeprecation Setting the "bar" service after it's been initialized is deprecated since Symfony 3.3 and won't be supported anymore in Symfony 4.0.
*/
public function testOverrideServiceWhenUsingADumpedContainerAndServiceIsUsedFromAnotherOne()
{
Expand All @@ -294,6 +295,8 @@ public function testOverrideServiceWhenUsingADumpedContainerAndServiceIsUsedFrom
require_once self::$fixturesPath.'/includes/classes.php';

$container = new \ProjectServiceContainer();
$container->setParameter('foo_bar', 'foo_bar');
$container->get('bar');
$container->set('bar', $bar = new \stdClass());

$this->assertSame($bar, $container->get('foo')->bar, '->set() overrides an already defined service');
Expand Down

0 comments on commit b7f1daa

Please sign in to comment.