Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commite080ce2

Browse files
committed
[DependencyInjection] Add a mechanism to deprecate public services to private
1 parent6dc7d8b commite080ce2

File tree

7 files changed

+240
-0
lines changed

7 files changed

+240
-0
lines changed

‎src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class UnusedTagsPass implements CompilerPassInterface
4141
'controller.argument_value_resolver',
4242
'controller.service_arguments',
4343
'data_collector',
44+
'deprecated_public_service',
4445
'form.type',
4546
'form.type_extension',
4647
'form.type_guesser',

‎src/Symfony/Component/DependencyInjection/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ CHANGELOG
1919
* deprecated`Definition::getDeprecationMessage()`, use`Definition::getDeprecation()` instead
2020
* deprecated`Alias::getDeprecationMessage()`, use`Alias::getDeprecation()` instead
2121
* deprecated PHP-DSL's`inline()` function, use`service()` instead
22+
* added`AliasDeprecatedPublicServicesPass` to deprecate public services to private
2223

2324
5.0.0
2425
-----
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
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+
namespaceSymfony\Component\DependencyInjection\Compiler;
13+
14+
useSymfony\Component\DependencyInjection\ContainerBuilder;
15+
useSymfony\Component\DependencyInjection\Exception\InvalidArgumentException;
16+
useSymfony\Component\DependencyInjection\Exception\RuntimeException;
17+
useSymfony\Component\DependencyInjection\Reference;
18+
19+
finalclass AliasDeprecatedPublicServicesPassextends AbstractRecursivePass
20+
{
21+
private$tagName;
22+
23+
private$aliases = [];
24+
25+
publicfunction__construct(string$tagName ='deprecated_public_service')
26+
{
27+
$this->tagName =$tagName;
28+
}
29+
30+
/**
31+
* {@inheritdoc}
32+
*/
33+
protectedfunctionprocessValue($value,bool$isRoot =false)
34+
{
35+
if ($valueinstanceof Reference &&isset($this->aliases[$id = (string)$value])) {
36+
returnnewReference($this->aliases[$id]);
37+
}
38+
39+
returnparent::processValue($value,$isRoot);
40+
}
41+
42+
/**
43+
* {@inheritdoc}
44+
*/
45+
publicfunctionprocess(ContainerBuilder$container)
46+
{
47+
foreach ($container->findTaggedServiceIds($this->tagName)as$id =>$tags) {
48+
if (null ===$package =$tags[0]['package'] ??null) {
49+
thrownewInvalidArgumentException(sprintf('The "package" attribute is mandatory for the "%s" tag on the "%s" service.',$this->tagName,$id));
50+
}
51+
52+
if (null ===$version =$tags[0]['version'] ??null) {
53+
thrownewInvalidArgumentException(sprintf('The "version" attribute is mandatory for the "%s" tag on the "%s" service.',$this->tagName,$id));
54+
}
55+
56+
$definition =$container->getDefinition($id);
57+
if (!$definition->isPublic() ||$definition->isPrivate()) {
58+
thrownewRuntimeException(sprintf('The "%s" service is not public. Only public services can be deprecated with the "%s" tag.',$id,$this->tagName));
59+
}
60+
61+
$container
62+
->setAlias($id,$aliasId ='.'.$this->tagName.'.'.ContainerBuilder::hash($id))
63+
->setPublic(true)
64+
->setDeprecated($package,$version,'The public "%alias_id%" service will be private in the future. You should not access it directly from the container at runtime.');
65+
66+
$container->setDefinition($aliasId,$definition);
67+
68+
$this->aliases[$id] =$aliasId;
69+
}
70+
71+
parent::process($container);
72+
}
73+
}

‎src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ public function __construct()
9292
$this->afterRemovingPasses = [[
9393
newCheckExceptionOnInvalidReferenceBehaviorPass(),
9494
newResolveHotPathPass(),
95+
newAliasDeprecatedPublicServicesPass(),
9596
]];
9697
}
9798

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php
2+
3+
namespaceSymfony\Component\DependencyInjection\Tests\Compiler;
4+
5+
usePHPUnit\Framework\TestCase;
6+
useSymfony\Component\DependencyInjection\Compiler\AliasDeprecatedPublicServicesPass;
7+
useSymfony\Component\DependencyInjection\ContainerBuilder;
8+
useSymfony\Component\DependencyInjection\Exception\InvalidArgumentException;
9+
useSymfony\Component\DependencyInjection\Exception\RuntimeException;
10+
11+
finalclass AliasDeprecatedPublicServicesPassTestextends TestCase
12+
{
13+
publicfunctiontestProcess()
14+
{
15+
$container =newContainerBuilder();
16+
$container
17+
->register('foo')
18+
->setPublic(true)
19+
->addTag('deprecated_public_service', ['package' =>'foo/bar','version' =>'1.2']);
20+
21+
(newAliasDeprecatedPublicServicesPass())->process($container);
22+
23+
$this->assertTrue($container->hasAlias('foo'));
24+
25+
$alias =$container->getAlias('foo');
26+
27+
$this->assertSame('.deprecated_public_service.EVZD5I4', (string)$alias);
28+
$this->assertTrue($alias->isPublic());
29+
$this->assertFalse($alias->isPrivate());
30+
$this->assertSame([
31+
'package' =>'foo/bar',
32+
'version' =>'1.2',
33+
'message' =>'The public "foo" service will be private in the future. You should not access it directly from the container at runtime.',
34+
],$alias->getDeprecation('foo'));
35+
}
36+
37+
/**
38+
* @dataProvider processWithMissingAttributeProvider
39+
*/
40+
publicfunctiontestProcessWithMissingAttribute(string$attribute,array$attributes)
41+
{
42+
$this->expectException(InvalidArgumentException::class);
43+
$this->expectExceptionMessage(sprintf('The "%s" attribute is mandatory for the "deprecated_public_service" tag on the "foo" service.',$attribute));
44+
45+
$container =newContainerBuilder();
46+
$container
47+
->register('foo')
48+
->addTag('deprecated_public_service',$attributes);
49+
50+
(newAliasDeprecatedPublicServicesPass())->process($container);
51+
}
52+
53+
publicfunctionprocessWithMissingAttributeProvider()
54+
{
55+
return [
56+
['package', ['version' =>'1.2']],
57+
['version', ['package' =>'foo/bar']],
58+
];
59+
}
60+
61+
publicfunctiontestProcessWithNonPublicService()
62+
{
63+
$this->expectException(RuntimeException::class);
64+
$this->expectExceptionMessage('The "foo" service is not public. Only public services can be deprecated with the "deprecated_public_service" tag.');
65+
66+
$container =newContainerBuilder();
67+
$container
68+
->register('foo')
69+
->setPublic(false)
70+
->addTag('deprecated_public_service', ['package' =>'foo/bar','version' =>'1.2']);
71+
72+
(newAliasDeprecatedPublicServicesPass())->process($container);
73+
}
74+
}

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

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
usePHPUnit\Framework\TestCase;
1919
usePsr\Container\ContainerInterfaceasPsrContainerInterface;
20+
useSymfony\Bridge\PhpUnit\ExpectDeprecationTrait;
2021
useSymfony\Component\Config\Resource\ComposerResource;
2122
useSymfony\Component\Config\Resource\DirectoryResource;
2223
useSymfony\Component\Config\Resource\FileResource;
@@ -31,6 +32,7 @@
3132
useSymfony\Component\DependencyInjection\ContainerBuilder;
3233
useSymfony\Component\DependencyInjection\ContainerInterface;
3334
useSymfony\Component\DependencyInjection\Definition;
35+
useSymfony\Component\DependencyInjection\Dumper\PhpDumper;
3436
useSymfony\Component\DependencyInjection\Exception\RuntimeException;
3537
useSymfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
3638
useSymfony\Component\DependencyInjection\Loader\ClosureLoader;
@@ -50,6 +52,8 @@
5052

5153
class ContainerBuilderTestextends TestCase
5254
{
55+
use ExpectDeprecationTrait;
56+
5357
publicfunctiontestDefaultRegisteredDefinitions()
5458
{
5559
$builder =newContainerBuilder();
@@ -1633,6 +1637,44 @@ public function testAutoAliasing()
16331637

16341638
$this->assertInstanceOf(D::class,$container->get(X::class));
16351639
}
1640+
1641+
/**
1642+
* @group legacy
1643+
*/
1644+
publicfunctiontestDirectlyAccessingDeprecatedPublicService()
1645+
{
1646+
$this->expectDeprecation('Since foo/bar 3.8: The public "Symfony\Component\DependencyInjection\Tests\A" service will be private in the future. You should not access it directly from the container at runtime.');
1647+
1648+
$container =newContainerBuilder();
1649+
$container
1650+
->register(A::class)
1651+
->setPublic(true)
1652+
->addTag('deprecated_public_service', ['package' =>'foo/bar','version' =>'3.8']);
1653+
1654+
$container->compile();
1655+
1656+
$container->get(A::class);
1657+
}
1658+
1659+
publicfunctiontestReferencingDeprecatedPublicService()
1660+
{
1661+
$container =newContainerBuilder();
1662+
$container
1663+
->register(A::class)
1664+
->setPublic(true)
1665+
->addTag('deprecated_public_service', ['package' =>'foo/bar','version' =>'3.8']);
1666+
$container
1667+
->register(B::class)
1668+
->setPublic(true)
1669+
->addArgument(newReference(A::class));
1670+
1671+
$container->compile();
1672+
1673+
// No deprecation should be triggered.
1674+
$container->get(B::class);
1675+
1676+
$this->addToAssertionCount(1);
1677+
}
16361678
}
16371679

16381680
class FooClass

‎src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1386,6 +1386,54 @@ public function testDumpServiceWithAbstractArgument()
13861386
$dumper =newPhpDumper($container);
13871387
$dumper->dump();
13881388
}
1389+
1390+
/**
1391+
* @group legacy
1392+
*/
1393+
publicfunctiontestDirectlyAccessingDeprecatedPublicService()
1394+
{
1395+
$this->expectDeprecation('Since foo/bar 3.8: The public "bar" service will be private in the future. You should not access it directly from the container at runtime.');
1396+
1397+
$container =newContainerBuilder();
1398+
$container
1399+
->register('bar', \BarClass::class)
1400+
->setPublic(true)
1401+
->addTag('deprecated_public_service', ['package' =>'foo/bar','version' =>'3.8']);
1402+
1403+
$container->compile();
1404+
1405+
$dumper =newPhpDumper($container);
1406+
eval('?>'.$dumper->dump(['class' =>'Symfony_DI_PhpDumper_Test_Directly_Accessing_Deprecated_Public_Service']));
1407+
1408+
$container =new \Symfony_DI_PhpDumper_Test_Directly_Accessing_Deprecated_Public_Service();
1409+
1410+
$container->get('bar');
1411+
}
1412+
1413+
publicfunctiontestReferencingDeprecatedPublicService()
1414+
{
1415+
$container =newContainerBuilder();
1416+
$container
1417+
->register('bar', \BarClass::class)
1418+
->setPublic(true)
1419+
->addTag('deprecated_public_service', ['package' =>'foo/bar','version' =>'3.8']);
1420+
$container
1421+
->register('bar_user', \BarUserClass::class)
1422+
->setPublic(true)
1423+
->addArgument(newReference('bar'));
1424+
1425+
$container->compile();
1426+
1427+
$dumper =newPhpDumper($container);
1428+
eval('?>'.$dumper->dump(['class' =>'Symfony_DI_PhpDumper_Test_Referencing_Deprecated_Public_Service']));
1429+
1430+
$container =new \Symfony_DI_PhpDumper_Test_Referencing_Deprecated_Public_Service();
1431+
1432+
// No deprecation should be triggered.
1433+
$container->get('bar_user');
1434+
1435+
$this->addToAssertionCount(1);
1436+
}
13891437
}
13901438

13911439
class Rot13EnvVarProcessorimplements EnvVarProcessorInterface

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp