Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 19f3c66

Browse filesBrowse files
author
Hugo Hamon
committed
[DependencyInjection] deprecate access to private shared services. Fixes issue #19117.
1 parent 6e03a42 commit 19f3c66
Copy full SHA for 19f3c66

File tree

7 files changed

+141
-12
lines changed
Filter options

7 files changed

+141
-12
lines changed

‎UPGRADE-4.0.md

Copy file name to clipboardExpand all lines: UPGRADE-4.0.md
+11Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,17 @@ DependencyInjection
1818

1919
* Using unsupported options to configure service aliases raises an exception.
2020

21+
* Unsetting or resetting a private shared service from outside of the container
22+
with the `Container::set()` method is no longer supported and will fail with
23+
an exception telling the service does not exist.
24+
25+
* Checking the existence of a private shared service with the `Container::has()`
26+
method is no longer supported and will always return `false`.
27+
28+
* Requesting a private shared service with the `Container::get()` method is no
29+
longer supported and will fail with an exception telling the service does
30+
not exist.
31+
2132
Form
2233
----
2334

‎src/Symfony/Component/DependencyInjection/CHANGELOG.md

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/CHANGELOG.md
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ CHANGELOG
66

77
* allowed to prioritize compiler passes by introducing a third argument to `PassConfig::addPass()`, to `Compiler::addPass` and to `ContainerBuilder::addCompilerPass()`
88
* added support for PHP constants in YAML configuration files
9+
* deprecated the ability to unset or reset a private shared service from outside of the container with the `Container::set()` method
10+
* deprecated the ability to check for the existence of a private shared service with the `Container::has()` method
11+
* deprecated the ability to request a private shared service with the `Container::get()` method outside of the container
912

1013
3.0.0
1114
-----

‎src/Symfony/Component/DependencyInjection/Container.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Container.php
+16Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ class Container implements ResettableContainerInterface
6565

6666
protected $services = array();
6767
protected $methodMap = array();
68+
protected $privates = array();
6869
protected $aliases = array();
6970
protected $loading = array();
7071

@@ -176,6 +177,14 @@ public function set($id, $service)
176177
if (null === $service) {
177178
unset($this->services[$id]);
178179
}
180+
181+
if (isset($this->privates[$id])) {
182+
if (null === $service) {
183+
@trigger_error(sprintf('Unsetting the "%s" private service from outside of the container is deprecated since Symfony 3.2 and won\'t be supported anymore in Symfony 4.0. An exception will be thrown instead in Symfony 4.0.', $id), E_USER_DEPRECATED);
184+
} else {
185+
@trigger_error(sprintf('Resetting the "%s" private service from outside of the container is deprecated since Symfony 3.2 and won\'t be supported anymore in Symfony 4.0. An exception will be thrown instead in Symfony 4.0.', $id), E_USER_DEPRECATED);
186+
}
187+
}
179188
}
180189

181190
/**
@@ -198,6 +207,10 @@ public function has($id)
198207
if (--$i && $id !== $lcId = strtolower($id)) {
199208
$id = $lcId;
200209
} else {
210+
if (isset($this->privates[$id])) {
211+
@trigger_error(sprintf('Checking for the existence of the "%s" private service is deprecated since Symfony 3.2 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED);
212+
}
213+
201214
return method_exists($this, 'get'.strtr($id, $this->underscoreMap).'Service');
202215
}
203216
}
@@ -268,6 +281,9 @@ public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE
268281

269282
return;
270283
}
284+
if (isset($this->privates[$id])) {
285+
@trigger_error(sprintf('Requesting the "%s" private service is deprecated since Symfony 3.2 and won\'t be supported anymore in Symfony 4.0. An exception will be thrown instead in Symfony 4.0.', $id), E_USER_DEPRECATED);
286+
}
271287

272288
$this->loading[$id] = true;
273289

‎src/Symfony/Component/DependencyInjection/ContainerBuilder.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/ContainerBuilder.php
+6-5Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -559,11 +559,12 @@ public function compile()
559559
$compiler->compile($this);
560560
$this->compiled = true;
561561

562-
if ($this->trackResources) {
563-
foreach ($this->definitions as $definition) {
564-
if ($definition->isLazy() && ($class = $definition->getClass()) && class_exists($class)) {
565-
$this->addClassResource(new \ReflectionClass($class));
566-
}
562+
foreach ($this->definitions as $id => $definition) {
563+
if (!$definition->isPublic()) {
564+
$this->privates[$id] = true;
565+
}
566+
if ($this->trackResources && $definition->isLazy() && ($class = $definition->getClass()) && class_exists($class)) {
567+
$this->addClassResource(new \ReflectionClass($class));
567568
}
568569
}
569570

‎src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
+36-5Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,7 @@ private function addService($id, $definition)
566566
$this->referenceVariables = array();
567567
$this->variableCount = 0;
568568

569+
$args = array();
569570
$return = array();
570571

571572
if ($definition->isSynthetic()) {
@@ -623,17 +624,16 @@ private function addService($id, $definition)
623624
EOF;
624625
}
625626

627+
$args = array();
626628
if ($definition->isLazy()) {
627-
$lazyInitialization = '$lazyLoad = true';
629+
$args[] = '$lazyLoad = true';
628630
$lazyInitializationDoc = "\n * @param bool \$lazyLoad whether to try lazy-loading the service with a proxy\n *";
629631
} else {
630-
$lazyInitialization = '';
631632
$lazyInitializationDoc = '';
632633
}
633634

634-
// with proxies, for 5.3.3 compatibility, the getter must be public to be accessible to the initializer
635+
$args = implode(', ', $args);
635636
$isProxyCandidate = $this->getProxyDumper()->isProxyCandidate($definition);
636-
$visibility = $isProxyCandidate ? 'public' : 'protected';
637637
$methodName = $this->generateMethodName($id);
638638
$code = <<<EOF
639639
@@ -642,7 +642,7 @@ private function addService($id, $definition)
642642
*$lazyInitializationDoc
643643
* $return
644644
*/
645-
{$visibility} function {$methodName}($lazyInitialization)
645+
protected function {$methodName}($args)
646646
{
647647
648648
EOF;
@@ -804,6 +804,7 @@ public function __construct()
804804
EOF;
805805

806806
$code .= $this->addMethodMap();
807+
$code .= $this->addPrivateServices();
807808
$code .= $this->addAliases();
808809

809810
$code .= <<<'EOF'
@@ -888,6 +889,36 @@ private function addMethodMap()
888889
return $code." );\n";
889890
}
890891

892+
/**
893+
* Adds the privates property definition.
894+
*
895+
* @return string
896+
*/
897+
private function addPrivateServices()
898+
{
899+
if (!$definitions = $this->container->getDefinitions()) {
900+
return '';
901+
}
902+
903+
$code = '';
904+
ksort($definitions);
905+
foreach ($definitions as $id => $definition) {
906+
if (!$definition->isPublic()) {
907+
$code .= ' '.var_export($id, true)." => true,\n";
908+
}
909+
}
910+
911+
if (empty($code)) {
912+
return '';
913+
}
914+
915+
$out = " \$this->privates = array(\n";
916+
$out .= $code;
917+
$out .= " );\n";
918+
919+
return $out;
920+
}
921+
891922
/**
892923
* Adds the aliases property definition.
893924
*

‎src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php
+62-2Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Symfony\Component\DependencyInjection\Tests;
1313

14+
use Symfony\Bridge\PhpUnit\ErrorAssert;
1415
use Symfony\Component\DependencyInjection\Container;
1516
use Symfony\Component\DependencyInjection\ContainerInterface;
1617
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
@@ -125,7 +126,7 @@ public function testGetServiceIds()
125126

126127
$sc = new ProjectServiceContainer();
127128
$sc->set('foo', $obj = new \stdClass());
128-
$this->assertEquals(array('bar', 'foo_bar', 'foo.baz', 'circular', 'throw_exception', 'throws_exception_on_service_configuration', 'service_container', 'foo'), $sc->getServiceIds(), '->getServiceIds() returns defined service ids by getXXXService() methods, followed by service ids defined by set()');
129+
$this->assertEquals(array('internal', 'bar', 'foo_bar', 'foo.baz', 'circular', 'throw_exception', 'throws_exception_on_service_configuration', 'service_container', 'foo'), $sc->getServiceIds(), '->getServiceIds() returns defined service ids by getXXXService() methods, followed by service ids defined by set()');
129130
}
130131

131132
public function testSet()
@@ -306,11 +307,63 @@ public function testThatCloningIsNotSupported()
306307
$this->assertFalse($class->isCloneable());
307308
$this->assertTrue($clone->isPrivate());
308309
}
310+
311+
/** @group legacy */
312+
public function testUnsetInternalPrivateServiceIsDeprecated()
313+
{
314+
$deprecations = array(
315+
'Unsetting the "internal" private service from outside of the container is deprecated since Symfony 3.2',
316+
);
317+
318+
ErrorAssert::assertDeprecationsAreTriggered($deprecations, function () {
319+
$c = new ProjectServiceContainer();
320+
$c->set('internal', null);
321+
});
322+
}
323+
324+
/** @group legacy */
325+
public function testChangeInternalPrivateServiceIsDeprecated()
326+
{
327+
$deprecations = array(
328+
'Resetting the "internal" private service from outside of the container is deprecated since Symfony 3.2',
329+
);
330+
331+
ErrorAssert::assertDeprecationsAreTriggered($deprecations, function () {
332+
$c = new ProjectServiceContainer();
333+
$c->set('internal', new \stdClass());
334+
});
335+
}
336+
337+
/** @group legacy */
338+
public function testCheckExistenceOfAnInternalPrivateServiceIsDeprecated()
339+
{
340+
$deprecations = array(
341+
'Checking for the existence of the "internal" private service is deprecated since Symfony 3.2',
342+
);
343+
344+
ErrorAssert::assertDeprecationsAreTriggered($deprecations, function () {
345+
$c = new ProjectServiceContainer();
346+
$c->has('internal');
347+
});
348+
}
349+
350+
/** @group legacy */
351+
public function testRequestAnInternalSharedPrivateServiceIsDeprecated()
352+
{
353+
$deprecations = array(
354+
'Requesting the "internal" private service is deprecated since Symfony 3.2',
355+
);
356+
357+
ErrorAssert::assertDeprecationsAreTriggered($deprecations, function () {
358+
$c = new ProjectServiceContainer();
359+
$c->get('internal');
360+
});
361+
}
309362
}
310363

311364
class ProjectServiceContainer extends Container
312365
{
313-
public $__bar, $__foo_bar, $__foo_baz;
366+
public $__bar, $__foo_bar, $__foo_baz, $__internal;
314367

315368
public function __construct()
316369
{
@@ -319,9 +372,16 @@ public function __construct()
319372
$this->__bar = new \stdClass();
320373
$this->__foo_bar = new \stdClass();
321374
$this->__foo_baz = new \stdClass();
375+
$this->__internal = new \stdClass();
376+
$this->privates = array('internal' => true);
322377
$this->aliases = array('alias' => 'bar');
323378
}
324379

380+
protected function getInternalService()
381+
{
382+
return $this->__internal;
383+
}
384+
325385
protected function getBarService()
326386
{
327387
return $this->__bar;

‎src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php
+7Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,13 @@ public function __construct()
4949
'request' => 'getRequestService',
5050
'service_from_static_method' => 'getServiceFromStaticMethodService',
5151
);
52+
$this->privates = array(
53+
'configurator_service' => true,
54+
'configurator_service_simple' => true,
55+
'factory_simple' => true,
56+
'inlined' => true,
57+
'new_factory' => true,
58+
);
5259
$this->aliases = array(
5360
'alias_for_alias' => 'foo',
5461
'alias_for_foo' => 'foo',

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.