Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 31, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions UPGRADE-5.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ Console

* `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
------

Expand Down
7 changes: 7 additions & 0 deletions UPGRADE-6.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ Console

* `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
------

Expand Down
62 changes: 48 additions & 14 deletions src/Symfony/Component/DependencyInjection/Alias.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ class Alias
private $id;
private $public;
private $private;
private $deprecated;
private $deprecationTemplate;
private $deprecation = [];

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

Expand All @@ -28,7 +27,6 @@ public function __construct(string $id, bool $public = true)
$this->id = $id;
$this->public = $public;
$this->private = 2 > \func_num_args();
$this->deprecated = false;
}

/**
Expand Down Expand Up @@ -85,40 +83,76 @@ public function isPrivate()
* Whether this alias is deprecated, that means it should not be referenced
* anymore.
*
* @param bool $status Whether this alias is deprecated, defaults to true
* @param string $template Optional template message to use if the alias 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
*
* @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) {
if (preg_match('#[\r\n]|\*/#', $template)) {
$args = \func_get_args();

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.');
}

if (false === strpos($template, '%alias_id%')) {
if (false === strpos($message, '%alias_id%')) {
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;
}

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
{
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']),
];
}

/**
Expand Down
3 changes: 3 additions & 0 deletions src/Symfony/Component/DependencyInjection/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ CHANGELOG
* 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 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
-----
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ private function doResolveDefinition(ChildDefinition $definition): Definition
$def->setMethodCalls($parentDef->getMethodCalls());
$def->setProperties($parentDef->getProperties());
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->setConfigurator($parentDef->getConfigurator());
Expand Down Expand Up @@ -137,7 +138,12 @@ private function doResolveDefinition(ChildDefinition $definition): Definition
$def->setLazy($definition->isLazy());
}
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'])) {
$def->setAutowired($definition->isAutowired());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ private function getDefinitionId(string $id, ContainerBuilder $container): strin
$alias = $container->getAlias($id);

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 = [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -568,7 +568,8 @@ private function doGet(string $id, int $invalidBehavior = ContainerInterface::EX
$alias = $this->aliasDefinitions[$id];

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);
Expand Down Expand Up @@ -1037,7 +1038,8 @@ private function createService(Definition $definition, array &$inlineServices, b
}

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) {
Expand Down
60 changes: 47 additions & 13 deletions src/Symfony/Component/DependencyInjection/Definition.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ class Definition
private $file;
private $factory;
private $shared = true;
private $deprecated = false;
private $deprecationTemplate;
private $deprecation = [];
private $properties = [];
private $calls = [];
private $instanceof = [];
Expand Down Expand Up @@ -705,29 +704,48 @@ public function isAbstract()
* 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
*
* @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) {
if (preg_match('#[\r\n]|\*/#', $template)) {
$args = \func_get_args();

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.');
}

if (false === strpos($template, '%service_id%')) {
if (false === strpos($message, '%service_id%')) {
throw new InvalidArgumentException('The deprecation template must contain the "%service_id%" placeholder.');
}

$this->deprecationTemplate = $template;
}

$this->changes['deprecated'] = true;

$this->deprecated = $status;
$this->deprecation = $status ? ['package' => $package, 'version' => $version, 'message' => $message ?: self::$defaultDeprecationTemplate] : [];

return $this;
}
Expand All @@ -740,19 +758,35 @@ public function setDeprecated(bool $status = true, string $template = null)
*/
public function isDeprecated()
{
return $this->deprecated;
return (bool) $this->deprecation;
}

/**
* 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
*
* @return string
*/
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']),
];
}

/**
Expand Down
13 changes: 9 additions & 4 deletions src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
Original file line number Diff line number Diff line change
Expand Up @@ -786,7 +786,8 @@ private function addService(string $id, Definition $definition): array
$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));
Expand Down Expand Up @@ -835,7 +836,8 @@ protected function {$methodName}($lazyInitialization)
$this->inlinedDefinitions = $this->getDefinitionsFromArguments([$definition], null, $this->serviceCalls);

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 {
foreach ($this->inlinedDefinitions as $def) {
foreach ($this->getClasses($def) as $class) {
Expand Down Expand Up @@ -1341,7 +1343,10 @@ private function addDeprecatedAliases(): string
$id = (string) $definition;
$methodNameAlias = $this->generateMethodName($alias);
$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

/*{$this->docStar}
Expand All @@ -1351,7 +1356,7 @@ private function addDeprecatedAliases(): string
*/
protected function {$methodNameAlias}()
{
trigger_deprecation('', '', $messageExported);
trigger_deprecation($packageExported, $versionExported, $messageExported);

return \$this->get($idExported);
}
Expand Down
10 changes: 8 additions & 2 deletions src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,11 @@ private function addService(Definition $definition, ?string $id, \DOMElement $pa
}

if ($definition->isDeprecated()) {
$deprecation = $definition->getDeprecation('%service_id%');
$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);
}
Expand Down Expand Up @@ -225,8 +228,11 @@ private function addServiceAlias(string $alias, Alias $id, \DOMElement $parent)
}

if ($id->isDeprecated()) {
$deprecation = $id->getDeprecation('%alias_id%');
$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);
}
Expand Down
Loading