diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php
index 92bf97d9cffe..ab5f702d26d4 100644
--- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php
+++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php
@@ -127,6 +127,9 @@ private function resolveDefinition(ContainerBuilder $container, DefinitionDecora
if ($parentDef->getFactoryService(false)) {
$def->setFactoryService($parentDef->getFactoryService(false));
}
+ if ($parentDef->isDeprecated()) {
+ $def->setDeprecated(true, $parentDef->getDeprecationMessage('%service_id%'));
+ }
$def->setFactory($parentDef->getFactory());
$def->setConfigurator($parentDef->getConfigurator());
$def->setFile($parentDef->getFile());
@@ -162,6 +165,9 @@ private function resolveDefinition(ContainerBuilder $container, DefinitionDecora
if (isset($changes['lazy'])) {
$def->setLazy($definition->isLazy());
}
+ if (isset($changes['deprecated'])) {
+ $def->setDeprecated($definition->isDeprecated(), $definition->getDeprecationMessage('%service_id%'));
+ }
if (isset($changes['decorated_service'])) {
$decoratedService = $definition->getDecoratedService();
if (null === $decoratedService) {
diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php
index 5ac89cde5731..52405413af3d 100644
--- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php
+++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php
@@ -931,6 +931,10 @@ public function createService(Definition $definition, $id, $tryProxy = true)
throw new RuntimeException(sprintf('You have requested a synthetic service ("%s"). The DIC does not know how to construct this service.', $id));
}
+ if ($definition->isDeprecated()) {
+ @trigger_error($definition->getDeprecationMessage($id), E_USER_DEPRECATED);
+ }
+
if ($tryProxy && $definition->isLazy()) {
$container = $this;
diff --git a/src/Symfony/Component/DependencyInjection/Definition.php b/src/Symfony/Component/DependencyInjection/Definition.php
index 49d705cf7d67..8a39d4fb9388 100644
--- a/src/Symfony/Component/DependencyInjection/Definition.php
+++ b/src/Symfony/Component/DependencyInjection/Definition.php
@@ -30,6 +30,8 @@ class Definition
private $factoryMethod;
private $factoryService;
private $shared = true;
+ private $deprecated = false;
+ private $deprecationTemplate = 'The "%service_id%" service is deprecated. You should stop using it, as it will soon be removed.';
private $scope = ContainerInterface::SCOPE_CONTAINER;
private $properties = array();
private $calls = array();
@@ -829,6 +831,65 @@ public function isAbstract()
return $this->abstract;
}
+ /**
+ * Whether this definition is deprecated, that means it should not be called
+ * anymore.
+ *
+ * @param bool $status
+ * @param string $template Template message to use if the definition is deprecated
+ *
+ * @return Definition the current instance
+ *
+ * @throws InvalidArgumentException When the message template is invalid.
+ *
+ * @api
+ */
+ public function setDeprecated($status = true, $template = null)
+ {
+ if (null !== $template) {
+ if (preg_match('#[\r\n]|\*/#', $template)) {
+ throw new InvalidArgumentException('Invalid characters found in deprecation template.');
+ }
+
+ if (false === strpos($template, '%service_id%')) {
+ throw new InvalidArgumentException('The deprecation template must contain the "%service_id%" placeholder.');
+ }
+
+ $this->deprecationTemplate = $template;
+ }
+
+ $this->deprecated = (bool) $status;
+
+ return $this;
+ }
+
+ /**
+ * Whether this definition is deprecated, that means it should not be called
+ * anymore.
+ *
+ * @return bool
+ *
+ * @api
+ */
+ public function isDeprecated()
+ {
+ return $this->deprecated;
+ }
+
+ /**
+ * Message to use if this definition is deprecated.
+ *
+ * @param string $id Service id relying on this definition
+ *
+ * @return string
+ *
+ * @api
+ */
+ public function getDeprecationMessage($id)
+ {
+ return str_replace('%service_id%', $id, $this->deprecationTemplate);
+ }
+
/**
* Sets a configurator to call after the service is fully initialized.
*
diff --git a/src/Symfony/Component/DependencyInjection/DefinitionDecorator.php b/src/Symfony/Component/DependencyInjection/DefinitionDecorator.php
index 7764079d5109..87004c29b414 100644
--- a/src/Symfony/Component/DependencyInjection/DefinitionDecorator.php
+++ b/src/Symfony/Component/DependencyInjection/DefinitionDecorator.php
@@ -180,6 +180,16 @@ public function setDecoratedService($id, $renamedId = null, $priority = 0)
return parent::setDecoratedService($id, $renamedId, $priority);
}
+ /**
+ * {@inheritdoc}
+ */
+ public function setDeprecated($boolean = true, $template = null)
+ {
+ $this->changes['deprecated'] = true;
+
+ return parent::setDeprecated($boolean, $template);
+ }
+
/**
* Gets an argument to pass to the service constructor/factory method.
*
diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
index c1c6f80f70b7..1cdeb2d35b4c 100644
--- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
+++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
@@ -592,7 +592,15 @@ private function addService($id, $definition)
$return[] = sprintf("@throws InactiveScopeException when the '%s' service is requested while the '%s' scope is not active", $id, $scope);
}
- $return = implode("\n * ", $return);
+ if ($definition->isDeprecated()) {
+ if ($return && 0 === strpos($return[count($return) - 1], '@return')) {
+ $return[] = '';
+ }
+
+ $return[] = sprintf('@deprecated %s', $definition->getDeprecationMessage($id));
+ }
+
+ $return = str_replace("\n * \n", "\n *\n", implode("\n * ", $return));
$doc = '';
if ($definition->isShared() && ContainerInterface::SCOPE_PROTOTYPE !== $scope) {
@@ -652,6 +660,10 @@ private function addService($id, $definition)
if ($definition->isSynthetic()) {
$code .= sprintf(" throw new RuntimeException('You have requested a synthetic service (\"%s\"). The DIC does not know how to construct this service.');\n }\n", $id);
} else {
+ if ($definition->isDeprecated()) {
+ $code .= sprintf(" @trigger_error(%s, E_USER_DEPRECATED);\n\n", var_export($definition->getDeprecationMessage($id), true));
+ }
+
$code .=
$this->addServiceInclude($id, $definition).
$this->addServiceLocalTempVariables($id, $definition).
diff --git a/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php
index c405c4ce902c..d4fbd6a202ee 100644
--- a/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php
+++ b/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php
@@ -201,6 +201,13 @@ private function addService($definition, $id, \DOMElement $parent)
$service->appendChild($factory);
}
+ if ($definition->isDeprecated()) {
+ $deprecated = $this->document->createElement('deprecated');
+ $deprecated->appendChild($this->document->createTextNode($definition->getDeprecationMessage('%service_id%')));
+
+ $service->appendChild($deprecated);
+ }
+
if ($callable = $definition->getConfigurator()) {
$configurator = $this->document->createElement('configurator');
diff --git a/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php
index 3fac53e01c33..94929f84a19e 100644
--- a/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php
+++ b/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php
@@ -104,6 +104,10 @@ private function addService($id, $definition)
$code .= sprintf(" synchronized: true\n");
}
+ if ($definition->isDeprecated()) {
+ $code .= sprintf(" deprecated: %s\n", $definition->getDeprecationMessage('%service_id%'));
+ }
+
if ($definition->getFactoryClass(false)) {
$code .= sprintf(" factory_class: %s\n", $definition->getFactoryClass(false));
}
diff --git a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php
index de2ea9852a5f..8a0e4ac24a65 100644
--- a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php
+++ b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php
@@ -181,6 +181,10 @@ private function parseDefinition(\DOMElement $service, $file)
$definition->setFile($files[0]->nodeValue);
}
+ if ($deprecated = $this->getChildren($service, 'deprecated')) {
+ $definition->setDeprecated(true, $deprecated[0]->nodeValue);
+ }
+
$definition->setArguments($this->getArgumentsAsPhp($service, 'argument'));
$definition->setProperties($this->getArgumentsAsPhp($service, 'property'));
diff --git a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php
index 74a7ed4f1ad3..19191a760c6c 100644
--- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php
+++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php
@@ -196,6 +196,10 @@ private function parseDefinition($id, $service, $file)
$definition->setAbstract($service['abstract']);
}
+ if (array_key_exists('deprecated', $service)) {
+ $definition->setDeprecated(true, $service['deprecated']);
+ }
+
if (isset($service['factory'])) {
if (is_string($service['factory'])) {
if (strpos($service['factory'], ':') !== false && strpos($service['factory'], '::') === false) {
diff --git a/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd b/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd
index 15bdd791dcf2..cbaa3606f7a0 100644
--- a/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd
+++ b/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd
@@ -81,6 +81,7 @@
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: