8000 Added support for deprecating aliases (runtime+dumper) · symfony/symfony@6c571ad · GitHub
[go: up one dir, main page]

Skip to content

Commit 6c571ad

Browse files
author
Renan
committed
Added support for deprecating aliases (runtime+dumper)
1 parent 0eb071b commit 6c571ad

File tree

11 files changed

+226
-30
lines changed

11 files changed

+226
-30
lines changed

src/Symfony/Component/DependencyInjection/Alias.php

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,10 @@ public function isPrivate()
8686
}
8787

8888
/**
89-
* Whether this alias is deprecated, that means it should not be called
89+
* Whether this alias is deprecated, that means it should not be referenced
9090
* anymore.
9191
*
92-
* @param bool $status Defaults to true
92+
* @param bool $status Whether this alias is deprecated, defaults to true
9393
* @param string $template Optional template message to use if the alias is deprecated
9494
*
9595
* @return $this
@@ -115,24 +115,12 @@ public function setDeprecated($status = true, $template = null)
115115
return $this;
116116
}
117117

118-
/**
119-
* Returns whether this alias is deprecated.
120-
*
121-
* @return bool
122-
*/
123-
public function isDeprecated()
118+
public function isDeprecated(): bool
124119
{
125120
return $this->deprecated;
126121
}
127122

128-
/**
129-
* Message to use if this alias is deprecated.
130-
*
131-
* @param string $id Service id relying on this alias
132-
*
133-
* @return string
134-
*/
135-
public function getDeprecationMessage($id)
123+
public function getDeprecationMessage(string $id): string
136124
{
137125
return str_replace('%service_id%', $id, $this->deprecationTemplate ?: self::$defaultDeprecationTemplate);
138126
}

src/Symfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ public function process(ContainerBuilder $container)
3131

3232
foreach ($container->getAliases() as $id => $alias) {
3333
$aliasId = (string) $alias;
34+
3435
if ($aliasId !== $defId = $this->getDefinitionId($aliasId, $container)) {
3536
$container->setAlias($id, $defId)->setPublic($alias->isPublic())->setPrivate($alias->isPrivate());
3637
}
@@ -60,8 +61,15 @@ private function getDefinitionId(string $id, ContainerBuilder $container): strin
6061
if (isset($seen[$id])) {
6162
throw new ServiceCircularReferenceException($id, array_merge(array_keys($seen), [$id]));
6263
}
64+
6365
$seen[$id] = true;
64-
$id = (string) $container->getAlias($id);
66+
$alias = $container->getAlias($id);
67+
68+
if ($alias->isDeprecated()) {
69+
@trigger_error($alias->getDeprecationMessage($id), E_USER_DEPRECATED);
70+
}
71+
72+
$id = (string) $alias;
6573
}
6674

6775
return $id;

src/Symfony/Component/DependencyInjection/ContainerBuilder.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -579,12 +579,13 @@ private function doGet($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_
579579
}
580580

581581
if (!isset($this->definitions[$id]) && isset($this->aliasDefinitions[$id])) {
582-
$aliasDefinition = $this->aliasDefinitions[$id];
583-
if ($aliasDefinition->isDeprecated()) {
584-
@trigger_error($aliasDefinition->getDeprecationMessage($id), E_USER_DEPRECATED);
582+
$alias = $this->aliasDefinitions[$id];
583+
584+
if ($alias->isDeprecated()) {
585+
@trigger_error($alias->getDeprecationMessage($id), E_USER_DEPRECATED);
585586
}
586587

587-
return $this->doGet((string) $aliasDefinition, $invalidBehavior, $inlineServices, $isConstructorArgument);
588+
return $this->doGet((string) $alias, $invalidBehavior, $inlineServices, $isConstructorArgument);
588589
}
589590

590591
try {

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

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ public function dump(array $options = [])
218218
$code =
219219
$this->startClass($options['class'], $baseClass, $baseClassWithNamespace).
220220
$this->addServices($services).
221+
$this->addDeprecatedAliases().
221222
$this->addDefaultParametersMethod()
222223
;
223224

@@ -1115,6 +1116,15 @@ private function addMethodMap(): string
11151116
}
11161117
}
11171118

1119+
$aliases = $this->container->getAliases();
1120+
foreach ($aliases as $alias => $id) {
1121+
if (!$id->isDeprecated()) {
1122+
continue;
1123+
}
1124+
$id = (string) $id;
1125+
$code .= ' '.$this->doExport($alias).' => '.$this->doExport($this->generateMethodName($alias)).",\n";
1126+
}
1127+
11181128
return $code ? " \$this->methodMap = [\n{$code} ];\n" : '';
11191129
}
11201130

@@ -1141,6 +1151,10 @@ private function addAliases(): string
11411151
$code = " \$this->aliases = [\n";
11421152
ksort($aliases);
11431153
foreach ($aliases as $alias => $id) {
1154+
if ($id->isDeprecated()) {
1155+
continue;
1156+
}
1157+
11441158
$id = (string) $id;
11451159
while (isset($aliases[$id])) {
11461160
$id = (string) $aliases[$id];
@@ -1151,6 +1165,39 @@ private function addAliases(): string
11511165
return $code." ];\n";
11521166
}
11531167

1168+
private function addDeprecatedAliases(): string
1169+
{
1170+
$code = '';
1171+
$aliases = $this->container->getAliases();
1172+
foreach ($aliases as $alias => $definition) {
1173+
if (!$definition->isDeprecated()) {
1174+
continue;
1175+
}
1176+
$public = $definition->isPublic() ? 'public' : 'private';
1177+
$id = (string) $definition;
1178+
$methodNameAlias = $this->generateMethodName($alias);
1179+
$idExported = $this->export($id);
1180+
$messageExported = $this->export($definition->getDeprecationMessage($alias));
1181+
$code = <<<EOF
1182+
1183+
/*{$this->docStar}
1184+
* Gets the $public '$alias' alias.
1185+
*
1186+
* @return object The "$id" service.
1187+
*/
1188+
protected function {$methodNameAlias}()
1189+
{
1190+
@trigger_error($messageExported, E_USER_DEPRECATED);
1191+
1192+
return \$this->get($idExported);
1193+
}
1194+
1195+
EOF;
1196+
}
1197+
1198+
return $code;
1199+
}
1200+
11541201
private function addInlineRequires(): string
11551202
{
11561203
if (!$this->hotPathTag || !$this->inlineRequires) {

src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -671,12 +671,11 @@ private function validateAlias(\DOMElement $alias, $file)
671671
}
672672
}
673673

674-
$allowedTags = array('deprecated');
675674
foreach ($alias->childNodes as $child) {
676675
if (!$child instanceof \DOMElement && self::NS !== $child->namespaceURI) {
677676
continue;
678677
}
679-
if (!in_array($child->localName, $allowedTags, true)) {
678+
if (!\in_array($child->localName, ['deprecated'], true)) {
680679
throw new InvalidArgumentException(sprintf('Invalid child element "%s" defined for alias "%s" in "%s".', $child->localName, $alias->getAttribute('id'), $file));
681680
}
682681
}

src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,6 @@ private function parseDefinition($id, $service, $file, array $defaults)
351351
foreach ($service as $key => $value) {
352352
if (!\in_array($key, ['alias', 'public', 'deprecated'])) {
353353
throw new InvalidArgumentException(sprintf('The configuration key "%s" is unsupported for the service "%s" which is defined as an alias in "%s". Allowed configuration keys for service aliases are "alias" and "public".', $key, $id, $file));
354-
continue;
355354
}
356355

357356
if ('deprecated' === $key) {

src/Symfony/Component/DependencyInjection/Tests/AliasTest.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,11 @@ public function testCannotDeprecateWithAnInvalidTemplate($message)
100100

101101
public function invalidDeprecationMessageProvider()
102102
{
103-
return array(
104-
"With \rs" => array("invalid \r message %service_id%"),
105-
"With \ns" => array("invalid \n message %service_id%"),
106-
'With */s' => array('invalid */ message %service_id%'),
107-
'message not containing required %service_id% variable' => array('this is deprecated'),
108-
);
103+
return [
104+
"With \rs" => ["invalid \r message %service_id%"],
105+
"With \ns" => ["invalid \n message %service_id%"],
106+
'With */s' => ['invalid */ message %service_id%'],
107+
'message not containing required %service_id% variable' => ['this is deprecated'],
108+
];
109109
}
110110
}

src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveReferencesToAliasesPassTest.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,48 @@ public function testResolveFactory()
8383
$this->assertSame('Factory', (string) $resolvedBarFactory[0]);
8484
}
8585

86+
/**
87+
* @group legacy
88+
* @expectedDeprecation The "deprecated_foo_alias" service alias is deprecated. You should stop using it, as it will soon be removed.
89+
*/
90+
public function testDeprecationNoticeWhenReferencedByAlias()
91+
{
92+
$container = new ContainerBuilder();
93+
94+
$container->register('foo', 'stdClass');
95+
96+
$aliasDeprecated = new Alias('foo');
97+
$aliasDeprecated->setDeprecated(true);
98+
$container->setAlias('deprecated_foo_alias', $aliasDeprecated);
99+
100+
$alias = new Alias('deprecated_foo_alias');
101+
$container->setAlias('alias', $alias);
102+
103+
$this->process($container);
104+
}
105+
106+
/**
107+
* @group legacy
108+
* @expectedDeprecation The "foo_aliased" service alias is deprecated. You should stop using it, as it will soon be removed.
109+
*/
110+
public function testDeprecationNoticeWhenReferencedByDefinition()
111+
{
112+
$container = new ContainerBuilder();
113+
114+
$container->register('foo', 'stdClass');
115+
116+
$aliasDeprecated = new Alias('foo');
117+
$aliasDeprecated->setDeprecated(true);
118+
$container->setAlias('foo_aliased', $aliasDeprecated);
119+
120+
$container
121+
->register('definition')
122+
->setArguments([new Reference('foo_aliased')])
123+
;
124+
125+
$this->process($container);
126+
}
127+
86128
protected function process(ContainerBuilder $container)
87129
{
88130
$pass = new ResolveReferencesToAliasesPass();

src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,24 @@ public function testAliases()
325325
$this->assertSame($foo, $container->get('alias_for_alias'));
326326
}
327327

328+
/**
329+
* @group legacy
330+
* @expectedDeprecation The "alias_for_foo_deprecated" service alias is deprecated. You should stop using it, as it will soon be removed.
331+
*/
332+
public function testAliasesDeprecation()
333+
{
334+
$container = include self::$fixturesPath.'/containers/container_alias_deprecation.php';
335+
$container->compile();
336+
$dumper = new PhpDumper($container);
337+
338+
$this->assertStringEqualsFile(self::$fixturesPath.'/php/container_alias_deprecation.php', $dumper->dump(['class' => 'Symfony_DI_PhpDumper_Test_Aliases_Deprecation']));
339+
340+
require self::$fixturesPath.'/php/container_alias_deprecation.php';
341+
$container = new \Symfony_DI_PhpDumper_Test_Aliases_Deprecation();
342+
$container->get('alias_for_foo_non_deprecated');
343+
$container->get('alias_for_foo_deprecated');
344+
}
345+
328346
public function testFrozenContainerWithoutAliases()
329347
{
330348
$container = new ContainerBuilder();
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
use Symfony\Component\DependencyInjection\ContainerBuilder;
4+
5+
$container = new ContainerBuilder();
6+
7+
$container
8+
->register('foo', 'stdClass')
9+
->setPublic(true)
10+
;
11+
12+
$container
13+
->setAlias('alias_for_foo_deprecated', 'foo')
14+
->setDeprecated(true)
15+
->setPublic(true);
16+
17+
$container
18+
->setAlias('alias_for_foo_non_deprecated', 'foo')
19+
->setPublic(true);
20+
21+
return $container;
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
3+
use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
4+
use Symfony\Component\DependencyInjection\ContainerInterface;
5+
use Symfony\Component\DependencyInjection\Container;
6+
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
7+
use Symfony\Component\DependencyInjection\Exception\LogicException;
8+
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
9+
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
10+
11+
/**
12+
* This class has been auto-generated
13+
* by the Symfony Dependency Injection Component.
14+
*
15+
* @final since Symfony 3.3
16+
*/
17+
class Symfony_DI_PhpDumper_Test_Aliases_Deprecation extends Container
18+
{
19+
private $parameters;
20+
private $targetDirs = [];
21+
22+
public function __construct()
23+
{
24+
$this->services = $this->privates = [];
25+
$this->methodMap = [
26+
'foo' => 'getFooService',
27+
'alias_for_foo_deprecated' => 'getAliasForFooDeprecatedService',
28+
];
29+
$this->aliases = [
30+
'alias_for_foo_non_deprecated' => 'foo',
31+
];
32+
}
33+
34+
public function compile()
35+
{
36+
throw new LogicException('You cannot compile a dumped container that was already compiled.');
37+
}
38+
39+
public function isCompiled()
40+
{
41+
return true;
42+
}
43+
44+
public function getRemovedIds()
45+
{
46+
return [
47+
'Psr\\Container\\ContainerInterface' => true,
48+
'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true,
49+
];
50+
}
51+
52+
/**
53+
* Gets the public 'foo' shared service.
54+
*
55+
* @return \stdClass
56+
*/
57+
protected function getFooService()
58+
{
59+
return $this->services['foo'] = new \stdClass();
60+
}
61+
62+
/**
63+
* Gets the public 'alias_for_foo_deprecated' alias.
64+
*
65+
* @return object The "foo" service.
66+
*/
67+
protected function getAliasForFooDeprecatedService()
68+
{
69+
@trigger_error('The "alias_for_foo_deprecated" service alias is deprecated. You should stop using it, as it will soon be removed.', E_USER_DEPRECATED);
70+
71+
return $this->get('foo');
72+
}
73+
}

0 commit comments

Comments
 (0)
0