10000 [DependencyInjection] Add support of PHP 8.1 enumerations · symfony/symfony@40ababd · GitHub
[go: up one dir, main page]

Skip to content

Commit 40ababd

Browse files
[DependencyInjection] Add support of PHP 8.1 enumerations
1 parent 98777c2 commit 40ababd

16 files changed

+195
-0
lines changed

src/Symfony/Component/DependencyInjection/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ CHANGELOG
1818
* Add support for `ConfigBuilder` in the `PhpFileLoader`
1919
* Add `ContainerConfigurator::env()` to get the current environment
2020
* Add `#[Target]` to tell how a dependency is used and hint named autowiring aliases
21+
* Add support of PHP 8.1 enumerations
2122

2223
5.2.0
2324
-----

src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1871,6 +1871,8 @@ private function dumpValue($value, bool $interpolate = true): string
18711871

18721872
return $code;
18731873
}
1874+
} elseif ($value instanceof \UnitEnum) {
1875+
return sprintf('\%s::%s', \get_class($value), $value->name);
18741876
} elseif ($value instanceof AbstractArgument) {
18751877
throw new RuntimeException($value->getTextWithContext());
18761878
} elseif (\is_object($value) || \is_resource($value)) {

src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,9 @@ private function convertParameters(array $parameters, string $type, \DOMElement
328328
$element->setAttribute('type', 'abstract');
329329
$text = $this->document->createTextNode(self::phpToXml($value->getText()));
330330
$element->appendChild($text);
331+
} elseif ($value instanceof \UnitEnum) {
332+
$element->setAttribute('type', 'constant');
333+
$element->appendChild($this->document->createTextNode(self::phpToXml($value)));
331334
} else {
332335
if (\in_array($value, ['null', 'true', 'false'], true)) {
333336
$element->setAttribute('type', 'string');
@@ -381,6 +384,8 @@ public static function phpToXml($value): string
381384
return 'false';
382385
case $value instanceof Parameter:
383386
return '%'.$value.'%';
387+
case $value instanceof \UnitEnum:
388+
return sprintf('%s::%s', \get_class($value), $value->name);
384389
case \is_object($value) || \is_resource($value):
385390
throw new RuntimeException('Unable to dump a service container if a parameter is an object or a resource.');
386391
default:

src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,8 @@ private function dumpValue($value)
308308
return new TaggedValue('service', (new Parser())->parse("_:\n".$this->addService('_', $value), Yaml::PARSE_CUSTOM_TAGS)['_']['_']);
309309
} elseif ($value instanceof AbstractArgument) {
310310
return new TaggedValue('abstract', $value->getText());
311+
} elseif ($value instanceof \UnitEnum) {
312+
return new TaggedValue('php/const', sprintf('%s::%s', \get_class($value), $value->name));
311313
} elseif (\is_object($value) || \is_resource($value)) {
312314
throw new RuntimeException('Unable to dump a service container if a parameter is an object or a resource.');
313315
}

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@
4242
use Symfony\Component\DependencyInjection\Tests\Compiler\Foo;
4343
use Symfony\Component\DependencyInjection\Tests\Compiler\Wither;
4444
use Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition;
45+
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithEnumAttribute;
46+
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooUnitEnum;
4547
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooWithAbstractArgument;
4648
use Symfony\Component\DependencyInjection\Tests\Fixtures\ScalarFactory;
4749
use Symfony\Component\DependencyInjection\Tests\Fixtures\StubbedTranslator;
@@ -1224,6 +1226,29 @@ public function testDumpHandlesObjectClassNames()
12241226
$this->assertInstanceOf(\stdClass::class, $container->get('bar'));
12251227
}
12261228

1229+
/**
1230+
* @requires PHP 8.1
1231+
*/
1232+
public function testDumpHandlesEnumeration()
1233+
{
1234+
$container = new ContainerBuilder();
1235+
$container
1236+
->register('foo', FooClassWithEnumAttribute::class)
1237+
->setPublic(true)
1238+
->addArgument(FooUnitEnum::BAR);
1239+
1240+
$container->compile();
1241+
1242+
$dumper = new PhpDumper($container);
1243+
eval('?>'.$dumper->dump([
1244+
'class' => 'Symfony_DI_PhpDumper_Test_Enumeration',
1245+
]));
1246+
1247+
$container = new \Symfony_DI_PhpDumper_Test_Enumeration();
1248+
1249+
$this->assertSame(FooUnitEnum::BAR, $container->get('foo')->getBar());
1250+
}
1251+
12271252
public function testUninitializedSyntheticReference()
12281253
{
12291254
$container = new ContainerBuilder();

src/Symfony/Component/DependencyInjection/Tests/Dumper/XmlDumperTest.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
use Symfony\Component\DependencyInjection\Dumper\XmlDumper;
2323
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
2424
use Symfony\Component\DependencyInjection\Reference;
25+
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithEnumAttribute;
26+
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooUnitEnum;
2527
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooWithAbstractArgument;
2628

2729
class XmlDumperTest extends TestCase
@@ -282,4 +284,21 @@ public function testDumpServiceWithAbstractArgument()
282284
$dumper = new XmlDumper($container);
283285
$this->assertStringEqualsFile(self::$fixturesPath.'/xml/services_with_abstract_argument.xml', $dumper->dump());
284286
}
287+
288+
/**
289+
* @requires PHP 8.1
290+
*/
291+
public function testDumpHandlesEnumeration()
292+
{
293+
$container = new ContainerBuilder();
294+
$container
295+
->register(FooClassWithEnumAttribute::class, FooClassWithEnumAttribute::class)
296+
->setPublic(true)
297+
->addArgument(FooUnitEnum::BAR);
298+
299+
$container->compile();
300+
$dumper = new XmlDumper($container);
301+
302+
$this->assertEquals(file_get_contents(self::$fixturesPath.'/xml/services_with_enumeration.xml'), $dumper->dump());
303+
}
285304
}

src/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
use Symfony\Component\DependencyInjection\Dumper\YamlDumper;
2424
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
2525
use Symfony\Component\DependencyInjection\Reference;
26+
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithEnumAttribute;
27+
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooUnitEnum;
2628
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooWithAbstractArgument;
2729
use Symfony\Component\Yaml\Parser;
2830
use Symfony\Component\Yaml\Yaml;
@@ -142,6 +144,22 @@ public function testDumpServiceWithAbstractArgument()
142144
$this->assertStringEqualsFile(self::$fixturesPath.'/yaml/services_with_abstract_argument.yml', $dumper->dump());
143145
}
144146

147+
/**
148+
* @requires PHP 8.1
149+
*/
150+
public function testDumpHandlesEnumeration()
151+
{
152+
$container = new ContainerBuilder();
153+
$container
154+
->register(FooClassWithEnumAttribute::class, FooClassWithEnumAttribute::class)
155+
->setPublic(true)
156+
->addArgument(FooUnitEnum::BAR);
157+
158+
$container->compile();
159+
$dumper = new YamlDumper($container);
160+
161+
$this->assertEquals(file_get_contents(self::$fixturesPath.'/yaml/services_with_enumeration.yml'), $dumper->dump());
162+
}
145163

146164
private function assertEqualYamlStructure(string $expected, string $yaml, string $message = '')
147165
{
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
namespace Symfony\Component\DependencyInjection\Tests\Fixtures;
4+
5+
class FooClassWithEnumAttribute
6+
{
7+
private FooUnitEnum $bar;
8+
9+
public function __construct(FooUnitEnum $bar)
10+
{
11+
$this->bar = $bar;
12+
}
13+
14+
public function getBar(): FooUnitEnum
15+
{
16+
return $this->bar;
17+
}
18+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
namespace Symfony\Component\DependencyInjection\Tests\Fixtures;
4+
5+
enum FooUnitEnum
6+
{
7+
case BAR;
8+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
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 https://symfony.com/schema/dic/services/services-1.0.xsd">
3+
<services>
4+
<service id="service_container" class="Symfony\Component\DependencyInjection\ContainerInterface" public="true" synthetic="true"/>
5+
<service id="Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithEnumAttribute" class="Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithEnumAttribute" public="true">
6+
<argument type="constant">Symfony\Component\DependencyInjection\Tests\Fixtures\FooUnitEnum::BAR</argument>
7+
</service>
8+
</services>
9+
</container>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
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 https://symfony.com/schema/dic/services/services-1.0.xsd">
3+
<services>
4+
<service id="service_container" class="Symfony\Component\DependencyInjection\ContainerInterface" public="true" synthetic="true"/>
5+
<service id="Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithEnumAttribute" class="Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithEnumAttribute" public="true">
6+
<argument type="constant">Symfony\Component\DependencyInjection\Tests\Fixtures\FooUnitEnum::BAZ</argument>
7+
</service>
8+
</services>
9+
</container>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
2+
services:
3+
service_container:
4+
class: Symfony\Component\DependencyInjection\ContainerInterface
5+
public: true
6+
synthetic: true
7+
Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithEnumAttribute:
8+
class: Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithEnumAttribute
9+
public: true
10+
arguments: [!php/const 'Symfony\Component\DependencyInjection\Tests\Fixtures\FooUnitEnum::BAR']
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
2+
services:
3+
service_container:
4+
class: Symfony\Component\DependencyInjection\ContainerInterface
5+
public: true
6+
synthetic: true
7+
Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithEnumAttribute:
8+
class: Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithEnumAttribute
9+
public: true
10+
arguments: [!php/const 'Symfony\Component\DependencyInjection\Tests\Fixtures\FooUnitEnum::BAZ']

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
use Symfony\Component\DependencyInjection\Tests\Fixtures\Bar;
4040
use Symfony\Component\DependencyInjection\Tests\Fixtures\BarInterface;
4141
use Symfony\Component\DependencyInjection\Tests\Fixtures\CaseSensitiveClass;
42+
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithEnumAttribute;
43+
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooUnitEnum;
4244
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooWithAbstractArgument;
4345
use Symfony\Component\DependencyInjection\Tests\Fixtures\NamedArgumentsDummy;
4446
use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype;
@@ -868,6 +870,32 @@ public function testInstanceof()
868870
$this->assertSame(['foo' => [[]], 'bar' => [[]]], $definition->getTags());
869871
}
870872

873+
/**
874+
* @requires PHP 8.1
875+
*/
876+
public function testEnumeration()
877+
{
878+
$container = new ContainerBuilder();
879+
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
880+
$loader->load('services_with_enumeration.xml');
881+
$container->compile();
882+
883+
$definition = $container->getDefinition(FooClassWithEnumAttribute::class);
884+
$this->assertSame([FooUnitEnum::BAR], $definition->getArguments());
885+
}
886+
887+
/**
888+
* @requires PHP 8.1
889+
*/
890+
public function testInvalidEnumeration()
891+
{
892+
$container = new ContainerBuilder();
893+
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
894+
895+
$this->expectException(\Error::class);
896+
$loader->load('services_with_invalid_enumeration.xml');
897+
}
898+
871899
public function testInstanceOfAndChildDefinition()
872900
{
873901
$container = new ContainerBuilder();

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

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
use Symfony\Component\DependencyInjection\Tests\Fixtures\Bar;
3939
use Symfony\Component\DependencyInjection\Tests\Fixtures\BarInterface;
4040
use Symfony\Component\DependencyInjection\Tests\Fixtures\CaseSensitiveClass;
41+
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithEnumAttribute;
42+
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooUnitEnum;
4143
use Symfony\Component\DependencyInjection\Tests\Fixtures\NamedArgumentsDummy;
4244
use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype;
4345
use Symfony\Component\ExpressionLanguage\Expression;
@@ -920,6 +922,33 @@ public function testDefaultValueOfTagged()
920922
$this->assertNull($iteratorArgument->getIndexAttribute());
921923
}
922924

925+
/**
926+
* @requires PHP 8.1
927+
*/
928+
public function testEnumeration()
929+
{
930+
$container = new ContainerBuilder();
931+
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
932+
$loader->load('services_with_enumeration.yml');
933+
$container->compile();
934+
935+
$definition = $container->getDefinition(FooClassWithEnumAttribute::class);
936+
$this->assertSame([FooUnitEnum::BAR], $definition->getArguments());
937+
}
938+
939+
/**
940+
* @requires PHP 8.1
941+
*/
942+
public function testInvalidEnumeration()
943+
{
944+
$container = new ContainerBuilder();
945+
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
946+
947+
$this->expectException(InvalidArgumentException::class);
948+
$this->expectExceptionMessage('The constant "Symfony\Component\DependencyInjection\Tests\Fixtures\FooUnitEnum::BAZ" is not defined');
949+
$loader->load('services_with_invalid_enumeration.yml');
950+
}
951+
923952
public function testReturnsClone()
924953
{
925954
$container = new ContainerBuilder();

src/Symfony/Component/Yaml/Inline.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ public static function dump($value, int $flags = 0): string
127127
return self::dumpNull($flags);
128128
case $value instanceof \DateTimeInterface:
129129
return $value->format('c');
130+
case $value instanceof \UnitEnum:
131+
return sprintf('%s::%s', \get_class($value), $value->name);
130132
case \is_object($value):
131133
if ($value instanceof TaggedValue) {
132134
return '!'.$value->getTag().' '.self::dump($value->getValue(), $flags);

0 commit comments

Comments
 (0)
0