Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0eb071b

Browse files
j92Renan
authored and
Renan
committed
Added support for deprecating an alias
1 parent a9f8ca5 commit 0eb071b

10 files changed

+249
-3
lines changed

src/Symfony/Component/DependencyInjection/Alias.php

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,24 @@
1111

1212
namespace Symfony\Component\DependencyInjection;
1313

14+
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
15+
1416
class Alias
1517
{
1618
private $id;
1719
private $public;
1820
private $private;
21+
private $deprecated;
22+
private $deprecationTemplate;
23+
24+
private static $defaultDeprecationTemplate = 'The "%service_id%" service alias is deprecated. You should stop using it, as it will soon be removed.';
1925

2026
public function __construct(string $id, bool $public = true)
2127
{
2228
$this->id = $id;
2329
$this->public = $public;
2430
$this->private = 2 > \func_num_args();
31+
$this->deprecated = false;
2532
}
2633

2734
/**
@@ -78,6 +85,58 @@ public function isPrivate()
7885
return $this->private;
7986
}
8087

88+
/**
89+
* Whether this alias is deprecated, that means it should not be called
90+
* anymore.
91+
*
92+
* @param bool $status Defaults to true
93+
* @param string $template Optional template message to use if the alias is deprecated
94+
*
95+
* @return $this
96+
*
97+
* @throws InvalidArgumentException when the message template is invalid
98+
*/
99+
public function setDeprecated($status = true, $template = null)
100+
{
101+
if (null !== $template) {
102+
if (preg_match('#[\r\n]|\*/#', $template)) {
103+
throw new InvalidArgumentException('Invalid characters found in deprecation template.');
104+
}
105+
106+
if (false === strpos($template, '%service_id%')) {
107+
throw new InvalidArgumentException('The deprecation template must contain the "%service_id%" placeholder.');
108+
}
109+
110+
$this->deprecationTemplate = $template;
111+
}
112+
113+
$this->deprecated = (bool) $status;
114+
115+
return $this;
116+
}
117+
118+
/**
119+
* Returns whether this alias is deprecated.
120+
*
121+
* @return bool
122+
*/
123+
public function isDeprecated()
124+
{
125+
return $this->deprecated;
126+
}
127+
128+
/**
129+
* Message to use if this alias is deprecated.
130+
*
131+
* @param string $id Service id relying on this alias
132+
*
133+
* @return string
134+
*/
135+
public function getDeprecationMessage($id)
136+
{
137+
return str_replace('%service_id%', $id, $this->deprecationTemplate ?: self::$defaultDeprecationTemplate);
138+
}
139+
81140
/**
82141
* Returns the Id of this alias.
83142
*

src/Symfony/Component/DependencyInjection/ContainerBuilder.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -579,7 +579,12 @@ private function doGet($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_
579579
}
580580

581581
if (!isset($this->definitions[$id]) && isset($this->aliasDefinitions[$id])) {
582-
return $this->doGet((string) $this->aliasDefinitions[$id], $invalidBehavior, $inlineServices, $isConstructorArgument);
582+
$aliasDefinition = $this->aliasDefinitions[$id];
583+
if ($aliasDefinition->isDeprecated()) {
584+
@trigger_error($aliasDefinition->getDeprecationMessage($id), E_USER_DEPRECATED);
585+
}
586+
587+
return $this->doGet((string) $aliasDefinition, $invalidBehavior, $inlineServices, $isConstructorArgument);
583588
}
584589

585590
try {

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,10 @@ private function parseDefinition(\DOMElement $service, $file, array $defaults)
220220
$alias->setPublic($defaults['public']);
221221
}
222222

223+
if ($deprecated = $this->getChildren($service, 'deprecated')) {
224+
$alias->setDeprecated(true, $deprecated[0]->nodeValue ?: null);
225+
}
226+
223227
return;
224228
}
225229

@@ -667,8 +671,12 @@ private function validateAlias(\DOMElement $alias, $file)
667671
}
668672
}
669673

674+
$allowedTags = array('deprecated');
670675
foreach ($alias->childNodes as $child) {
671-
if ($child instanceof \DOMElement && self::NS === $child->namespaceURI) {
676+
if (!$child instanceof \DOMElement && self::NS !== $child->namespaceURI) {
677+
continue;
678+
}
679+
if (!in_array($child->localName, $allowedTags, true)) {
672680
throw new InvalidArgumentException(sprintf('Invalid child element "%s" defined for alias "%s" in "%s".', $child->localName, $alias->getAttribute('id'), $file));
673681
}
674682
}

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,8 +349,13 @@ private function parseDefinition($id, $service, $file, array $defaults)
349349
}
350350

351351
foreach ($service as $key => $value) {
352-
if (!\in_array($key, ['alias', 'public'])) {
352+
if (!\in_array($key, ['alias', 'public', 'deprecated'])) {
353353
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));
354+
continue;
355+
}
356+
357+
if ('deprecated' === $key) {
358+
$alias->setDeprecated(true, $value);
354359
}
355360
}
356361

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\DependencyInjection\Tests;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\DependencyInjection\Alias;
16+
17+
class AliasTest extends TestCase
18+
{
19+
public function testConstructor()
20+
{
21+
$alias = new Alias('foo');
22+
23+
$this->assertEquals('foo', (string) $alias);
24+
$this->assertTrue($alias->isPublic());
25+
}
26+
27+
public function testCanConstructANonPublicAlias()
28+
{
29+
$alias = new Alias('foo', false);
30+
31+
$this->assertEquals('foo', (string) $alias);
32+
$this->assertFalse($alias->isPublic());
33+
}
34+
35+
public function testCanConstructAPrivateAlias()
36+
{
37+
$alias = new Alias('foo', false, false);
38+
39+
$this->assertEquals('foo', (string) $alias);
40+
$this->assertFalse($alias->isPublic());
41+
$this->assertFalse($alias->isPrivate());
42+
}
43+
44+
public function testCanSetPublic()
45+
{
46+
$alias = new Alias('foo', false);
47+
$alias->setPublic(true);
48+
49+
$this->assertTrue($alias->isPublic());
50+
}
51+
52+
public function testCanDeprecateAnAlias()
53+
{
54+
$alias = new Alias('foo', false);
55+
$alias->setDeprecated(true, 'The %service_id% service is deprecated.');
56+
57+
$this->assertTrue($alias->isDeprecated());
58+
}
59+
60+
public function testItHasADefaultDeprecationMessage()
61+
{
62+
$alias = new Alias('foo', false);
63+
$alias->setDeprecated();
64+
65+
$expectedMessage = 'The "foo" service alias is deprecated. You should stop using it, as it will soon be removed.';
66+
$this->assertEquals($expectedMessage, $alias->getDeprecationMessage('foo'));
67+
}
68+
69+
public function testReturnsCorrectDeprecationMessage()
70+
{
71+
$alias = new Alias('foo', false);
72+
$alias->setDeprecated(true, 'The "%service_id%" is deprecated.');
73+
74+
$expectedMessage = 'The "foo" is deprecated.';
75+
$this->assertEquals($expectedMessage, $alias->getDeprecationMessage('foo'));
76+
}
77+
78+
public function testCanOverrideDeprecation()
79+
{
80+
$alias = new Alias('foo', false);
81+
$alias->setDeprecated();
82+
83+
$initial = $alias->isDeprecated();
84+
$alias->setDeprecated(false);
85+
$final = $alias->isDeprecated();
86+
87+
$this->assertTrue($initial);
88+
$this->assertFalse($final);
89+
}
90+
91+
/**
92+
* @dataProvider invalidDeprecationMessageProvider
93+
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
94+
*/
95+
public function testCannotDeprecateWithAnInvalidTemplate($message)
96+
{
97+
$def = new Alias('foo');
98+
$def->setDeprecated(true, $message);
99+
}
100+
101+
public function invalidDeprecationMessageProvider()
102+
{
103+
return array(
104+
"With \rs" => array("invalid \r message %service_id%"),
105+
"With \ns" => array("invalid \n message %service_id%"),
106+
'With */s' => array('invalid */ message %service_id%'),
107+
'message not containing required %service_id% variable' => array('this is deprecated'),
108+
);
109+
}
110+
}

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,22 @@ public function testAliases()
259259
}
260260
}
261261

262+
/**
263+
* @group legacy
264+
* @expectedDeprecation The "foobar" service alias is deprecated. You should stop using it, as it will soon be removed.
265+
*/
266+
public function testDeprecatedAlias()
267+
{
268+
$builder = new ContainerBuilder();
269+
$builder->register('foo', 'stdClass');
270+
271+
$alias = new Alias('foo');
272+
$alias->setDeprecated();
273+
$builder->setAlias('foobar', $alias);
274+
275+
$builder->get('foobar');
276+
}
277+
262278
public function testGetAliases()
263279
{
264280
$builder = new ContainerBuilder();
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<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">
3+
<services>
4+
<service id="foo" class="Foo">
5+
</service>
6+
<service id="alias_for_foo" alias="foo">
7+
<deprecated />
8+
</service>
9+
<service id="alias_for_foobar" alias="foobar">
10+
<deprecated>The "%service_id%" service alias is deprecated.</deprecated>
11+
</service>
12+
</services>
13+
</container>
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
services:
2+
alias_for_foobar:
3+
alias: foobar
4+
deprecated: The "%service_id%" service alias is deprecated.

src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,21 @@ public function testDeprecated()
351351
$this->assertSame($message, $container->getDefinition('bar')->getDeprecationMessage('bar'));
352352
}
353353

354+
public function testDeprecatedAliases()
355+
{
356+
$container = new ContainerBuilder();
357+
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
358+
$loader->load('deprecated_alias_definitions.xml');
359+
360+
$this->assertTrue($container->getAlias('alias_for_foo')->isDeprecated());
361+
$message = 'The "alias_for_foo" service alias is deprecated. You should stop using it, as it will soon be removed.';
362+
$this->assertSame($message, $container->getAlias('alias_for_foo')->getDeprecationMessage('alias_for_foo'));
363+
364+
$this->assertTrue($container->getAlias('alias_for_foobar')->isDeprecated());
365+
$message = 'The "alias_for_foobar" service alias is deprecated.';
366+
$this->assertSame($message, $container->getAlias('alias_for_foobar')->getDeprecationMessage('alias_for_foobar'));
367+
}
368+
354369
public function testConvertDomElementToArray()
355370
{
356371
$doc = new \DOMDocument('1.0');

src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,17 @@ public function testLoadServices()
175175
$this->assertEquals(['decorated', 'decorated.pif-pouf', 5], $services['decorator_service_with_name_and_priority']->getDecoratedService());
176176
}
177177

178+
public function testDeprecatedAliases()
179+
{
180+
$container = new ContainerBuilder();
181+
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
182+
$loader->load('deprecated_alias_definitions.yml');
183+
184+
$this->assertTrue($container->getAlias('alias_for_foobar')->isDeprecated());
185+
$message = 'The "alias_for_foobar" service alias is deprecated.';
186+
$this->assertSame($message, $container->getAlias('alias_for_foobar')->getDeprecationMessage('alias_for_foobar'));
187+
}
188+
178189
public function testLoadFactoryShortSyntax()
179190
{
180191
$container = new ContainerBuilder();

0 commit comments

Comments
 (0)