Permalink
Browse files

feature #24238 [DI] Turn services and aliases private by default, wit…

…h BC layer (nicolas-grekas)

This PR was merged into the 3.4 branch.

Discussion
----------

[DI] Turn services and aliases private by default, with BC layer

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

With this PR, all services and aliases are made private by default.
This is done in a BC way, thanks to the layer introduced in #24104.

We will require bundles to explicitly opt-in for "public", either using "defaults", or stating `public="true"` explicitly. Same in DI extension, where calling `->setPublic(true)` will be required in 4.0.

Commits
-------

9948b09 [DI] Turn services and aliases private by default, with BC layer
  • Loading branch information...
nicolas-grekas committed Sep 19, 2017
2 parents 55a7691 + 9948b09 commit ad4bc6b64790d46f33ca52e69f0b1f3dc68f5a72
Showing with 264 additions and 121 deletions.
  1. +7 −4 UPGRADE-3.4.md
  2. +9 −6 UPGRADE-4.0.md
  3. +1 −1 src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Dumper/PhpDumperTest.php
  4. +3 −3 src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
  5. +1 −0 src/Symfony/Bundle/FrameworkBundle/Kernel/MicroKernelTrait.php
  6. +1 −0 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AutowiringTypes/config.yml
  7. +1 −0 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ContainerDebug/config.yml
  8. +1 −0 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Serializer/config.yml
  9. +1 −1 src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/ConcreteMicroKernel.php
  10. +1 −1 src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php
  11. +1 −0 src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Acl/config.yml
  12. +1 −0 src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AutowiringTypes/config.yml
  13. +3 −2 src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php
  14. +2 −2 src/Symfony/Component/Console/composer.json
  15. +3 −1 src/Symfony/Component/DependencyInjection/Alias.php
  16. +1 −0 src/Symfony/Component/DependencyInjection/CHANGELOG.md
  17. +1 −1 src/Symfony/Component/DependencyInjection/Compiler/AutoAliasServicePass.php
  18. +1 −1 src/Symfony/Component/DependencyInjection/Compiler/CheckDefinitionValidityPass.php
  19. +1 −1 src/Symfony/Component/DependencyInjection/Compiler/DecoratorServicePass.php
  20. +1 −0 src/Symfony/Component/DependencyInjection/Compiler/RegisterEnvVarProcessorsPass.php
  21. +1 −1 src/Symfony/Component/DependencyInjection/Compiler/ReplaceAliasByActualDefinitionPass.php
  22. +2 −0 src/Symfony/Component/DependencyInjection/Compiler/ResolveChildDefinitionsPass.php
  23. +1 −1 src/Symfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.php
  24. +2 −1 src/Symfony/Component/DependencyInjection/Definition.php
  25. +4 −4 src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php
  26. +4 −4 src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php
  27. +3 −4 src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php
  28. +10 −4 src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php
  29. +2 −2 src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveChildDefinitionsPassTest.php
  30. +43 −24 src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php
  31. +5 −5 src/Symfony/Component/DependencyInjection/Tests/Dumper/XmlDumperTest.php
  32. +2 −1 src/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php
  33. +1 −0 src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container10.php
  34. +1 −0 src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container11.php
  35. +1 −0 src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container12.php
  36. +2 −0 src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container13.php
  37. +1 −0 src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container15.php
  38. +1 −0 src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container16.php
  39. +1 −0 src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container17.php
  40. +2 −0 src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container19.php
  41. +1 −0 src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container21.php
  42. +1 −0 src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container24.php
  43. +2 −2 src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container33.php
  44. +22 −2 src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php
  45. +1 −0 src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_abstract.php
  46. +3 −0 src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_uninitialized_ref.php
  47. +3 −0 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php
  48. +3 −0 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.php
  49. +3 −0 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php
  50. +3 −0 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php
  51. +3 −0 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php
  52. +3 −0 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php
  53. +3 −0 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services24.php
  54. +3 −0 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php
  55. +3 −0 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services33.php
  56. +3 −0 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php
  57. +1 −0 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt
  58. +1 −0 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php
  59. +3 −0 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php
  60. +3 −0 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_base64_env.php
  61. +1 −12 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_legacy_privates.php
  62. +1 −0 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php
  63. +1 −0 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php
  64. +1 −0 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_in_expression.php
  65. +3 −0 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_rot13_env.php
  66. +1 −0 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php
  67. +1 −0 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_uninitialized_ref.php
  68. +1 −1 src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services21.xml
  69. +1 −1 src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services24.xml
  70. +22 −22 src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml
  71. +1 −1 src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_abstract.xml
  72. +1 −0 src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_without_id.xml
  73. +1 −0 src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services24.yml
  74. +1 −0 src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services26.yml
  75. +26 −2 src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml
  76. +1 −0 src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_inline.yml
  77. +1 −2 src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_legacy_privates.yml
  78. +1 −1 src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php
View
@@ -4,6 +4,9 @@ UPGRADE FROM 3.3 to 3.4
DependencyInjection
-------------------
* Definitions and aliases will be made private by default in 4.0. You should either use service injection
or explicitly define your services as public if you really need to inject the container.
* Relying on service auto-registration while autowiring is deprecated and won't be supported
in Symfony 4.0. Explicitly inject your dependencies or create services
whose ids are their fully-qualified class name.
@@ -154,7 +157,7 @@ FrameworkBundle
* The `Symfony\Bundle\FrameworkBundle\Translation\TranslationLoader`
class has been deprecated and will be removed in 4.0. Use the
`Symfony\Component\Translation\Reader\TranslationReader` class instead.
* The `translation.loader` service has been deprecated and will be removed in 4.0.
Use the `translation.reader` service instead..
@@ -269,9 +272,9 @@ SecurityBundle
Translation
-----------
* `Symfony\Component\Translation\Writer\TranslationWriter::writeTranslations` has been deprecated
and will be removed in 4.0, use `Symfony\Component\Translation\Writer\TranslationWriter::write`
instead.
* `Symfony\Component\Translation\Writer\TranslationWriter::writeTranslations` has been deprecated
and will be removed in 4.0, use `Symfony\Component\Translation\Writer\TranslationWriter::write`
instead.
* Passing a `Symfony\Component\Translation\MessageSelector` to `Translator` has been
deprecated. You should pass a message formatter instead
View
@@ -77,6 +77,9 @@ Debug
DependencyInjection
-------------------
* Definitions and aliases are now private by default in 4.0. You should either use service injection
or explicitly define your services as public if you really need to inject the container.
* Relying on service auto-registration while autowiring is not supported anymore.
Explicitly inject your dependencies or create services whose ids are
their fully-qualified class name.
@@ -449,14 +452,14 @@ FrameworkBundle
* The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslatorPass`
class has been removed. Use the
`Symfony\Component\Translation\DependencyInjection\TranslatorPass` class instead.
* The `Symfony\Bundle\FrameworkBundle\Translation\TranslationLoader`
class has been deprecated and will be removed in 4.0. Use the
`Symfony\Component\Translation\Reader\TranslationReader` class instead.
* The `translation.loader` service has been removed.
Use the `translation.reader` service instead.
* `AssetsInstallCommand::__construct()` now requires an instance of
`Symfony\Component\Filesystem\Filesystem` as first argument.
@@ -673,11 +676,11 @@ Translation
-----------
* Removed the backup feature from the file dumper classes.
* The default value of the `$readerServiceId` argument of `TranslatorPass::__construct()` has been changed to `"translation.reader"`.
* Removed `Symfony\Component\Translation\Writer\TranslationWriter::writeTranslations`,
use `Symfony\Component\Translation\Writer\TranslationWriter::write` instead.
* Removed `Symfony\Component\Translation\Writer\TranslationWriter::writeTranslations`,
use `Symfony\Component\Translation\Writer\TranslationWriter::write` instead.
* Removed support for passing `Symfony\Component\Translation\MessageSelector` as a second argument to the
`Translator::__construct()`. You should pass an instance of `Symfony\Component\Translation\Formatter\MessageFormatterInterface` instead.
@@ -61,7 +61,7 @@ private function dumpLazyServiceProjectServiceContainer()
{
$container = new ContainerBuilder();
$container->register('foo', 'stdClass');
$container->register('foo', 'stdClass')->setPublic(true);
$container->getDefinition('foo')->setLazy(true);
$container->compile();
@@ -1012,12 +1012,12 @@ private function registerTemplatingConfiguration(array $config, ContainerBuilder
// Use a delegation unless only a single engine was registered
if (1 === count($engines)) {
$container->setAlias('templating', (string) reset($engines));
$container->setAlias('templating', (string) reset($engines))->setPublic(true);
} else {
foreach ($engines as $engine) {
$container->getDefinition('templating.engine.delegating')->addMethodCall('addEngine', array($engine));
}
$container->setAlias('templating', 'templating.engine.delegating');
$container->setAlias('templating', 'templating.engine.delegating')->setPublic(true);
}
$container->getDefinition('fragment.renderer.hinclude')
@@ -1213,7 +1213,7 @@ private function registerTranslatorConfiguration(array $config, ContainerBuilder
$container->getDefinition('translation.writer')->setPrivate(true);
// Use the "real" translator instead of the identity default
$container->setAlias('translator', 'translator.default');
$container->setAlias('translator', 'translator.default')->setPublic(true);
$container->setAlias('translator.formatter', new Alias($config['formatter'], false));
$translator = $container->findDefinition('translator.default');
$translator->addMethodCall('setFallbackLocales', array($config['fallbacks']));
@@ -72,6 +72,7 @@ public function registerContainerConfiguration(LoaderInterface $loader)
if ($this instanceof EventSubscriberInterface) {
$container->register('kernel', static::class)
->setSynthetic(true)
->setPublic(true)
->addTag('kernel.event_subscriber')
;
}
@@ -2,6 +2,7 @@ imports:
- { resource: ../config/default.yml }
services:
_defaults: { public: true }
test.autowiring_types.autowired_services:
class: Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\AutowiringTypes\AutowiredServices
autowire: true
@@ -2,6 +2,7 @@ imports:
- { resource: ../config/default.yml }
services:
_defaults: { public: true }
public:
class: Symfony\Bundle\FrameworkBundle\Tests\Fixtures\DeclaredClass
private_alias:
@@ -2,6 +2,7 @@ imports:
- { resource: ../config/default.yml }
services:
_defaults: { public: true }
test.property_info: '@property_info'
framework:
@@ -82,7 +82,7 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load
));
$c->setParameter('halloween', 'Have a great day!');
$c->register('halloween', 'stdClass');
$c->register('halloween', 'stdClass')->setPublic(true);
}
/**
@@ -185,7 +185,7 @@ private function configureDbalAclProvider(array $config, ContainerBuilder $conta
$container->getAlias('security.acl.provider')->setPrivate(true);
if (null !== $config['connection']) {
$container->setAlias('security.acl.dbal.connection', sprintf('doctrine.dbal.%s_connection', $config['connection']));
$container->setAlias('security.acl.dbal.connection', sprintf('doctrine.dbal.%s_connection', $config['connection']))->setPrivate(true);
}
$container
@@ -2,6 +2,7 @@ imports:
- { resource: ./../config/framework.yml }
services:
_defaults: { public: true }
test.security.acl.provider: '@security.acl.provider'
doctrine:
@@ -2,6 +2,7 @@ imports:
- { resource: ../config/framework.yml }
services:
_defaults: { public: true }
test.autowiring_types.autowired_services:
class: Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\AutowiringBundle\AutowiredServices
autowire: true
@@ -65,8 +65,8 @@ public function process(ContainerBuilder $container)
if (isset($serviceIds[$commandId]) || $container->hasAlias($commandId)) {
$commandId = $commandId.'_'.$id;
}
if (!$definition->isPublic()) {
$container->setAlias($commandId, $id);
if (!$definition->isPublic() || $definition->isPrivate()) {
$container->setAlias($commandId, $id)->setPublic(true);
$id = $commandId;
}
$serviceIds[$commandId] = $id;
@@ -97,6 +97,7 @@ public function process(ContainerBuilder $container)
$container
->register($this->commandLoaderServiceId, ContainerCommandLoader::class)
->setPublic(true)
->setArguments(array(ServiceLocatorTagPass::register($container, $lazyCommandRefs), $lazyCommandMap));
$container->setParameter('console.command.ids', $serviceIds);
@@ -23,7 +23,7 @@
"require-dev": {
"symfony/config": "~3.3|~4.0",
"symfony/event-dispatcher": "~2.8|~3.0|~4.0",
"symfony/dependency-injection": "~3.3|~4.0",
"symfony/dependency-injection": "~3.4|~4.0",
"symfony/lock": "~3.4|~4.0",
"symfony/process": "~3.3|~4.0",
"psr/log": "~1.0"
@@ -35,7 +35,7 @@
"psr/log": "For using the console logger"
},
"conflict": {
"symfony/dependency-injection": "<3.3",
"symfony/dependency-injection": "<3.4",
"symfony/process": "<3.3"
},
"autoload": {
@@ -15,7 +15,7 @@ class Alias
{
private $id;
private $public;
private $private = false;
private $private;
/**
* @param string $id Alias identifier
@@ -25,6 +25,7 @@ public function __construct($id, $public = true)
{
$this->id = (string) $id;
$this->public = $public;
$this->private = 2 > func_num_args();
}
/**
@@ -47,6 +48,7 @@ public function isPublic()
public function setPublic($boolean)
{
$this->public = (bool) $boolean;
$this->private = false;
return $this;
}
@@ -4,6 +4,7 @@ CHANGELOG
3.4.0
-----
* deprecated "public-by-default" definitions and aliases, the new default will be "private" in 4.0
* added `EnvVarProcessorInterface` and corresponding "container.env_var_processor" tag for processing env vars
* added support for ignore-on-uninitialized references
* deprecated service auto-registration while autowiring
@@ -33,7 +33,7 @@ public function process(ContainerBuilder $container)
$aliasId = $container->getParameterBag()->resolveValue($tag['format']);
if ($container->hasDefinition($aliasId) || $container->hasAlias($aliasId)) {
$container->setAlias($serviceId, new Alias($aliasId));
$container->setAlias($serviceId, new Alias($aliasId, true));
}
}
}
@@ -39,7 +39,7 @@ public function process(ContainerBuilder $container)
{
foreach ($container->getDefinitions() as $id => $definition) {
// synthetic service is public
if ($definition->isSynthetic() && (!$definition->isPublic() || $definition->isPrivate())) {
if ($definition->isSynthetic() && !($definition->isPublic() || $definition->isPrivate())) {
throw new RuntimeException(sprintf('A synthetic service ("%s") must be public.', $id));
}
@@ -67,7 +67,7 @@ public function process(ContainerBuilder $container)
$container->setDefinition($renamedId, $decoratedDefinition);
}
$container->setAlias($inner, $id)->setPublic($public && !$private)->setPrivate($private);
$container->setAlias($inner, $id)->setPublic($public)->setPrivate($private);
}
}
}
@@ -52,6 +52,7 @@ public function process(ContainerBuilder $container)
$bag->setProvidedTypes($types);
}
$container->register('container.env_var_processors_locator', ServiceLocator::class)
->setPublic(true)
->setArguments(array($processors))
;
}
@@ -45,7 +45,7 @@ public function process(ContainerBuilder $container)
}
// Check if target needs to be replaces
if (isset($replacements[$targetId])) {
$container->setAlias($definitionId, $replacements[$targetId]);
$container->setAlias($definitionId, $replacements[$targetId])->setPublic($target->isPublic())->setPrivate($target->isPrivate());
}
// No need to process the same target twice
if (isset($seenAliasTargets[$targetId])) {
@@ -36,12 +36,14 @@ public function process(ContainerBuilder $container)
foreach ($container->getDefinitions() as $definition) {
if ($definition->isPrivate()) {
$definition->setPublic(false);
$definition->setPrivate(true);
}
}
foreach ($container->getAliases() as $alias) {
if ($alias->isPrivate()) {
$alias->setPublic(false);
$alias->setPrivate(true);
}
}
}
@@ -32,7 +32,7 @@ public function process(ContainerBuilder $container)
foreach ($container->getAliases() as $id => $alias) {
$aliasId = (string) $alias;
if ($aliasId !== $defId = $this->getDefinitionId($aliasId, $container)) {
$container->setAlias($id, $defId)->setPublic($alias->isPublic() && !$alias->isPrivate())->setPrivate($alias->isPrivate());
$container->setAlias($id, $defId)->setPublic($alias->isPublic())->setPrivate($alias->isPrivate());
}
}
}
@@ -35,7 +35,7 @@ class Definition
private $configurator;
private $tags = array();
private $public = true;
private $private = false;
private $private = true;
private $synthetic = false;
private $abstract = false;
private $lazy = false;
@@ -603,6 +603,7 @@ public function setPublic($boolean)
$this->changes['public'] = true;
$this->public = (bool) $boolean;
$this->private = false;
return $this;
}
@@ -122,8 +122,8 @@ private function addService($definition, $id, \DOMElement $parent)
if (!$definition->isShared()) {
$service->setAttribute('shared', 'false');
}
if (!$definition->isPublic()) {
$service->setAttribute('public', 'false');
if (!$definition->isPrivate()) {
$service->setAttribute('public', $definition->isPublic() ? 'true' : 'false');
}
if ($definition->isSynthetic()) {
$service->setAttribute('synthetic', 'true');
@@ -242,8 +242,8 @@ private function addServiceAlias($alias, Alias $id, \DOMElement $parent)
$service = $this->document->createElement('service');
$service->setAttribute('id', $alias);
$service->setAttribute('alias', $id);
if (!$id->isPublic()) {
$service->setAttribute('public', 'false');
if (!$id->isPrivate()) {
$service->setAttribute('public', $id->isPublic() ? 'true' : 'false');
}
$parent->appendChild($service);
}
@@ -74,8 +74,8 @@ private function addService($id, $definition)
$code .= sprintf(" class: %s\n", $this->dumper->dump($class));
}
if (!$definition->isPublic()) {
$code .= " public: false\n";
if (!$definition->isPrivate()) {
$code .= sprintf(" public: %s\n", $definition->isPublic() ? 'true' : 'false');
}
$tagsCode = '';
@@ -178,11 +178,11 @@ private function addService($id, $definition)
*/
private function addServiceAlias($alias, $id)
{
if ($id->isPublic()) {
if ($id->isPrivate()) {
return sprintf(" %s: '@%s'\n", $alias, $id);
}
return sprintf(" %s:\n alias: %s\n public: false\n", $alias, $id);
return sprintf(" %s:\n alias: %s\n public: %s\n", $alias, $id, $id->isPublic() ? 'true' : 'false');
}
/**
@@ -203,13 +203,12 @@ private function parseDefinition(\DOMElement $service, $file, array $defaults)
if ($alias = $service->getAttribute('alias')) {
$this->validateAlias($service, $file);
$public = true;
$this->container->setAlias((string) $service->getAttribute('id'), $alias = new Alias($alias));
if ($publicAttr = $service->getAttribute('public')) {
$public = XmlUtils::phpize($publicAttr);
$alias->setPublic(XmlUtils::phpize($publicAttr));
} elseif (isset($defaults['public'])) {
$public = $defaults['public'];
$alias->setPublic($defaults['public']);
}
$this->container->setAlias((string) $service->getAttribute('id'), new Alias($alias, $public));
return;
}
Oops, something went wrong.

0 comments on commit ad4bc6b

Please sign in to comment.