Added support for deprecating an alias
This commit is contained in:
parent
a9f8ca57af
commit
0eb071b9f8
@ -11,17 +11,24 @@
|
||||
|
||||
namespace Symfony\Component\DependencyInjection;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
||||
|
||||
class Alias
|
||||
{
|
||||
private $id;
|
||||
private $public;
|
||||
private $private;
|
||||
private $deprecated;
|
||||
private $deprecationTemplate;
|
||||
|
||||
private static $defaultDeprecationTemplate = 'The "%service_id%" service alias is deprecated. You should stop using it, as it will soon be removed.';
|
||||
|
||||
public function __construct(string $id, bool $public = true)
|
||||
{
|
||||
$this->id = $id;
|
||||
$this->public = $public;
|
||||
$this->private = 2 > \func_num_args();
|
||||
$this->deprecated = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -78,6 +85,58 @@ class Alias
|
||||
return $this->private;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this alias is deprecated, that means it should not be called
|
||||
* anymore.
|
||||
*
|
||||
* @param bool $status Defaults to true
|
||||
* @param string $template Optional template message to use if the alias is deprecated
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @throws InvalidArgumentException when the message template is invalid
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this alias is deprecated.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isDeprecated()
|
||||
{
|
||||
return $this->deprecated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Message to use if this alias is deprecated.
|
||||
*
|
||||
* @param string $id Service id relying on this alias
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDeprecationMessage($id)
|
||||
{
|
||||
return str_replace('%service_id%', $id, $this->deprecationTemplate ?: self::$defaultDeprecationTemplate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Id of this alias.
|
||||
*
|
||||
|
@ -579,7 +579,12 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
|
||||
}
|
||||
|
||||
if (!isset($this->definitions[$id]) && isset($this->aliasDefinitions[$id])) {
|
||||
return $this->doGet((string) $this->aliasDefinitions[$id], $invalidBehavior, $inlineServices, $isConstructorArgument);
|
||||
$aliasDefinition = $this->aliasDefinitions[$id];
|
||||
if ($aliasDefinition->isDeprecated()) {
|
||||
@trigger_error($aliasDefinition->getDeprecationMessage($id), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
return $this->doGet((string) $aliasDefinition, $invalidBehavior, $inlineServices, $isConstructorArgument);
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -220,6 +220,10 @@ class XmlFileLoader extends FileLoader
|
||||
$alias->setPublic($defaults['public']);
|
||||
}
|
||||
|
||||
if ($deprecated = $this->getChildren($service, 'deprecated')) {
|
||||
$alias->setDeprecated(true, $deprecated[0]->nodeValue ?: null);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -667,8 +671,12 @@ EOF
|
||||
}
|
||||
}
|
||||
|
||||
$allowedTags = array('deprecated');
|
||||
foreach ($alias->childNodes as $child) {
|
||||
if ($child instanceof \DOMElement && self::NS === $child->namespaceURI) {
|
||||
if (!$child instanceof \DOMElement && self::NS !== $child->namespaceURI) {
|
||||
continue;
|
||||
}
|
||||
if (!in_array($child->localName, $allowedTags, true)) {
|
||||
throw new InvalidArgumentException(sprintf('Invalid child element "%s" defined for alias "%s" in "%s".', $child->localName, $alias->getAttribute('id'), $file));
|
||||
}
|
||||
}
|
||||
|
@ -349,8 +349,13 @@ class YamlFileLoader extends FileLoader
|
||||
}
|
||||
|
||||
foreach ($service as $key => $value) {
|
||||
if (!\in_array($key, ['alias', 'public'])) {
|
||||
if (!\in_array($key, ['alias', 'public', 'deprecated'])) {
|
||||
throw new InvalidArgumentException(sprintf('The configuration key "%s" is unsupported for the service "%s" which is defined as an alias in "%s". Allowed configuration keys for service aliases are "alias" and "public".', $key, $id, $file));
|
||||
continue;
|
||||
}
|
||||
|
||||
if ('deprecated' === $key) {
|
||||
$alias->setDeprecated(true, $value);
|
||||
}
|
||||
}
|
||||
|
||||
|
110
src/Symfony/Component/DependencyInjection/Tests/AliasTest.php
Normal file
110
src/Symfony/Component/DependencyInjection/Tests/AliasTest.php
Normal file
@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\DependencyInjection\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\DependencyInjection\Alias;
|
||||
|
||||
class AliasTest extends TestCase
|
||||
{
|
||||
public function testConstructor()
|
||||
{
|
||||
$alias = new Alias('foo');
|
||||
|
||||
$this->assertEquals('foo', (string) $alias);
|
||||
$this->assertTrue($alias->isPublic());
|
||||
}
|
||||
|
||||
public function testCanConstructANonPublicAlias()
|
||||
{
|
||||
$alias = new Alias('foo', false);
|
||||
|
||||
$this->assertEquals('foo', (string) $alias);
|
||||
$this->assertFalse($alias->isPublic());
|
||||
}
|
||||
|
||||
public function testCanConstructAPrivateAlias()
|
||||
{
|
||||
$alias = new Alias('foo', false, false);
|
||||
|
||||
$this->assertEquals('foo', (string) $alias);
|
||||
$this->assertFalse($alias->isPublic());
|
||||
$this->assertFalse($alias->isPrivate());
|
||||
}
|
||||
|
||||
public function testCanSetPublic()
|
||||
{
|
||||
$alias = new Alias('foo', false);
|
||||
$alias->setPublic(true);
|
||||
|
||||
$this->assertTrue($alias->isPublic());
|
||||
}
|
||||
|
||||
public function testCanDeprecateAnAlias()
|
||||
{
|
||||
$alias = new Alias('foo', false);
|
||||
$alias->setDeprecated(true, 'The %service_id% service is deprecated.');
|
||||
|
||||
$this->assertTrue($alias->isDeprecated());
|
||||
}
|
||||
|
||||
public function testItHasADefaultDeprecationMessage()
|
||||
{
|
||||
$alias = new Alias('foo', false);
|
||||
$alias->setDeprecated();
|
||||
|
||||
$expectedMessage = 'The "foo" service alias is deprecated. You should stop using it, as it will soon be removed.';
|
||||
$this->assertEquals($expectedMessage, $alias->getDeprecationMessage('foo'));
|
||||
}
|
||||
|
||||
public function testReturnsCorrectDeprecationMessage()
|
||||
{
|
||||
$alias = new Alias('foo', false);
|
||||
$alias->setDeprecated(true, 'The "%service_id%" is deprecated.');
|
||||
|
||||
$expectedMessage = 'The "foo" is deprecated.';
|
||||
$this->assertEquals($expectedMessage, $alias->getDeprecationMessage('foo'));
|
||||
}
|
||||
|
||||
public function testCanOverrideDeprecation()
|
||||
{
|
||||
$alias = new Alias('foo', false);
|
||||
$alias->setDeprecated();
|
||||
|
||||
$initial = $alias->isDeprecated();
|
||||
$alias->setDeprecated(false);
|
||||
$final = $alias->isDeprecated();
|
||||
|
||||
$this->assertTrue($initial);
|
||||
$this->assertFalse($final);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider invalidDeprecationMessageProvider
|
||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
|
||||
*/
|
||||
public function testCannotDeprecateWithAnInvalidTemplate($message)
|
||||
{
|
||||
$def = new Alias('foo');
|
||||
$def->setDeprecated(true, $message);
|
||||
}
|
||||
|
||||
public function invalidDeprecationMessageProvider()
|
||||
{
|
||||
return array(
|
||||
"With \rs" => array("invalid \r message %service_id%"),
|
||||
"With \ns" => array("invalid \n message %service_id%"),
|
||||
'With */s' => array('invalid */ message %service_id%'),
|
||||
'message not containing required %service_id% variable' => array('this is deprecated'),
|
||||
);
|
||||
}
|
||||
}
|
@ -259,6 +259,22 @@ class ContainerBuilderTest extends TestCase
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
* @expectedDeprecation The "foobar" service alias is deprecated. You should stop using it, as it will soon be removed.
|
||||
*/
|
||||
public function testDeprecatedAlias()
|
||||
{
|
||||
$builder = new ContainerBuilder();
|
||||
$builder->register('foo', 'stdClass');
|
||||
|
||||
$alias = new Alias('foo');
|
||||
$alias->setDeprecated();
|
||||
$builder->setAlias('foobar', $alias);
|
||||
|
||||
$builder->get('foobar');
|
||||
}
|
||||
|
||||
public function testGetAliases()
|
||||
{
|
||||
$builder = new ContainerBuilder();
|
||||
|
@ -0,0 +1,13 @@
|
||||
<?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 http://symfony.com/schema/dic/services/services-1.0.xsd">
|
||||
<services>
|
||||
<service id="foo" class="Foo">
|
||||
</service>
|
||||
<service id="alias_for_foo" alias="foo">
|
||||
<deprecated />
|
||||
</service>
|
||||
<service id="alias_for_foobar" alias="foobar">
|
||||
<deprecated>The "%service_id%" service alias is deprecated.</deprecated>
|
||||
</service>
|
||||
</services>
|
||||
</container>
|
@ -0,0 +1,4 @@
|
||||
services:
|
||||
alias_for_foobar:
|
||||
alias: foobar
|
||||
deprecated: The "%service_id%" service alias is deprecated.
|
@ -351,6 +351,21 @@ class XmlFileLoaderTest extends TestCase
|
||||
$this->assertSame($message, $container->getDefinition('bar')->getDeprecationMessage('bar'));
|
||||
}
|
||||
|
||||
public function testDeprecatedAliases()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
|
||||
$loader->load('deprecated_alias_definitions.xml');
|
||||
|
||||
$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 soon be removed.';
|
||||
$this->assertSame($message, $container->getAlias('alias_for_foo')->getDeprecationMessage('alias_for_foo'));
|
||||
|
||||
$this->assertTrue($container->getAlias('alias_for_foobar')->isDeprecated());
|
||||
$message = 'The "alias_for_foobar" service alias is deprecated.';
|
||||
$this->assertSame($message, $container->getAlias('alias_for_foobar')->getDeprecationMessage('alias_for_foobar'));
|
||||
}
|
||||
|
||||
public function testConvertDomElementToArray()
|
||||
{
|
||||
$doc = new \DOMDocument('1.0');
|
||||
|
@ -175,6 +175,17 @@ class YamlFileLoaderTest extends TestCase
|
||||
$this->assertEquals(['decorated', 'decorated.pif-pouf', 5], $services['decorator_service_with_name_and_priority']->getDecoratedService());
|
||||
}
|
||||
|
||||
public function testDeprecatedAliases()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
|
||||
$loader->load('deprecated_alias_definitions.yml');
|
||||
|
||||
$this->assertTrue($container->getAlias('alias_for_foobar')->isDeprecated());
|
||||
$message = 'The "alias_for_foobar" service alias is deprecated.';
|
||||
$this->assertSame($message, $container->getAlias('alias_for_foobar')->getDeprecationMessage('alias_for_foobar'));
|
||||
}
|
||||
|
||||
public function testLoadFactoryShortSyntax()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
|
Reference in New Issue
Block a user