8000 [DependencyInjection] improve the deprecation features by handling pa… · symfony/symfony@875b04e · GitHub
[go: up one dir, main page]

Skip to content

Commit 875b04e

Browse files
committed
[DependencyInjection] improve the deprecation features by handling package+version info
1 parent cde44fc commit 875b04e

30 files changed

+257
-41
lines changed

src/Symfony/Component/DependencyInjection/Alias.php

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class Alias
1919
private $public;
2020
private $private;
2121
private $deprecated;
22-
private $deprecationTemplate;
22+
private $deprecation = [];
2323

2424
private static $defaultDeprecationTemplate = 'The "%alias_id%" service alias is deprecated. You should stop using it, as it will be removed in the future.';
2525

@@ -92,7 +92,7 @@ public function isPrivate()
9292
*
9393
* @throws InvalidArgumentException when the message template is invalid
9494
*/
95-
public function setDeprecated(bool $status = true, string $template = null)
95+
public function setDeprecated(bool $status = true, string $template = null, string $package = null, string $sinceVersion = null)
9696
{
9797
if (null !== $template) {
9898
if (preg_match('#[\r\n]|\*/#', $template)) {
@@ -103,7 +103,15 @@ public function setDeprecated(bool $status = true, string $template = null)
103103
throw new InvalidArgumentException('The deprecation template must contain the "%alias_id%" placeholder.');
104104
}
105105

106-
$this->deprecationTemplate = $template;
106+
$this->deprecation['message'] = $template;
107+
}
108+
109+
if (null !== $package) {
110+
$this->deprecation['package'] = $package;
111+
}
112+
113+
if (null !== $sinceVersion) {
114+
$this->deprecation['since_version'] = $sinceVersion;
107115
}
108116

109117
$this->deprecated = $status;
@@ -118,7 +126,21 @@ public function isDeprecated(): bool
118126

119127
public function getDeprecationMessage(string $id): string
120128
{
121-
return str_replace('%alias_id%', $id, $this->deprecationTemplate ?: self::$defaultDeprecationTemplate);
129+
trigger_deprecation('symfony/dependency-injection', '5.1', 'The "%s()" method is deprecated, use "getDeprecation()" instead.', __METHOD__);
130+
131+
return $this->getDeprecation($id)['message'];
132+
}
133+
134+
/**
135+
* @param string $id Service id relying on this definition
136+
*/
137+
public function getDeprecation(string $id): array
138+
{
139+
return [
140+
'message' => str_replace('%alias_id%', $id, $this->deprecation['message'] ?? self::$defaultDeprecationTemplate),
141+
'since_version' => $this->deprecation['since_version'] ?? '',
142+
'package' => $this->deprecation['package'] ?? '',
143+
];
122144
}
123145

124146
/**

src/Symfony/Component/DependencyInjection/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ CHANGELOG
77
* added support to autowire public typed properties in php 7.4
88
* added support for defining method calls, a configurator, and property setters in `InlineServiceConfigurator`
99
* added possibility to define abstract service arguments
10+
* added support for `package` and `since_version` in service/alias deprecations
11+
* deprecated using `Definition::getDeprecationMessage` and `Alias::getDeprecationMessage()`
12+
* deprecated using service/alias deprecation message as xml node content, use `message` attribute instead.
1013

1114
5.0.0
1215
-----

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,8 @@ private function doResolveDefinition(ChildDefinition $definition): Definition
102102
$def->setMethodCalls($parentDef->getMethodCalls());
103103
$def->setProperties($parentDef->getProperties());
104104
if ($parentDef->isDeprecated()) {
105-
$def->setDeprecated(true, $parentDef->getDeprecationMessage('%service_id%'));
105+
$parentDeprecation = $parentDef->getDeprecation('%service_id%');
106+
$def->setDeprecated(true, $parentDeprecation['message'], $parentDeprecation['package'], $parentDeprecation['since_version']);
106107
}
107108
$def->setFactory($parentDef->getFactory());
108< 433 /code>109
$def->setConfigurator($parentDef->getConfigurator());

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,9 @@ private function getDefinitionId(string $id, ContainerBuilder $container): strin
6262
$alias = $container->getAlias($id);
6363

6464
if ($alias->isDeprecated()) {
65-
trigger_deprecation('', '', '%s. It is being referenced by the "%s" %s.', rtrim($alias->getDeprecationMessage($id), '. '), $this->currentId, $container->hasDefinition($this->currentId) ? 'service' : 'alias');
65+
$deprecation = $alias->getDeprecation($id);
66+
67+
trigger_deprecation($deprecation['package'], $deprecation['since_version'], '%s. It is being referenced by the "%s" %s.', rtrim($deprecation['message'], '. '), $this->currentId, $container->hasDefinition($this->currentId) ? 'service' : 'alias');
6668
}
6769

6870
$seen = [];

src/Symfony/Component/DependencyInjection/ContainerBuilder.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -568,7 +568,9 @@ private function doGet(string $id, int $invalidBehavior = ContainerInterface::EX
568568
$alias = $this->aliasDefinitions[$id];
569569

570570
if ($alias->isDeprecated()) {
571-
trigger_deprecation('', '', $alias->getDeprecationMessage($id));
571+
$deprecation = $alias->getDeprecation($id);
572+
573+
trigger_deprecation($deprecation['package'], $deprecation['since_version'], $deprecation['message']);
572574
}
573575

574576
return $this->doGet((string) $alias, $invalidBehavior, $inlineServices, $isConstructorArgument);
@@ -1037,7 +1039,8 @@ private function createService(Definition $definition, array &$inlineServices, b
10371039
}
10381040

10391041
if ($definition->isDeprecated()) {
1040-
trigger_deprecation('', '', $definition->getDeprecationMessage($id));
1042+
$deprecation = $definition->getDeprecation($id);
1043+
trigger_deprecation($deprecation['package'], $deprecation['since_version'], $deprecation['message']);
10411044
}
10421045

10431046
if ($tryProxy && $definition->isLazy() && !$tryProxy = !($proxy = $this->proxyInstantiator) || $proxy instanceof RealServiceInstantiator) {

src/Symfony/Component/DependencyInjection/Definition.php

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class Definition
2727
private $factory;
2828
private $shared = true;
2929
private $deprecated = false;
30-
private $deprecationTemplate;
30+
private $deprecation = [];
3131
private $properties = [];
3232
private $calls = [];
3333
private $instanceof = [];
@@ -711,7 +711,7 @@ public function isAbstract()
711711
*
712712
* @throws InvalidArgumentException when the message template is invalid
713713
*/
714-
public function setDeprecated(bool $status = true, string $template = null)
714+
public function setDeprecated(bool $status = true, string $template = null, string $package = null, string $sinceVersion = null)
715715
{
716716
if (null !== $template) {
717717
if (preg_match('#[\r\n]|\*/#', $template)) {
@@ -722,7 +722,15 @@ public function setDeprecated(bool $status = true, string $template = null)
722722
throw new InvalidArgumentException('The deprecation template must contain the "%service_id%" placeholder.');
723723
}
724724

725-
$this->deprecationTemplate = $template;
725+
$this->deprecation['message'] = $template;
726+
}
727+
728+
if (null !== $package) {
729+
$this->deprecation['package'] = $package;
730+
}
731+
732+
if (null !== $sinceVersion) {
733+
$this->deprecation['since_version'] = $sinceVersion;
726734
}
727735

728736
$this->changes['deprecated'] = true;
@@ -752,7 +760,21 @@ public function isDeprecated()
752760
*/
753761
public function getDeprecationMessage(string $id)
754762
{
755-
return str_replace('%service_id%', $id, $this->deprecationTemplate ?: self::$defaultDeprecationTemplate);
763+
trigger_deprecation('symfony/dependency-injection', '5.1', 'The "%s()" method is deprecated, use "getDeprecation()" instead.', __METHOD__);
764+
765+
return $this->getDeprecation($id)['message'];
766+
}
767+
768+
/**
769+
* @param string $id Service id relying on this definition
770+
*/
771+
public function getDeprecation(string $id): array
772+
{
773+
return [
774+
'message' => str_replace('%service_id%', $id, $this->deprecation['message'] ?? self::$defaultDeprecationTemplate),
775+
'since_version' => $this->deprecation['since_version'] ?? '',
776+
'package' => $this->deprecation['package'] ?? '',
777+
];
756778
}
757779

758780
/**

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

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -760,7 +760,8 @@ private function addService(string $id, Definition $definition): array
760760
$return[] = '';
761761
}
762762

763-
$return[] = sprintf('@deprecated %s', $definition->getDeprecationMessage($id));
763+
$deprecation = $definition->getDeprecation($id);
764+
$return[] = sprintf('@deprecated %s%s', $deprecation['message'], $deprecation['since_version'] ? (' since version '.$deprecation['since_version']) : '');
764765
}
765766

766767
$return = str_replace("\n * \n", "\n *\n", implode("\n * ", $return));
@@ -803,7 +804,8 @@ protected function {$methodName}($lazyInitialization)
803804
$this->inlinedDefinitions = $this->getDefinitionsFromArguments([$definition], null, $this->serviceCalls);
804805

805806
if ($definition->isDeprecated()) {
806-
$code .= sprintf(" trigger_deprecation('', '', %s);\n\n", $this->export($definition->getDeprecationMessage($id)));
807+
$deprecation = $definition->getDeprecation($id);
808+
$code .= sprintf(" trigger_deprecation(%s, %s, %s);\n\n", $this->export($deprecation['package']), $this->export($deprecation['since_version']), $this->export($deprecation['message']));
807809
}
808810

809811
if ($this->getProxyDumper()->isProxyCandidate($definition)) {
@@ -1302,7 +1304,10 @@ private function addDeprecatedAliases(): string
13021304
$id = (string) $definition;
13031305
$methodNameAlias = $this->generateMethodName($alias);
13041306
$idExported = $this->export($id);
1305-
$messageExported = $this->export($definition->getDeprecationMessage($alias));
1307+
$deprecation = $definition->getDeprecation($alias);
1308+
$packageExported = $this->export($deprecation['package']);
1309+
$sinceVersionExported = $this->export($deprecation['since_version']);
1310+
$messageExported = $this->export($deprecation['message']);
13061311
$code .= <<<EOF
13071312
13081313
/*{$this->docStar}
@@ -1312,7 +1317,7 @@ private function addDeprecatedAliases(): string
13121317
*/
13131318
protected function {$methodNameAlias}()
13141319
{
1315-
trigger_deprecation('', '', $messageExported);
1320+
trigger_deprecation($packageExported, $sinceVersionExported, $messageExported);
13161321
13171322
return \$this->get($idExported);
13181323
}

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

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,12 @@ private function addService(Definition $definition, ?string $id, \DOMElement $pa
180180

181181
if ($definition->isDeprecated()) {
182182
$deprecated = $this->document->createElement('deprecated');
183-
$deprecated->appendChild($this->document->createTextNode($definition->getDeprecationMessage('%service_id%')));
183+
184+
foreach ($definition->getDeprecation('%service_id%') as $key => $value) {
185+
if (!empty($value)) {
186+
$deprecated->setAttribute(str_replace('_', '-', $key), $value);
187+
}
188+
}
184189

185190
$service->appendChild($deprecated);
186191
}
@@ -225,8 +230,11 @@ private function addServiceAlias(string $alias, Alias $id, \DOMElement $parent)
225230
}
226231

227232
if ($id->isDeprecated()) {
233+
$deprecation = $id->getDeprecation('%alias_id%');
228234
$deprecated = $this->document->createElement('deprecated');
229-
$deprecated->appendChild($this->document->createTextNode($id->getDeprecationMessage('%alias_id%')));
235+
$deprecated->setAttribute('message', $deprecation['message']);
236+
$deprecated->setAttribute('package', $deprecation['package']);
237+
$deprecated->setAttribute('since_version', $deprecation['since_version']);
230238

231239
$service->appendChild($deprecated);
232240
}

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

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,12 @@ private function addService(string $id, Definition $definition): string
9797
}
9898

9999
if ($definition->isDeprecated()) {
100-
$code .= sprintf(" deprecated: %s\n", $this->dumper->dump($definition->getDeprecationMessage('%service_id%')));
100+
$code .= " deprecated:\n";
101+
foreach ($definition->getDeprecation('%service_id%') as $key => $value) {
102+
if ('' !== $value) {
103+
$code .= sprintf(" %s: %s\n", $key, $this->dumper->dump($value));
104+
}
105+
}
101106
}
102107

103108
if ($definition->isAutowired()) {
@@ -162,7 +167,17 @@ private function addService(string $id, Definition $definition): string
162167

163168
private function addServiceAlias(string $alias, Alias $id): string
164169
{
165-
$deprecated = $id->isDeprecated() ? sprintf(" deprecated: %s\n", $id->getDeprecationMessage('%alias_id%')) : '';
170+
$deprecated = '';
171+
172+
if ($id->isDeprecated()) {
173+
$deprecated = " deprecated:\n";
174+
175+
foreach ($id->getDeprecation('%alias_id%') as $key => $value) {
176+
if (!empty($value)) {
177+
$deprecated .= sprintf(" %s: %s\n", $key, $value);
178+
}
179+
}
180+
}
166181

167182
if ($id->isPrivate()) {
168183
return F438 sprintf(" %s: '@%s'\n%s", $alias, $id, $deprecated);

src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/DeprecateTrait.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,17 @@ trait DeprecateTrait
1818
/**
1919
* Whether this definition is deprecated, that means it should not be called anymore.
2020
*
21-
* @param string $template Template message to use if the definition is deprecated
21+
* @param string $template Template message to use if the definition is deprecated
22+
* @param string $package The name of the Composer package that is triggering the deprecation
23+
* @param string $sinceVersion The version of the package that introduced the deprecation
2224
*
2325
* @return $this
2426
*
2527
* @throws InvalidArgumentException when the message template is invalid
2628
*/
27-
final public function deprecate(string $template = null): self
29+
final public function deprecate(string $template = null, string $package = null, string $sinceVersion = null): self
2830
{
29-
$this->definition->setDeprecated(true, $template);
31+
$this->definition->setDeprecated(true, $template, $package, $sinceVersion);
3032

3133
return $this;
3234
}

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

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,16 @@ private function parseDefinition(\DOMElement $service, string $file, array $defa
205205
}
206206

207207
if ($deprecated = $this->getChildren($service, 'deprecated')) {
208-
$alias->setDeprecated(true, $deprecated[0]->nodeValue ?: null);
208+
$message = $deprecated[0]->getAttribute('message') ?: null;
209+
$package = $deprecated[0]->getAttribute('package') ?: null;
210+
$sinceVersion = $deprecated[0]->getAttribute('since-version') ?: null;
211+
212+
if (!empty($deprecated[0]->nodeValue)) {
213+
$message = $deprecated[0]->nodeValue;
214+
trigger_deprecation('symfony/dependency-injection', '5.1', 'Using deprecation message in content is deprecated, use the attribute "message" instead.');
215+
}
216+
217+
$alias->setDeprecated(true, $message, $package, $sinceVersion);
209218
}
210219

211220
return null;
@@ -284,7 +293,16 @@ private function parseDefinition(\DOMElement $service, string $file, array $defa
284293
}
285294

286295
if ($deprecated = $this->getChildren($service, 'deprecated')) {
287-
$definition->setDeprecated(true, $deprecated[0]->nodeValue ?: null);
296+
$message = $deprecated[0]->getAttribute('message') ?: null;
297+
$package = $deprecated[0]->getAttribute('package') ?: null;
298+
$sinceVersion = $deprecated[0]->getAttribute('since-version') ?: null;
299+
300+
if (!empty($deprecated[0]->nodeValue)) {
301+
$message = $deprecated[0]->nodeValue;
302+
trigger_deprecation('symfony/dependency-injection', '5.1', 'Using deprecation message in content is deprecated, use the attribute "message" instead.');
303+
}
304+
305+
$definition->setDeprecated(true, $message, $package, $sinceVersion);
288306
}
289307

290308
$definition->setArguments($this->getArgumentsAsPhp($service, 'argument', $file, $definition instanceof ChildDefinition));

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,9 @@ private function parseDefinition(string $id, $service, string $file, array $defa
435435
}
436436

437437
if (\array_key_exists('deprecated', $service)) {
438-
$definition->setDeprecated(true, $service['deprecated']);
438+
$deprecation = \is_array($service['deprecated']) ? $service['deprecated'] : ['message' => $service['deprecated']];
439+
440+
$definition->setDeprecated(true, $deprecation['message'], $deprecation['package'] ?? null, $deprecation['since_version'] ?? null);
439441
}
440442

441443
if (isset($service['factory'])) {

src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@
113113
<xsd:element name="argument" type="argument" minOccurs="0" maxOccurs="unbounded" />
114114
<xsd:element name="configurator" type="callable" minOccurs="0" maxOccurs="1" />
115115
<xsd:element name="factory" type="callable" minOccurs="0" maxOccurs="1" />
116-
<xsd:element name="deprecated" type="xsd:string" minOccurs="0" maxOccurs="1" />
116+
<xsd:element name="deprecated" type="deprecated" minOccurs="0" maxOccurs="1" />
117117
<xsd:element name="call" type="call" minOccurs="0" maxOccurs="unbounded" />
118118
<xsd:element name="tag" type="tag" minOccurs="0" maxOccurs="unbounded" />
119119
<xsd:element name="property" type="property" minOccurs="0" maxOccurs="unbounded" />
@@ -157,7 +157,7 @@
157157
<xsd:element name="argument" type="argument" minOccurs="0" maxOccurs="unbounded" />
158158
<xsd:element name="configurator" type="callable" minOccurs="0" maxOccurs="1" />
159159
<xsd:element name="factory" type="callable" minOccurs="0" maxOccurs="1" />
160-
<xsd:element name="deprecated" type="xsd:string" minOccurs="0" maxOccurs="1" />
160+
<xsd:element name="deprecated" type="deprecated" minOccurs="0" maxOccurs="1" />
161161
<xsd:element name="call" type="call" minOccurs="0" maxOccurs="unbounded" />
162162
<xsd:element name="tag" type="tag" minOccurs="0" maxOccurs="unbounded" />
163163
<xsd:element name="property" type="property" minOccurs="0" maxOccurs="unbounded" />
@@ -181,6 +181,16 @@
181181
<xsd:anyAttribute namespace="##any" processContents="lax" />
182182
</xsd:complexType>
183183

184+
<xsd:complexType name="deprecated">
185+
<xsd:simpleContent>
186+
<xsd:extension base="xsd:string">
187+
<xsd:attribute name="message" type="xsd:string" />
188+
<xsd:attribute name="package" type="xsd:string" />
189+
<xsd:attribute name="since-version" type="xsd:string" />
190+
</xsd:extension>
191+
</xsd:simpleContent>
192+
</xsd:complexType>
193+
184194
<xsd:complexType name="parameters">
185195
<xsd:choice minOccurs="1" maxOccurs="unbounded">
186196
<xsd:element name="parameter" type="parameter" />

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,22 @@ public function testDeprecatedAlias()
307307
$builder->get('foobar');
308308
}
309309

310+
/**
311+
* @group legacy
312+
* @expectedDeprecation Since symfony/dependency-injection 5.1: The "foobar" service alias is deprecated. You should stop using it, as it will be removed in the future.
313+
*/
314+
public function testDeprecatedAliasWithPackageAndVersion()
315+
{
316+
$builder = new ContainerBuilder();
317+
$builder->register('foo', 'stdClass');
318+
319+
$alias = new Alias('foo');
320+
$alias->setDeprecated(true, null, 'symfony/dependency-injection', '5.1');
321+
$builder->setAlias('foobar', $alias);
322+
323+
$builder->get('foobar');
324+
}
325+
310326
public function testGetAliases()
311327
{
312328
$builder = new ContainerBuilder();

0 commit comments

Comments
 (0)
0