feature #35778 [DI] Improve the deprecation features by handling package and version (atailouloute)

This PR was merged into the 5.1-dev branch.

Discussion
----------

[DI] Improve the deprecation features by handling package and version

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| Deprecations? | yes
| Tickets       |
| License       | MIT
| Doc PR        | TODO

Improve the deprecation feature of the Dependency Injection component, by handling the `package` + `since_version`

Before
```yaml
services:
    LegacyService:
        deprecated: 'The %service_id% is deprecated, use NewService instead'
```

now:
```yaml
services:
    LegacyService:
        deprecated:
            message: 'The %service_id% is deprecated, use NewService instead'
            package: 'my/package'
            since_version: '1.2'
```

TODO:
- [x] update UPGRADE

Commits
-------

f10413cf34 [DependencyInjection] improve the deprecation features by handling package+version info
This commit is contained in:
Nicolas Grekas 2020-03-31 21:52:01 +02:00
commit c8f4d1655e
45 changed files with 467 additions and 110 deletions

View File

@ -6,6 +6,13 @@ Console
* `Command::setHidden()` is final since Symfony 5.1 * `Command::setHidden()` is final since Symfony 5.1
DependencyInjection
-------------------
* The signature of method `Definition::setDeprecated()` has been updated to `Definition::setDeprecation(string $package, string $version, string $message)`.
* The signature of method `Alias::setDeprecated()` has been updated to `Alias::setDeprecation(string $package, string $version, string $message)`.
* The signature of method `DeprecateTrait::deprecate()` has been updated to `DeprecateTrait::deprecation(string $package, string $version, string $message)`.
Dotenv Dotenv
------ ------

View File

@ -6,6 +6,13 @@ Console
* `Command::setHidden()` has a default value (`true`) for `$hidden` parameter * `Command::setHidden()` has a default value (`true`) for `$hidden` parameter
DependencyInjection
-------------------
* The signature of method `Definition::setDeprecated()` has been updated to `Definition::setDeprecation(string $package, string $version, string $message)`.
* The signature of method `Alias::setDeprecated()` has been updated to `Alias::setDeprecation(string $package, string $version, string $message)`.
* The signature of method `DeprecateTrait::deprecate()` has been updated to `DeprecateTrait::deprecation(string $package, string $version, string $message)`.
Dotenv Dotenv
------ ------

View File

@ -18,8 +18,7 @@ class Alias
private $id; private $id;
private $public; private $public;
private $private; private $private;
private $deprecated; private $deprecation = [];
private $deprecationTemplate;
private static $defaultDeprecationTemplate = 'The "%alias_id%" service alias is deprecated. You should stop using it, as it will be removed in the future.'; private static $defaultDeprecationTemplate = 'The "%alias_id%" service alias is deprecated. You should stop using it, as it will be removed in the future.';
@ -28,7 +27,6 @@ class Alias
$this->id = $id; $this->id = $id;
$this->public = $public; $this->public = $public;
$this->private = 2 > \func_num_args(); $this->private = 2 > \func_num_args();
$this->deprecated = false;
} }
/** /**
@ -85,40 +83,76 @@ class Alias
* Whether this alias is deprecated, that means it should not be referenced * Whether this alias is deprecated, that means it should not be referenced
* anymore. * anymore.
* *
* @param bool $status Whether this alias is deprecated, defaults to true * @param string $package The name of the composer package that is triggering the deprecation
* @param string $template Optional template message to use if the alias is deprecated * @param string $version The version of the package that introduced the deprecation
* @param string $message The deprecation message to use
* *
* @return $this * @return $this
* *
* @throws InvalidArgumentException when the message template is invalid * @throws InvalidArgumentException when the message template is invalid
*/ */
public function setDeprecated(bool $status = true, string $template = null) public function setDeprecated(/* string $package, string $version, string $message */)
{ {
if (null !== $template) { $args = \func_get_args();
if (preg_match('#[\r\n]|\*/#', $template)) {
if (\func_num_args() < 3) {
trigger_deprecation('symfony/dependency-injection', '5.1', 'The signature of method "%s()" requires 3 arguments: "string $package, string $version, string $message", not defining them is deprecated.', __METHOD__);
$status = $args[0] ?? true;
if (!$status) {
trigger_deprecation('symfony/dependency-injection', '5.1', 'Passing a null message to un-deprecate a node is deprecated.');
}
$message = (string) ($args[1] ?? null);
$package = $version = '';
} else {
$status = true;
$package = (string) $args[0];
$version = (string) $args[1];
$message = (string) $args[2];
}
if ('' !== $message) {
if (preg_match('#[\r\n]|\*/#', $message)) {
throw new InvalidArgumentException('Invalid characters found in deprecation template.'); throw new InvalidArgumentException('Invalid characters found in deprecation template.');
} }
if (false === strpos($template, '%alias_id%')) { if (false === strpos($message, '%alias_id%')) {
throw new InvalidArgumentException('The deprecation template must contain the "%alias_id%" placeholder.'); throw new InvalidArgumentException('The deprecation template must contain the "%alias_id%" placeholder.');
} }
$this->deprecationTemplate = $template;
} }
$this->deprecated = $status; $this->deprecation = $status ? ['package' => $package, 'version' => $version, 'message' => $message ?: self::$defaultDeprecationTemplate] : [];
return $this; return $this;
} }
public function isDeprecated(): bool public function isDeprecated(): bool
{ {
return $this->deprecated; return (bool) $this->deprecation;
} }
/**
* @deprecated since Symfony 5.1, use "getDeprecation()" instead.
*/
public function getDeprecationMessage(string $id): string public function getDeprecationMessage(string $id): string
{ {
return str_replace('%alias_id%', $id, $this->deprecationTemplate ?: self::$defaultDeprecationTemplate); trigger_deprecation('symfony/dependency-injection', '5.1', 'The "%s()" method is deprecated, use "getDeprecation()" instead.', __METHOD__);
return $this->getDeprecation($id)['message'];
}
/**
* @param string $id Service id relying on this definition
*/
public function getDeprecation(string $id): array
{
return [
'package' => $this->deprecation['package'],
'version' => $this->deprecation['version'],
'message' => str_replace('%alias_id%', $id, $this->deprecation['message']),
];
} }
/** /**

View File

@ -7,6 +7,9 @@ CHANGELOG
* added support to autowire public typed properties in php 7.4 * added support to autowire public typed properties in php 7.4
* added support for defining method calls, a configurator, and property setters in `InlineServiceConfigurator` * added support for defining method calls, a configurator, and property setters in `InlineServiceConfigurator`
* added possibility to define abstract service arguments * added possibility to define abstract service arguments
* updated the signature of method `Definition::setDeprecated()` to `Definition::setDeprecation(string $package, string $version, string $message)`
* updated the signature of method `Alias::setDeprecated()` to `Alias::setDeprecation(string $package, string $version, string $message)`
* updated the signature of method `DeprecateTrait::deprecate()` to `DeprecateTrait::deprecation(string $package, string $version, string $message)`
5.0.0 5.0.0
----- -----

View File

@ -102,7 +102,8 @@ class ResolveChildDefinitionsPass extends AbstractRecursivePass
$def->setMethodCalls($parentDef->getMethodCalls()); $def->setMethodCalls($parentDef->getMethodCalls());
$def->setProperties($parentDef->getProperties()); $def->setProperties($parentDef->getProperties());
if ($parentDef->isDeprecated()) { if ($parentDef->isDeprecated()) {
$def->setDeprecated(true, $parentDef->getDeprecationMessage('%service_id%')); $deprecation = $parentDef->getDeprecation('%service_id%');
$def->setDeprecated($deprecation['package'], $deprecation['version'], $deprecation['message']);
} }
$def->setFactory($parentDef->getFactory()); $def->setFactory($parentDef->getFactory());
$def->setConfigurator($parentDef->getConfigurator()); $def->setConfigurator($parentDef->getConfigurator());
@ -137,7 +138,12 @@ class ResolveChildDefinitionsPass extends AbstractRecursivePass
$def->setLazy($definition->isLazy()); $def->setLazy($definition->isLazy());
} }
if (isset($changes['deprecated'])) { if (isset($changes['deprecated'])) {
$def->setDeprecated($definition->isDeprecated(), $definition->getDeprecationMessage('%service_id%')); if ($definition->isDeprecated()) {
$deprecation = $definition->getDeprecation('%service_id%');
$def->setDeprecated($deprecation['package'], $deprecation['version'], $deprecation['message']);
} else {
$def->setDeprecated(false);
}
} }
if (isset($changes['autowired'])) { if (isset($changes['autowired'])) {
$def->setAutowired($definition->isAutowired()); $def->setAutowired($definition->isAutowired());

View File

@ -62,7 +62,8 @@ class ResolveReferencesToAliasesPass extends AbstractRecursivePass
$alias = $container->getAlias($id); $alias = $container->getAlias($id);
if ($alias->isDeprecated()) { if ($alias->isDeprecated()) {
trigger_deprecation('', '', '%s. It is being referenced by the "%s" %s.', rtrim($alias->getDeprecationMessage($id), '. '), $this->currentId, $container->hasDefinition($this->currentId) ? 'service' : 'alias'); $deprecation = $alias->getDeprecation($id);
trigger_deprecation($deprecation['package'], $deprecation['version'], rtrim($deprecation['message'], '. ').'. It is being referenced by the "%s" '.($container->hasDefinition($this->currentId) ? 'service.' : 'alias.'), rtrim($deprecation['message'], '. '), $this->currentId);
} }
$seen = []; $seen = [];

View File

@ -568,7 +568,8 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
$alias = $this->aliasDefinitions[$id]; $alias = $this->aliasDefinitions[$id];
if ($alias->isDeprecated()) { if ($alias->isDeprecated()) {
trigger_deprecation('', '', $alias->getDeprecationMessage($id)); $deprecation = $alias->getDeprecation($id);
trigger_deprecation($deprecation['package'], $deprecation['version'], $deprecation['message']);
} }
return $this->doGet((string) $alias, $invalidBehavior, $inlineServices, $isConstructorArgument); return $this->doGet((string) $alias, $invalidBehavior, $inlineServices, $isConstructorArgument);
@ -1037,7 +1038,8 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
} }
if ($definition->isDeprecated()) { if ($definition->isDeprecated()) {
trigger_deprecation('', '', $definition->getDeprecationMessage($id)); $deprecation = $definition->getDeprecation($id);
trigger_deprecation($deprecation['package'], $deprecation['version'], $deprecation['message']);
} }
if ($tryProxy && $definition->isLazy() && !$tryProxy = !($proxy = $this->proxyInstantiator) || $proxy instanceof RealServiceInstantiator) { if ($tryProxy && $definition->isLazy() && !$tryProxy = !($proxy = $this->proxyInstantiator) || $proxy instanceof RealServiceInstantiator) {

View File

@ -26,8 +26,7 @@ class Definition
private $file; private $file;
private $factory; private $factory;
private $shared = true; private $shared = true;
private $deprecated = false; private $deprecation = [];
private $deprecationTemplate;
private $properties = []; private $properties = [];
private $calls = []; private $calls = [];
private $instanceof = []; private $instanceof = [];
@ -705,29 +704,48 @@ class Definition
* Whether this definition is deprecated, that means it should not be called * Whether this definition is deprecated, that means it should not be called
* anymore. * anymore.
* *
* @param string $template Template message to use if the definition is deprecated * @param string $package The name of the composer package that is triggering the deprecation
* @param string $version The version of the package that introduced the deprecation
* @param string $message The deprecation message to use
* *
* @return $this * @return $this
* *
* @throws InvalidArgumentException when the message template is invalid * @throws InvalidArgumentException when the message template is invalid
*/ */
public function setDeprecated(bool $status = true, string $template = null) public function setDeprecated(/* string $package, string $version, string $message */)
{ {
if (null !== $template) { $args = \func_get_args();
if (preg_match('#[\r\n]|\*/#', $template)) {
if (\func_num_args() < 3) {
trigger_deprecation('symfony/dependency-injection', '5.1', 'The signature of method "%s()" requires 3 arguments: "string $package, string $version, string $message", not defining them is deprecated.', __METHOD__);
$status = $args[0] ?? true;
if (!$status) {
trigger_deprecation('symfony/dependency-injection', '5.1', 'Passing a null message to un-deprecate a node is deprecated.');
}
$message = (string) ($args[1] ?? null);
$package = $version = '';
} else {
$status = true;
$package = (string) $args[0];
$version = (string) $args[1];
$message = (string) $args[2];
}
if ('' !== $message) {
if (preg_match('#[\r\n]|\*/#', $message)) {
throw new InvalidArgumentException('Invalid characters found in deprecation template.'); throw new InvalidArgumentException('Invalid characters found in deprecation template.');
} }
if (false === strpos($template, '%service_id%')) { if (false === strpos($message, '%service_id%')) {
throw new InvalidArgumentException('The deprecation template must contain the "%service_id%" placeholder.'); throw new InvalidArgumentException('The deprecation template must contain the "%service_id%" placeholder.');
} }
$this->deprecationTemplate = $template;
} }
$this->changes['deprecated'] = true; $this->changes['deprecated'] = true;
$this->deprecation = $status ? ['package' => $package, 'version' => $version, 'message' => $message ?: self::$defaultDeprecationTemplate] : [];
$this->deprecated = $status;
return $this; return $this;
} }
@ -740,19 +758,35 @@ class Definition
*/ */
public function isDeprecated() public function isDeprecated()
{ {
return $this->deprecated; return (bool) $this->deprecation;
} }
/** /**
* Message to use if this definition is deprecated. * Message to use if this definition is deprecated.
* *
* @deprecated since Symfony 5.1, use "getDeprecation()" instead.
*
* @param string $id Service id relying on this definition * @param string $id Service id relying on this definition
* *
* @return string * @return string
*/ */
public function getDeprecationMessage(string $id) public function getDeprecationMessage(string $id)
{ {
return str_replace('%service_id%', $id, $this->deprecationTemplate ?: self::$defaultDeprecationTemplate); trigger_deprecation('symfony/dependency-injection', '5.1', 'The "%s()" method is deprecated, use "getDeprecation()" instead.', __METHOD__);
return $this->getDeprecation($id)['message'];
}
/**
* @param string $id Service id relying on this definition
*/
public function getDeprecation(string $id): array
{
return [
'package' => $this->deprecation['package'],
'version' => $this->deprecation['version'],
'message' => str_replace('%service_id%', $id, $this->deprecation['message']),
];
} }
/** /**

View File

@ -786,7 +786,8 @@ EOF;
$return[] = ''; $return[] = '';
} }
$return[] = sprintf('@deprecated %s', $definition->getDeprecationMessage($id)); $deprecation = $definition->getDeprecation($id);
$return[] = sprintf('@deprecated %s', ($deprecation['package'] || $deprecation['version'] ? "Since {$deprecation['package']} {$deprecation['version']}: " : '').$deprecation['message']);
} }
$return = str_replace("\n * \n", "\n *\n", implode("\n * ", $return)); $return = str_replace("\n * \n", "\n *\n", implode("\n * ", $return));
@ -835,7 +836,8 @@ EOF;
$this->inlinedDefinitions = $this->getDefinitionsFromArguments([$definition], null, $this->serviceCalls); $this->inlinedDefinitions = $this->getDefinitionsFromArguments([$definition], null, $this->serviceCalls);
if ($definition->isDeprecated()) { if ($definition->isDeprecated()) {
$code .= sprintf(" trigger_deprecation('', '', %s);\n\n", $this->export($definition->getDeprecationMessage($id))); $deprecation = $definition->getDeprecation($id);
$code .= sprintf(" trigger_deprecation(%s, %s, %s);\n\n", $this->export($deprecation['package']), $this->export($deprecation['version']), $this->export($deprecation['message']));
} else { } else {
foreach ($this->inlinedDefinitions as $def) { foreach ($this->inlinedDefinitions as $def) {
foreach ($this->getClasses($def) as $class) { foreach ($this->getClasses($def) as $class) {
@ -1341,7 +1343,10 @@ EOF;
$id = (string) $definition; $id = (string) $definition;
$methodNameAlias = $this->generateMethodName($alias); $methodNameAlias = $this->generateMethodName($alias);
$idExported = $this->export($id); $idExported = $this->export($id);
$messageExported = $this->export($definition->getDeprecationMessage($alias)); $deprecation = $definition->getDeprecation($alias);
$packageExported = $this->export($deprecation['package']);
$versionExported = $this->export($deprecation['version']);
$messageExported = $this->export($deprecation['message']);
$code .= <<<EOF $code .= <<<EOF
/*{$this->docStar} /*{$this->docStar}
@ -1351,7 +1356,7 @@ EOF;
*/ */
protected function {$methodNameAlias}() protected function {$methodNameAlias}()
{ {
trigger_deprecation('', '', $messageExported); trigger_deprecation($packageExported, $versionExported, $messageExported);
return \$this->get($idExported); return \$this->get($idExported);
} }

View File

@ -179,8 +179,11 @@ class XmlDumper extends Dumper
} }
if ($definition->isDeprecated()) { if ($definition->isDeprecated()) {
$deprecation = $definition->getDeprecation('%service_id%');
$deprecated = $this->document->createElement('deprecated'); $deprecated = $this->document->createElement('deprecated');
$deprecated->appendChild($this->document->createTextNode($definition->getDeprecationMessage('%service_id%'))); $deprecated->appendChild($this->document->createTextNode($definition->getDeprecation('%service_id%')['message']));
$deprecated->setAttribute('package', $deprecation['package']);
$deprecated->setAttribute('version', $deprecation['version']);
$service->appendChild($deprecated); $service->appendChild($deprecated);
} }
@ -225,8 +228,11 @@ class XmlDumper extends Dumper
} }
if ($id->isDeprecated()) { if ($id->isDeprecated()) {
$deprecation = $id->getDeprecation('%alias_id%');
$deprecated = $this->document->createElement('deprecated'); $deprecated = $this->document->createElement('deprecated');
$deprecated->appendChild($this->document->createTextNode($id->getDeprecationMessage('%alias_id%'))); $deprecated->setAttribute('message', $deprecation['message']);
$deprecated->setAttribute('package', $deprecation['package']);
$deprecated->setAttribute('version', $deprecation['version']);
$service->appendChild($deprecated); $service->appendChild($deprecated);
} }

View File

@ -97,7 +97,12 @@ class YamlDumper extends Dumper
} }
if ($definition->isDeprecated()) { if ($definition->isDeprecated()) {
$code .= sprintf(" deprecated: %s\n", $this->dumper->dump($definition->getDeprecationMessage('%service_id%'))); $code .= " deprecated:\n";
foreach ($definition->getDeprecation('%service_id%') as $key => $value) {
if ('' !== $value) {
$code .= sprintf(" %s: %s\n", $key, $this->dumper->dump($value));
}
}
} }
if ($definition->isAutowired()) { if ($definition->isAutowired()) {
@ -162,7 +167,17 @@ class YamlDumper extends Dumper
private function addServiceAlias(string $alias, Alias $id): string private function addServiceAlias(string $alias, Alias $id): string
{ {
$deprecated = $id->isDeprecated() ? sprintf(" deprecated: %s\n", $id->getDeprecationMessage('%alias_id%')) : ''; $deprecated = '';
if ($id->isDeprecated()) {
$deprecated = " deprecated:\n";
foreach ($id->getDeprecation('%alias_id%') as $key => $value) {
if ('' !== $value) {
$deprecated .= sprintf(" %s: %s\n", $key, $value);
}
}
}
if ($id->isPrivate()) { if ($id->isPrivate()) {
return sprintf(" %s: '@%s'\n%s", $alias, $id, $deprecated); return sprintf(" %s: '@%s'\n%s", $alias, $id, $deprecated);

View File

@ -18,15 +18,30 @@ trait DeprecateTrait
/** /**
* Whether this definition is deprecated, that means it should not be called anymore. * Whether this definition is deprecated, that means it should not be called anymore.
* *
* @param string $template Template message to use if the definition is deprecated * @param string $package The name of the composer package that is triggering the deprecation
* @param string $version The version of the package that introduced the deprecation
* @param string $message The deprecation message to use
* *
* @return $this * @return $this
* *
* @throws InvalidArgumentException when the message template is invalid * @throws InvalidArgumentException when the message template is invalid
*/ */
final public function deprecate(string $template = null): self final public function deprecate(/* string $package, string $version, string $message */): self
{ {
$this->definition->setDeprecated(true, $template); $args = \func_get_args();
$package = $version = $message = '';
if (\func_num_args() < 3) {
trigger_deprecation('symfony/dependency-injection', '5.1', 'The signature of method "%s()" requires 3 arguments: "string $package, string $version, string $message", not defining them is deprecated.', __METHOD__);
$message = (string) ($args[0] ?? null);
} else {
$package = (string) $args[0];
$version = (string) $args[1];
$message = (string) $args[2];
}
$this->definition->setDeprecated($package, $version, $message);
return $this; return $this;
} }

View File

@ -205,7 +205,19 @@ class XmlFileLoader extends FileLoader
} }
if ($deprecated = $this->getChildren($service, 'deprecated')) { if ($deprecated = $this->getChildren($service, 'deprecated')) {
$alias->setDeprecated(true, $deprecated[0]->nodeValue ?: null); $message = $deprecated[0]->nodeValue ?: '';
$package = $deprecated[0]->getAttribute('package') ?: '';
$version = $deprecated[0]->getAttribute('version') ?: '';
if (!$deprecated[0]->hasAttribute('package')) {
trigger_deprecation('symfony/dependency-injection', '5.1', 'Not setting the attribute "package" of the node "deprecated" is deprecated.');
}
if (!$deprecated[0]->hasAttribute('version')) {
trigger_deprecation('symfony/dependency-injection', '5.1', 'Not setting the attribute "version" of the node "deprecated" is deprecated.');
}
$alias->setDeprecated($package, $version, $message);
} }
return null; return null;
@ -284,7 +296,19 @@ class XmlFileLoader extends FileLoader
} }
if ($deprecated = $this->getChildren($service, 'deprecated')) { if ($deprecated = $this->getChildren($service, 'deprecated')) {
$definition->setDeprecated(true, $deprecated[0]->nodeValue ?: null); $message = $deprecated[0]->nodeValue ?: '';
$package = $deprecated[0]->getAttribute('package') ?: '';
$version = $deprecated[0]->getAttribute('version') ?: '';
if ('' === $package) {
trigger_deprecation('symfony/dependency-injection', '5.1', 'Not setting the attribute "package" of the node "deprecated" is deprecated.');
}
if ('' === $version) {
trigger_deprecation('symfony/dependency-injection', '5.1', 'Not setting the attribute "version" of the node "deprecated" is deprecated.');
}
$definition->setDeprecated($package, $version, $message);
} }
$definition->setArguments($this->getArgumentsAsPhp($service, 'argument', $file, $definition instanceof ChildDefinition)); $definition->setArguments($this->getArgumentsAsPhp($service, 'argument', $file, $definition instanceof ChildDefinition));

View File

@ -358,7 +358,17 @@ class YamlFileLoader extends FileLoader
} }
if ('deprecated' === $key) { if ('deprecated' === $key) {
$alias->setDeprecated(true, $value); $deprecation = \is_array($value) ? $value : ['message' => $value];
if (!isset($deprecation['package'])) {
trigger_deprecation('symfony/dependency-injection', '5.1', 'Not setting the attribute "package" of the "deprecated" option is deprecated.');
}
if (!isset($deprecation['version'])) {
trigger_deprecation('symfony/dependency-injection', '5.1', 'Not setting the attribute "version" of the "deprecated" option is deprecated.');
}
$alias->setDeprecated($deprecation['package'] ?? '', $deprecation['version'] ?? '', $deprecation['message']);
} }
} }
@ -435,7 +445,17 @@ class YamlFileLoader extends FileLoader
} }
if (\array_key_exists('deprecated', $service)) { if (\array_key_exists('deprecated', $service)) {
$definition->setDeprecated(true, $service['deprecated']); $deprecation = \is_array($service['deprecated']) ? $service['deprecated'] : ['message' => $service['deprecated']];
if (!isset($deprecation['package'])) {
trigger_deprecation('symfony/dependency-injection', '5.1', 'Not setting the attribute "package" of the "deprecated" option is deprecated.');
}
if (!isset($deprecation['version'])) {
trigger_deprecation('symfony/dependency-injection', '5.1', 'Not setting the attribute "version" of the "deprecated" option is deprecated.');
}
$definition->setDeprecated($deprecation['package'] ?? '', $deprecation['version'] ?? '', $deprecation['message']);
} }
if (isset($service['factory'])) { if (isset($service['factory'])) {

View File

@ -113,7 +113,7 @@
<xsd:element name="argument" type="argument" minOccurs="0" maxOccurs="unbounded" /> <xsd:element name="argument" type="argument" minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="configurator" type="callable" minOccurs="0" maxOccurs="1" /> <xsd:element name="configurator" type="callable" minOccurs="0" maxOccurs="1" />
<xsd:element name="factory" type="callable" minOccurs="0" maxOccurs="1" /> <xsd:element name="factory" type="callable" minOccurs="0" maxOccurs="1" />
<xsd:element name="deprecated" type="xsd:string" minOccurs="0" maxOccurs="1" /> <xsd:element name="deprecated" type="deprecated" minOccurs="0" maxOccurs="1" />
<xsd:element name="call" type="call" minOccurs="0" maxOccurs="unbounded" /> <xsd:element name="call" type="call" minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="tag" type="tag" minOccurs="0" maxOccurs="unbounded" /> <xsd:element name="tag" type="tag" minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="property" type="property" minOccurs="0" maxOccurs="unbounded" /> <xsd:element name="property" type="property" minOccurs="0" maxOccurs="unbounded" />
@ -157,7 +157,7 @@
<xsd:element name="argument" type="argument" minOccurs="0" maxOccurs="unbounded" /> <xsd:element name="argument" type="argument" minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="configurator" type="callable" minOccurs="0" maxOccurs="1" /> <xsd:element name="configurator" type="callable" minOccurs="0" maxOccurs="1" />
<xsd:element name="factory" type="callable" minOccurs="0" maxOccurs="1" /> <xsd:element name="factory" type="callable" minOccurs="0" maxOccurs="1" />
<xsd:element name="deprecated" type="xsd:string" minOccurs="0" maxOccurs="1" /> <xsd:element name="deprecated" type="deprecated" minOccurs="0" maxOccurs="1" />
<xsd:element name="call" type="call" minOccurs="0" maxOccurs="unbounded" /> <xsd:element name="call" type="call" minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="tag" type="tag" minOccurs="0" maxOccurs="unbounded" /> <xsd:element name="tag" type="tag" minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="property" type="property" minOccurs="0" maxOccurs="unbounded" /> <xsd:element name="property" type="property" minOccurs="0" maxOccurs="unbounded" />
@ -181,6 +181,16 @@
<xsd:anyAttribute namespace="##any" processContents="lax" /> <xsd:anyAttribute namespace="##any" processContents="lax" />
</xsd:complexType> </xsd:complexType>
<xsd:complexType name="deprecated">
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<!-- In Symfony 6, make these attributes required -->
<xsd:attribute name="package" type="xsd:string" />
<xsd:attribute name="version" type="xsd:string" />
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
<xsd:complexType name="parameters"> <xsd:complexType name="parameters">
<xsd:choice minOccurs="1" maxOccurs="unbounded"> <xsd:choice minOccurs="1" maxOccurs="unbounded">
<xsd:element name="parameter" type="parameter" /> <xsd:element name="parameter" type="parameter" />

View File

@ -52,33 +52,59 @@ class AliasTest extends TestCase
public function testCanDeprecateAnAlias() public function testCanDeprecateAnAlias()
{ {
$alias = new Alias('foo', false); $alias = new Alias('foo', false);
$alias->setDeprecated(true, 'The %alias_id% service is deprecated.'); $alias->setDeprecated('vendor/package', '1.1', 'The %alias_id% service is deprecated.');
$this->assertTrue($alias->isDeprecated()); $this->assertTrue($alias->isDeprecated());
} }
/**
* @group legacy
* @expectedDeprecation Since symfony/dependency-injection 5.1: The signature of method "Symfony\Component\DependencyInjection\Alias::setDeprecated()" requires 3 arguments: "string $package, string $version, string $message", not defining them is deprecated.
*/
public function testItHasADefaultDeprecationMessage() public function testItHasADefaultDeprecationMessage()
{ {
$alias = new Alias('foo', false); $alias = new Alias('foo', false);
$alias->setDeprecated(); $alias->setDeprecated();
$expectedMessage = 'The "foo" service alias is deprecated. You should stop using it, as it will be removed in the future.'; $expectedMessage = 'The "foo" service alias is deprecated. You should stop using it, as it will be removed in the future.';
$this->assertEquals($expectedMessage, $alias->getDeprecationMessage('foo')); $this->assertEquals($expectedMessage, $alias->getDeprecation('foo')['message']);
} }
public function testReturnsCorrectDeprecationMessage() /**
* @group legacy
* @expectedDeprecation Since symfony/dependency-injection 5.1: The signature of method "Symfony\Component\DependencyInjection\Alias::setDeprecated()" requires 3 arguments: "string $package, string $version, string $message", not defining them is deprecated.
*/
public function testSetDeprecatedWithoutPackageAndVersion()
{
$def = new Alias('stdClass');
$def->setDeprecated(true, '%alias_id%');
$deprecation = $def->getDeprecation('deprecated_alias');
$this->assertSame('deprecated_alias', $deprecation['message']);
$this->assertSame('', $deprecation['package']);
$this->assertSame('', $deprecation['version']);
}
public function testReturnsCorrectDeprecation()
{ {
$alias = new Alias('foo', false); $alias = new Alias('foo', false);
$alias->setDeprecated(true, 'The "%alias_id%" is deprecated.'); $alias->setDeprecated('vendor/package', '1.1', 'The "%alias_id%" is deprecated.');
$expectedMessage = 'The "foo" is deprecated.'; $deprecation = $alias->getDeprecation('foo');
$this->assertEquals($expectedMessage, $alias->getDeprecationMessage('foo')); $this->assertEquals('The "foo" is deprecated.', $deprecation['message']);
$this->assertEquals('vendor/package', $deprecation['package']);
$this->assertEquals('1.1', $deprecation['version']);
} }
/**
* @group legacy
* @expectedDeprecation Since symfony/dependency-injection 5.1: The signature of method "Symfony\Component\DependencyInjection\Alias::setDeprecated()" requires 3 arguments: "string $package, string $version, string $message", not defining them is deprecated.
* @expectedDeprecation Since symfony/dependency-injection 5.1: Passing a null message to un-deprecate a node is deprecated.
*/
public function testCanOverrideDeprecation() public function testCanOverrideDeprecation()
{ {
$alias = new Alias('foo', false); $alias = new Alias('foo', false);
$alias->setDeprecated(); $alias->setDeprecated('vendor/package', '1.1', 'The "%alias_id%" is deprecated.');
$this->assertTrue($alias->isDeprecated()); $this->assertTrue($alias->isDeprecated());
$alias->setDeprecated(false); $alias->setDeprecated(false);
@ -92,7 +118,7 @@ class AliasTest extends TestCase
{ {
$this->expectException('Symfony\Component\DependencyInjection\Exception\InvalidArgumentException'); $this->expectException('Symfony\Component\DependencyInjection\Exception\InvalidArgumentException');
$def = new Alias('foo'); $def = new Alias('foo');
$def->setDeprecated(true, $message); $def->setDeprecated('package', '1.1', $message);
} }
public function invalidDeprecationMessageProvider() public function invalidDeprecationMessageProvider()

View File

@ -679,7 +679,7 @@ class AutowirePassTest extends TestCase
public function testProcessDoesNotTriggerDeprecations() public function testProcessDoesNotTriggerDeprecations()
{ {
$container = new ContainerBuilder(); $container = new ContainerBuilder();
$container->register('deprecated', 'Symfony\Component\DependencyInjection\Tests\Fixtures\DeprecatedClass')->setDeprecated(true); $container->register('deprecated', 'Symfony\Component\DependencyInjection\Tests\Fixtures\DeprecatedClass')->setDeprecated('vendor/package', '1.1', '%service_id%');
$container->register('foo', Foo::class); $container->register('foo', Foo::class);
$container->register('bar', Bar::class)->setAutowired(true); $container->register('bar', Bar::class)->setAutowired(true);

View File

@ -298,7 +298,7 @@ class ResolveChildDefinitionsPassTest extends TestCase
{ {
$container = new ContainerBuilder(); $container = new ContainerBuilder();
$container->register('deprecated_parent') $container->register('deprecated_parent')
->setDeprecated(true) ->setDeprecated('vendor/package', '1.1', '%service_id%')
; ;
$container->setDefinition('decorated_deprecated_parent', new ChildDefinition('deprecated_parent')); $container->setDefinition('decorated_deprecated_parent', new ChildDefinition('deprecated_parent'));
@ -308,6 +308,11 @@ class ResolveChildDefinitionsPassTest extends TestCase
$this->assertTrue($container->getDefinition('decorated_deprecated_parent')->isDeprecated()); $this->assertTrue($container->getDefinition('decorated_deprecated_parent')->isDeprecated());
} }
/**
* @group legacy
* @expectedDeprecation Since symfony/dependency-injection 5.1: The signature of method "Symfony\Component\DependencyInjection\Definition::setDeprecated()" requires 3 arguments: "string $package, string $version, string $message", not defining them is deprecated.
* @expectedDeprecation Since symfony/dependency-injection 5.1: Passing a null message to un-deprecate a node is deprecated.
*/
public function testDecoratedServiceCanOverwriteDeprecatedParentStatus() public function testDecoratedServiceCanOverwriteDeprecatedParentStatus()
{ {
$container = new ContainerBuilder(); $container = new ContainerBuilder();

View File

@ -41,8 +41,8 @@ class ResolveHotPathPassTest extends TestCase
->addArgument(new Reference('lazy')) ->addArgument(new Reference('lazy'))
->addArgument(new Reference('lazy')); ->addArgument(new Reference('lazy'));
$container->register('buz'); $container->register('buz');
$container->register('deprec_with_tag')->setDeprecated()->addTag('container.hot_path'); $container->register('deprec_with_tag')->setDeprecated('vendor/package', '1.1', '%service_id%')->addTag('container.hot_path');
$container->register('deprec_ref_notag')->setDeprecated(); $container->register('deprec_ref_notag')->setDeprecated('vendor/package', '1.1', '%service_id%');
(new ResolveHotPathPass())->process($container); (new ResolveHotPathPass())->process($container);

View File

@ -174,11 +174,28 @@ class DefinitionTest extends TestCase
{ {
$def = new Definition('stdClass'); $def = new Definition('stdClass');
$this->assertFalse($def->isDeprecated(), '->isDeprecated() returns false by default'); $this->assertFalse($def->isDeprecated(), '->isDeprecated() returns false by default');
$this->assertSame($def, $def->setDeprecated(true), '->setDeprecated() implements a fluent interface'); $this->assertSame($def, $def->setDeprecated('vendor/package', '1.1', '%service_id%'), '->setDeprecated() implements a fluent interface');
$this->assertTrue($def->isDeprecated(), '->isDeprecated() returns true if the instance should not be used anymore.'); $this->assertTrue($def->isDeprecated(), '->isDeprecated() returns true if the instance should not be used anymore.');
$deprecation = $def->getDeprecation('deprecated_service');
$this->assertSame('deprecated_service', $deprecation['message'], '->getDeprecation() should return an array with the formatted message template');
$this->assertSame('vendor/package', $deprecation['package']);
$this->assertSame('1.1', $deprecation['version']);
}
/**
* @group legacy
* @expectedDeprecation Since symfony/dependency-injection 5.1: The signature of method "Symfony\Component\DependencyInjection\Definition::setDeprecated()" requires 3 arguments: "string $package, string $version, string $message", not defining them is deprecated.
*/
public function testSetDeprecatedWithoutPackageAndVersion()
{
$def = new Definition('stdClass');
$def->setDeprecated(true, '%service_id%'); $def->setDeprecated(true, '%service_id%');
$this->assertSame('deprecated_service', $def->getDeprecationMessage('deprecated_service'), '->getDeprecationMessage() should return given formatted message template');
$deprecation = $def->getDeprecation('deprecated_service');
$this->assertSame('deprecated_service', $deprecation['message']);
$this->assertSame('', $deprecation['package']);
$this->assertSame('', $deprecation['version']);
} }
/** /**
@ -188,7 +205,7 @@ class DefinitionTest extends TestCase
{ {
$this->expectException('Symfony\Component\DependencyInjection\Exception\InvalidArgumentException'); $this->expectException('Symfony\Component\DependencyInjection\Exception\InvalidArgumentException');
$def = new Definition('stdClass'); $def = new Definition('stdClass');
$def->setDeprecated(false, $message); $def->setDeprecated('vendor/package', '1.1', $message);
} }
public function invalidDeprecationMessageProvider() public function invalidDeprecationMessageProvider()
@ -341,7 +358,7 @@ class DefinitionTest extends TestCase
$def->setAutowired(true); $def->setAutowired(true);
$def->setConfigurator('configuration_func'); $def->setConfigurator('configuration_func');
$def->setDecoratedService(null); $def->setDecoratedService(null);
$def->setDeprecated(true); $def->setDeprecated('vendor/package', '1.1', '%service_id%');
$def->setFactory('factory_func'); $def->setFactory('factory_func');
$def->setFile('foo.php'); $def->setFile('foo.php');
$def->setLazy(true); $def->setLazy(true);

View File

@ -0,0 +1,10 @@
<?php
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
return function (ContainerConfigurator $c) {
$c->services()
->set('foo', 'stdClass')
->deprecate('%service_id%')
;
};

View File

@ -10,7 +10,10 @@ services:
tags: tags:
- { name: foo } - { name: foo }
- { name: baz } - { name: baz }
deprecated: '%service_id%' deprecated:
package: vendor/package
version: '1.1'
message: '%service_id%'
arguments: [1] arguments: [1]
factory: f factory: f
Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Sub\Bar: Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Sub\Bar:
@ -19,7 +22,10 @@ services:
tags: tags:
- { name: foo } - { name: foo }
- { name: baz } - { name: baz }
deprecated: '%service_id%' deprecated:
package: vendor/package
version: '1.1'
message: '%service_id%'
lazy: true lazy: true
arguments: [1] arguments: [1]
factory: f factory: f

View File

@ -11,7 +11,7 @@ return function (ContainerConfigurator $c) {
->autoconfigure() ->autoconfigure()
->exclude('../Prototype/{OtherDir,BadClasses,SinglyImplementedInterface}') ->exclude('../Prototype/{OtherDir,BadClasses,SinglyImplementedInterface}')
->factory('f') ->factory('f')
->deprecate('%service_id%') ->deprecate('vendor/package', '1.1', '%service_id%')
->args([0]) ->args([0])
->args([1]) ->args([1])
->autoconfigure(false) ->autoconfigure(false)

View File

@ -10,7 +10,10 @@ services:
tags: tags:
- { name: foo } - { name: foo }
- { name: baz } - { name: baz }
deprecated: '%service_id%' deprecated:
package: vendor/package
version: '1.1'
message: '%service_id%'
arguments: [1] arguments: [1]
factory: f factory: f
Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Sub\Bar: Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Sub\Bar:
@ -19,7 +22,10 @@ services:
tags: tags:
- { name: foo } - { name: foo }
- { name: baz } - { name: baz }
deprecated: '%service_id%' deprecated:
package: vendor/package
version: '1.1'
message: '%service_id%'
lazy: true lazy: true
arguments: [1] arguments: [1]
factory: f factory: f

View File

@ -11,7 +11,7 @@ return function (ContainerConfigurator $c) {
->autoconfigure() ->autoconfigure()
->exclude(['../Prototype/OtherDir', '../Prototype/BadClasses', '../Prototype/SinglyImplementedInterface']) ->exclude(['../Prototype/OtherDir', '../Prototype/BadClasses', '../Prototype/SinglyImplementedInterface'])
->factory('f') ->factory('f')
->deprecate('%service_id%') ->deprecate('vendor/package', '1.1', '%service_id%')
->args([0]) ->args([0])
->args([1]) ->args([1])
->autoconfigure(false) ->autoconfigure(false)

View File

@ -88,7 +88,7 @@ return function (ContainerConfigurator $c) {
->decorate('decorated', 'decorated.pif-pouf'); ->decorate('decorated', 'decorated.pif-pouf');
$s->set('deprecated_service', 'stdClass') $s->set('deprecated_service', 'stdClass')
->deprecate(); ->deprecate('vendor/package', '1.1', 'The "%service_id%" service is deprecated. You should stop using it, as it will be removed in the future.');
$s->set('new_factory', 'FactoryClass') $s->set('new_factory', 'FactoryClass')
->property('foo', 'bar') ->property('foo', 'bar')
@ -105,7 +105,7 @@ return function (ContainerConfigurator $c) {
->factory(['Bar\FooClass', 'getInstance']); ->factory(['Bar\FooClass', 'getInstance']);
$s->set('factory_simple', 'SimpleFactoryClass') $s->set('factory_simple', 'SimpleFactoryClass')
->deprecate() ->deprecate('vendor/package', '1.1', 'The "%service_id%" service is deprecated. You should stop using it, as it will be removed in the future.')
->args(['foo']) ->args(['foo'])
->private(); ->private();

View File

@ -115,7 +115,7 @@ $container
; ;
$container $container
->register('deprecated_service', 'stdClass') ->register('deprecated_service', 'stdClass')
->setDeprecated(true) ->setDeprecated('vendor/package', '1.1', 'The "%service_id%" service is deprecated. You should stop using it, as it will be removed in the future.')
->setPublic(true) ->setPublic(true)
; ;
$container $container
@ -142,7 +142,7 @@ $container
$container $container
->register('factory_simple', 'SimpleFactoryClass') ->register('factory_simple', 'SimpleFactoryClass')
->addArgument('foo') ->addArgument('foo')
->setDeprecated(true) ->setDeprecated('vendor/package', '1.1', 'The "%service_id%" service is deprecated. You should stop using it, as it will be removed in the future.')
->setPublic(false) ->setPublic(false)
; ;
$container $container

View File

@ -239,11 +239,11 @@ class getDeprecatedServiceService extends ProjectServiceContainer
* *
* @return \stdClass * @return \stdClass
* *
* @deprecated The "deprecated_service" service is deprecated. You should stop using it, as it will be removed in the future. * @deprecated Since vendor/package 1.1: The "deprecated_service" service is deprecated. You should stop using it, as it will be removed in the future.
*/ */
public static function do($container, $lazyLoad = true) public static function do($container, $lazyLoad = true)
{ {
trigger_deprecation('', '', 'The "deprecated_service" service is deprecated. You should stop using it, as it will be removed in the future.'); trigger_deprecation('vendor/package', '1.1', 'The "deprecated_service" service is deprecated. You should stop using it, as it will be removed in the future.');
return $container->services['deprecated_service'] = new \stdClass(); return $container->services['deprecated_service'] = new \stdClass();
} }
@ -312,11 +312,11 @@ class getFactorySimpleService extends ProjectServiceContainer
* *
* @return \SimpleFactoryClass * @return \SimpleFactoryClass
* *
* @deprecated The "factory_simple" service is deprecated. You should stop using it, as it will be removed in the future. * @deprecated Since vendor/package 1.1: The "factory_simple" service is deprecated. You should stop using it, as it will be removed in the future.
*/ */
public static function do($container, $lazyLoad = true) public static function do($container, $lazyLoad = true)
{ {
trigger_deprecation('', '', 'The "factory_simple" service is deprecated. You should stop using it, as it will be removed in the future.'); trigger_deprecation('vendor/package', '1.1', 'The "factory_simple" service is deprecated. You should stop using it, as it will be removed in the future.');
return new \SimpleFactoryClass('foo'); return new \SimpleFactoryClass('foo');
} }

View File

@ -203,11 +203,11 @@ class ProjectServiceContainer extends Container
* *
* @return \stdClass * @return \stdClass
* *
* @deprecated The "deprecated_service" service is deprecated. You should stop using it, as it will be removed in the future. * @deprecated Since vendor/package 1.1: The "deprecated_service" service is deprecated. You should stop using it, as it will be removed in the future.
*/ */
protected function getDeprecatedServiceService() protected function getDeprecatedServiceService()
{ {
trigger_deprecation('', '', 'The "deprecated_service" service is deprecated. You should stop using it, as it will be removed in the future.'); trigger_deprecation('vendor/package', '1.1', 'The "deprecated_service" service is deprecated. You should stop using it, as it will be removed in the future.');
return $this->services['deprecated_service'] = new \stdClass(); return $this->services['deprecated_service'] = new \stdClass();
} }
@ -397,11 +397,11 @@ class ProjectServiceContainer extends Container
* *
* @return \SimpleFactoryClass * @return \SimpleFactoryClass
* *
* @deprecated The "factory_simple" service is deprecated. You should stop using it, as it will be removed in the future. * @deprecated Since vendor/package 1.1: The "factory_simple" service is deprecated. You should stop using it, as it will be removed in the future.
*/ */
protected function getFactorySimpleService() protected function getFactorySimpleService()
{ {
trigger_deprecation('', '', 'The "factory_simple" service is deprecated. You should stop using it, as it will be removed in the future.'); trigger_deprecation('vendor/package', '1.1', 'The "factory_simple" service is deprecated. You should stop using it, as it will be removed in the future.');
return new \SimpleFactoryClass('foo'); return new \SimpleFactoryClass('foo');
} }

View File

@ -226,11 +226,11 @@ class ProjectServiceContainer extends Container
* *
* @return \stdClass * @return \stdClass
* *
* @deprecated The "deprecated_service" service is deprecated. You should stop using it, as it will be removed in the future. * @deprecated Since vendor/package 1.1: The "deprecated_service" service is deprecated. You should stop using it, as it will be removed in the future.
*/ */
protected function getDeprecatedServiceService() protected function getDeprecatedServiceService()
{ {
trigger_deprecation('', '', 'The "deprecated_service" service is deprecated. You should stop using it, as it will be removed in the future.'); trigger_deprecation('vendor/package', '1.1', 'The "deprecated_service" service is deprecated. You should stop using it, as it will be removed in the future.');
return $this->services['deprecated_service'] = new \stdClass(); return $this->services['deprecated_service'] = new \stdClass();
} }
@ -448,11 +448,11 @@ class ProjectServiceContainer extends Container
* *
* @return \SimpleFactoryClass * @return \SimpleFactoryClass
* *
* @deprecated The "factory_simple" service is deprecated. You should stop using it, as it will be removed in the future. * @deprecated Since vendor/package 1.1: The "factory_simple" service is deprecated. You should stop using it, as it will be removed in the future.
*/ */
protected function getFactorySimpleService() protected function getFactorySimpleService()
{ {
trigger_deprecation('', '', 'The "factory_simple" service is deprecated. You should stop using it, as it will be removed in the future.'); trigger_deprecation('vendor/package', '1.1', 'The "factory_simple" service is deprecated. You should stop using it, as it will be removed in the future.');
return new \SimpleFactoryClass('foo'); return new \SimpleFactoryClass('foo');
} }

View File

@ -203,11 +203,11 @@ class Symfony_DI_PhpDumper_Errored_Definition extends Container
* *
* @return \stdClass * @return \stdClass
* *
* @deprecated The "deprecated_service" service is deprecated. You should stop using it, as it will be removed in the future. * @deprecated Since vendor/package 1.1: The "deprecated_service" service is deprecated. You should stop using it, as it will be removed in the future.
*/ */
protected function getDeprecatedServiceService() protected function getDeprecatedServiceService()
{ {
trigger_deprecation('', '', 'The "deprecated_service" service is deprecated. You should stop using it, as it will be removed in the future.'); trigger_deprecation('vendor/package', '1.1', 'The "deprecated_service" service is deprecated. You should stop using it, as it will be removed in the future.');
return $this->services['deprecated_service'] = new \stdClass(); return $this->services['deprecated_service'] = new \stdClass();
} }
@ -397,11 +397,11 @@ class Symfony_DI_PhpDumper_Errored_Definition extends Container
* *
* @return \SimpleFactoryClass * @return \SimpleFactoryClass
* *
* @deprecated The "factory_simple" service is deprecated. You should stop using it, as it will be removed in the future. * @deprecated Since vendor/package 1.1: The "factory_simple" service is deprecated. You should stop using it, as it will be removed in the future.
*/ */
protected function getFactorySimpleService() protected function getFactorySimpleService()
{ {
trigger_deprecation('', '', 'The "factory_simple" service is deprecated. You should stop using it, as it will be removed in the future.'); trigger_deprecation('vendor/package', '1.1', 'The "factory_simple" service is deprecated. You should stop using it, as it will be removed in the future.');
return new \SimpleFactoryClass('foo'); return new \SimpleFactoryClass('foo');
} }

View File

@ -44,7 +44,7 @@ class Symfony_DI_PhpDumper_Test_Rot13Parameters extends Container
public function getRemovedIds(): array public function getRemovedIds(): array
{ {
return [ return [
'.service_locator.ZZqL6HL' => true, '.service_locator.PnIy5ic' => true,
'Psr\\Container\\ContainerInterface' => true, 'Psr\\Container\\ContainerInterface' => true,
'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true, 'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true,
]; ];

View File

@ -45,7 +45,7 @@ class Symfony_DI_PhpDumper_Service_Locator_Argument extends Container
public function getRemovedIds(): array public function getRemovedIds(): array
{ {
return [ return [
'.service_locator.iSxuxv5' => true, '.service_locator.VAwNRfI' => true,
'Psr\\Container\\ContainerInterface' => true, 'Psr\\Container\\ContainerInterface' => true,
'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true, 'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true,
'foo2' => true, 'foo2' => true,

View File

@ -42,8 +42,8 @@ class ProjectServiceContainer extends Container
public function getRemovedIds(): array public function getRemovedIds(): array
{ {
return [ return [
'.service_locator.2Wk0Efb' => true, '.service_locator.Csd_kfL' => true,
'.service_locator.2Wk0Efb.foo_service' => true, '.service_locator.Csd_kfL.foo_service' => true,
'Psr\\Container\\ContainerInterface' => true, 'Psr\\Container\\ContainerInterface' => true,
'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true, 'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true,
'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CustomDefinition' => true, 'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CustomDefinition' => true,

View File

@ -4,10 +4,10 @@
<service id="foo" class="Foo"> <service id="foo" class="Foo">
</service> </service>
<service id="alias_for_foo" alias="foo"> <service id="alias_for_foo" alias="foo">
<deprecated>The "%alias_id%" service alias is deprecated. You should stop using it, as it will be removed in the future.</deprecated> <deprecated package="vendor/package" version="1.1">The "%alias_id%" service alias is deprecated. You should stop using it, as it will be removed in the future.</deprecated>
</service> </service>
<service id="alias_for_foobar" alias="foobar"> <service id="alias_for_foobar" alias="foobar">
<deprecated>The "%alias_id%" service alias is deprecated.</deprecated> <deprecated package="vendor/package" version="1.1">The "%alias_id%" service alias is deprecated.</deprecated>
</service> </service>
</services> </services>
</container> </container>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="foo" class="Foo">
</service>
<service id="alias_for_foo" alias="foo">
<deprecated>The "%alias_id%" service alias is deprecated. You should stop using it, as it will be removed in the future.</deprecated>
</service>
</services>
</container>

View File

@ -97,7 +97,7 @@
<service id="decorator_service" class="stdClass" public="true" decorates="decorated"/> <service id="decorator_service" class="stdClass" public="true" decorates="decorated"/>
<service id="decorator_service_with_name" class="stdClass" public="true" decorates="decorated" decoration-inner-name="decorated.pif-pouf"/> <service id="decorator_service_with_name" class="stdClass" public="true" decorates="decorated" decoration-inner-name="decorated.pif-pouf"/>
<service id="deprecated_service" class="stdClass" public="true"> <service id="deprecated_service" class="stdClass" public="true">
<deprecated>The "%service_id%" service is deprecated. You should stop using it, as it will be removed in the future.</deprecated> <deprecated package="vendor/package" version="1.1">The "%service_id%" service is deprecated. You should stop using it, as it will be removed in the future.</deprecated>
</service> </service>
<service id="new_factory" class="FactoryClass" public="false"> <service id="new_factory" class="FactoryClass" public="false">
<property name="foo">bar</property> <property name="foo">bar</property>
@ -114,7 +114,7 @@
</service> </service>
<service id="factory_simple" class="SimpleFactoryClass" public="false"> <service id="factory_simple" class="SimpleFactoryClass" public="false">
<argument>foo</argument> <argument>foo</argument>
<deprecated>The "%service_id%" service is deprecated. You should stop using it, as it will be removed in the future.</deprecated> <deprecated package="vendor/package" version="1.1">The "%service_id%" service is deprecated. You should stop using it, as it will be removed in the future.</deprecated>
</service> </service>
<service id="factory_service_simple" class="Bar" public="true"> <service id="factory_service_simple" class="Bar" public="true">
<factory service="factory_simple" method="getInstance"/> <factory service="factory_simple" method="getInstance"/>

View File

@ -2,10 +2,10 @@
<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd"> <container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd">
<services> <services>
<service id="foo" class="Foo"> <service id="foo" class="Foo">
<deprecated /> <deprecated package="vendor/package" version="1.1" />
</service> </service>
<service id="bar" class="Bar"> <service id="bar" class="Bar">
<deprecated>The "%service_id%" service is deprecated.</deprecated> <deprecated package="vendor/package" version="1.1">The "%service_id%" service is deprecated.</deprecated>
</service> </service>
</services> </services>
</container> </container>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="foo" class="Bar">
<deprecated>The "%service_id%" service is deprecated.</deprecated>
</service>
</services>
</container>

View File

@ -1,4 +1,7 @@
services: services:
alias_for_foobar: alias_for_foobar:
alias: foobar alias: foobar
deprecated: The "%alias_id%" service alias is deprecated. deprecated:
package: vendor/package
version: 1.1
message: The "%alias_id%" service alias is deprecated.

View File

@ -0,0 +1,4 @@
services:
alias_for_foobar:
alias: foobar
deprecated: The "%alias_id%" service alias is deprecated.

View File

@ -103,7 +103,10 @@ services:
public: true public: true
deprecated_service: deprecated_service:
class: stdClass class: stdClass
deprecated: The "%service_id%" service is deprecated. You should stop using it, as it will be removed in the future. deprecated:
message: The "%service_id%" service is deprecated. You should stop using it, as it will be removed in the future.
package: vendor/package
version: 1.1
public: true public: true
new_factory: new_factory:
class: FactoryClass class: FactoryClass
@ -124,7 +127,10 @@ services:
public: true public: true
factory_simple: factory_simple:
class: SimpleFactoryClass class: SimpleFactoryClass
deprecated: The "%service_id%" service is deprecated. You should stop using it, as it will be removed in the future. deprecated:
message: The "%service_id%" service is deprecated. You should stop using it, as it will be removed in the future.
package: vendor/package
version: 1.1
public: false public: false
arguments: ['foo'] arguments: ['foo']
factory_service_simple: factory_service_simple:

View File

@ -100,4 +100,15 @@ class PhpFileLoaderTest extends TestCase
$loader->load($fixtures.'/config/factory_short_notation.php'); $loader->load($fixtures.'/config/factory_short_notation.php');
$container->compile(); $container->compile();
} }
/**
* @group legacy
* @expectedDeprecation Since symfony/dependency-injection 5.1: The signature of method "Symfony\Component\DependencyInjection\Loader\Configurator\Traits\DeprecateTrait::deprecate()" requires 3 arguments: "string $package, string $version, string $message", not defining them is deprecated.
*/
public function testDeprecatedWithoutPackageAndVersion()
{
$fixtures = realpath(__DIR__.'/../Fixtures');
$loader = new PhpFileLoader($container = new ContainerBuilder(), new FileLocator());
$loader->load($fixtures.'/config/deprecated_without_package_version.php');
}
} }

View File

@ -394,11 +394,28 @@ class XmlFileLoaderTest extends TestCase
$this->assertTrue($container->getDefinition('foo')->isDeprecated()); $this->assertTrue($container->getDefinition('foo')->isDeprecated());
$message = 'The "foo" service is deprecated. You should stop using it, as it will be removed in the future.'; $message = 'The "foo" service is deprecated. You should stop using it, as it will be removed in the future.';
$this->assertSame($message, $container->getDefinition('foo')->getDeprecationMessage('foo')); $this->assertSame($message, $container->getDefinition('foo')->getDeprecation('foo')['message']);
$this->assertTrue($container->getDefinition('bar')->isDeprecated()); $this->assertTrue($container->getDefinition('bar')->isDeprecated());
$message = 'The "bar" service is deprecated.'; $message = 'The "bar" service is deprecated.';
$this->assertSame($message, $container->getDefinition('bar')->getDeprecationMessage('bar')); $this->assertSame($message, $container->getDefinition('bar')->getDeprecation('bar')['message']);
}
/**
* @group legacy
* @expectedDeprecation Since symfony/dependency-injection 5.1: Not setting the attribute "package" of the node "deprecated" is deprecated.
*/
public function testDeprecatedWithoutPackageAndVersion()
{
$container = new ContainerBuilder();
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
$loader->load('services_deprecated_without_package_and_version.xml');
$this->assertTrue($container->getDefinition('foo')->isDeprecated());
$deprecation = $container->getDefinition('foo')->getDeprecation('foo');
$this->assertSame('The "foo" service is deprecated.', $deprecation['message']);
$this->assertSame('', $deprecation['package']);
$this->assertSame('', $deprecation['version']);
} }
public function testDeprecatedAliases() public function testDeprecatedAliases()
@ -409,11 +426,28 @@ class XmlFileLoaderTest extends TestCase
$this->assertTrue($container->getAlias('alias_for_foo')->isDeprecated()); $this->assertTrue($container->getAlias('alias_for_foo')->isDeprecated());
$message = 'The "alias_for_foo" service alias is deprecated. You should stop using it, as it will be removed in the future.'; $message = 'The "alias_for_foo" service alias is deprecated. You should stop using it, as it will be removed in the future.';
$this->assertSame($message, $container->getAlias('alias_for_foo')->getDeprecationMessage('alias_for_foo')); $this->assertSame($message, $container->getAlias('alias_for_foo')->getDeprecation('alias_for_foo')['message']);
$this->assertTrue($container->getAlias('alias_for_foobar')->isDeprecated()); $this->assertTrue($container->getAlias('alias_for_foobar')->isDeprecated());
$message = 'The "alias_for_foobar" service alias is deprecated.'; $message = 'The "alias_for_foobar" service alias is deprecated.';
$this->assertSame($message, $container->getAlias('alias_for_foobar')->getDeprecationMessage('alias_for_foobar')); $this->assertSame($message, $container->getAlias('alias_for_foobar')->getDeprecation('alias_for_foobar')['message']);
}
/**
* @group legacy
* @expectedDeprecation Since symfony/dependency-injection 5.1: Not setting the attribute "package" of the node "deprecated" is deprecated.
*/
public function testDeprecatedAliaseWithoutPackageAndVersion()
{
$container = new ContainerBuilder();
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
$loader->load('deprecated_alias_definitions_without_package_and_version.xml');
$this->assertTrue($container->getAlias('alias_for_foo')->isDeprecated());
$deprecation = $container->getAlias('alias_for_foo')->getDeprecation('alias_for_foo');
$this->assertSame('The "alias_for_foo" service alias is deprecated. You should stop using it, as it will be removed in the future.', $deprecation['message']);
$this->assertSame('', $deprecation['package']);
$this->assertSame('', $deprecation['version']);
} }
public function testConvertDomElementToArray() public function testConvertDomElementToArray()

View File

@ -213,7 +213,29 @@ class YamlFileLoaderTest extends TestCase
$this->assertTrue($container->getAlias('alias_for_foobar')->isDeprecated()); $this->assertTrue($container->getAlias('alias_for_foobar')->isDeprecated());
$message = 'The "alias_for_foobar" service alias is deprecated.'; $message = 'The "alias_for_foobar" service alias is deprecated.';
$this->assertSame($message, $container->getAlias('alias_for_foobar')->getDeprecationMessage('alias_for_foobar')); $deprecation = $container->getAlias('alias_for_foobar')->getDeprecation('alias_for_foobar');
$this->assertSame($message, $deprecation['message']);
$this->assertSame('vendor/package', $deprecation['package']);
$this->assertSame('1.1', $deprecation['version']);
}
/**
* @group legacy
* @expectedDeprecation Since symfony/dependency-injection 5.1: Not setting the attribute "package" of the "deprecated" option is deprecated.
* @expectedDeprecation Since symfony/dependency-injection 5.1: Not setting the attribute "version" of the "deprecated" option is deprecated.
*/
public function testDeprecatedAliasesWithoutPackageAndVersion()
{
$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('deprecated_alias_definitions_without_package_and_version.yml');
$this->assertTrue($container->getAlias('alias_for_foobar')->isDeprecated());
$message = 'The "alias_for_foobar" service alias is deprecated.';
$deprecation = $container->getAlias('alias_for_foobar')->getDeprecation('alias_for_foobar');
$this->assertSame($message, $deprecation['message']);
$this->assertSame('', $deprecation['package']);
$this->assertSame('', $deprecation['version']);
} }
public function testFactorySyntaxError() public function testFactorySyntaxError()
@ -376,7 +398,7 @@ class YamlFileLoaderTest extends TestCase
$this->assertEquals([new IteratorArgument(['k1' => new Reference('foo.baz'), 'k2' => new Reference('service_container')]), new IteratorArgument([])], $lazyDefinition->getArguments(), '->load() parses lazy arguments'); $this->assertEquals([new IteratorArgument(['k1' => new Reference('foo.baz'), 'k2' => new Reference('service_container')]), new IteratorArgument([])], $lazyDefinition->getArguments(), '->load() parses lazy arguments');
$message = 'The "deprecated_service" service is deprecated. You should stop using it, as it will be removed in the future.'; $message = 'The "deprecated_service" service is deprecated. You should stop using it, as it will be removed in the future.';
$this->assertSame($message, $container->getDefinition('deprecated_service')->getDeprecationMessage('deprecated_service')); $this->assertSame($message, $container->getDefinition('deprecated_service')->getDeprecation('deprecated_service')['message']);
} }
public function testAutowire() public function testAutowire()