8000 bug #40857 [DependencyInjection] Add support of PHP enumerations (ale… · symfony/symfony@ef06f33 · GitHub
[go: up one dir, main page]

Skip to content

Commit ef06f33

Browse files
bug #40857 [DependencyInjection] Add support of PHP enumerations (alexandre-daubois)
This PR was merged into the 4.4 branch. Discussion ---------- [DependencyInjection] Add support of PHP enumerations | Q | A | ------------- | --- | Branch? | 4.4 | Bug fix? | yes (new PHP version compatibility) | New feature? | no | Deprecations? | no | Tickets | Fix #40233 | License | MIT | Doc PR | _(see below)_ Added support of enums using `!php/const` tag, as they work the same way. Commits ------- 88c69c0 [DependencyInjection] Add support of PHP enumerations
2 parents b62881c + 88c69c0 commit ef06f33

17 files changed

+212
-0
lines changed

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

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

18131813
return $code;
18141814
}
1815+
} elseif ($value instanceof \UnitEnum) {
1816+
return sprintf('\%s::%s', \get_class($value), $value->name);
18151817
} elseif (\is_object($value) || \is_resource($value)) {
18161818
throw new RuntimeException('Unable to dump a service container if a parameter is an object or a resource.');
18171819
}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,9 @@ private function convertParameters(array $parameters, string $type, \DOMElement
313313
$element->setAttribute('type', 'binary');
314314
$text = $this->document->createTextNode(self::phpToXml(base64_encode($value)));
315315
$element->appendChild($text);
316+
} elseif ($value instanceof \UnitEnum) {
317+
$element->setAttribute('type', 'constant');
318+
$element->appendChild($this->document->createTextNode(self::phpToXml($value)));
316319
} else {
317320
if (\in_array($value, ['null', 'true', 'false'], true)) {
318321
$element->setAttribute('type', 'string');
@@ -366,6 +369,8 @@ public static function phpToXml($value): string
366369
return 'false';
367370
case $value instanceof Parameter:
368371
return '%'.$value.'%';
372+
case $value instanceof \UnitEnum:
373+
return sprintf('%s::%s', \get_class($value), $value->name);
369374
case \is_object($value) || \is_resource($value):
370375
throw new RuntimeException('Unable to dump a service container if a parameter is an object or a resource.');
371376
default:

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,8 @@ private function dumpValue($value)
286286
return $this->getExpressionCall((string) $value);
287287
} elseif ($value instanceof Definition) {
288288
return new TaggedValue('service', (new Parser())->parse("_:\n".$this->addService('_', $value), Yaml::PARSE_CUSTOM_TAGS)['_']['_']);
289+
} elseif ($value instanceof \UnitEnum) {
290+
return new TaggedValue('php/const', sprintf('%s::%s', \get_class($value), $value->name));
289291
} elseif (\is_object($value) || \is_resource($value)) {
290292
throw new RuntimeException('Unable to dump a service container if a parameter is an object or a resource.');
291293
}

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
use Symfony\Component\DependencyInjection\Tests\Compiler\Foo;
4141
use Symfony\Component\DependencyInjection\Tests\Compiler\Wither;
4242
use Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition;
43+
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithEnumAttribute;
44+
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooUnitEnum;
4345
use Symfony\Component\DependencyInjection\Tests\Fixtures\ScalarFactory;
4446
use Symfony\Component\DependencyInjection\Tests\Fixtures\StubbedTranslator;
4547
use Symfony\Component\DependencyInjection\Tests\Fixtures\TestDefinition1;
@@ -1208,6 +1210,29 @@ public function testDumpHandlesObjectClassNames()
12081210
$this->assertInstanceOf(\stdClass::class, $container->get('bar'));
12091211
}
12101212

1213+
/**
1214+
* @requires PHP 8.1
1215+
*/
1216+
public function testDumpHandlesEnumeration()
1217+
{
1218+
$container = new ContainerBuilder();
1219+
$container
1220+
->register('foo', FooClassWithEnumAttribute::class)
1221+
->setPublic(true)
1222+
->addArgument(FooUnitEnum::BAR);
1223+
1224+
$container->compile();
1225+
1226+
$dumper = new PhpDumper($container);
1227+
eval('?>'.$dumper->dump([
1228+
'class' => 'Symfony_DI_PhpDumper_Test_Enumeration',
1229+
]));
1230+
1231+
$container = new \Symfony_DI_PhpDumper_Test_Enumeration();
1232+
1233+
$this->assertSame(FooUnitEnum::BAR, $container->get('foo')->getBar());
1234+
}
1235+
12111236
public function testUninitializedSyntheticReference()
12121237
{
12131238
$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
@@ -21,6 +21,8 @@
2121
use Symfony\Component\DependencyInjection\Dumper\XmlDumper;
2222
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
2323
use Symfony\Component\DependencyInjection\Reference;
24+
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithEnumAttribute;
25+
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooUnitEnum;
2426

2527
class XmlDumperTest extends TestCase
2628
{
@@ -249,4 +251,21 @@ public function testDumpAbstractServices()
249251

250252
$this->assertEquals(file_get_contents(self::$fixturesPath.'/xml/services_abstract.xml'), $dumper->dump());
251253
}
254+
255+
/**
256+
* @requires PHP 8.1
257+
*/
258+
public function testDumpHandlesEnumeration()
259+
{
260+
$container = new ContainerBuilder();
261+
$container
262+
->register(FooClassWithEnumAttribute::class, FooClassWithEnumAttribute::class)
263+
->setPublic(true)
264+
->addArgument(FooUnitEnum::BAR);
265+
266+
$container->compile();
267+
$dumper = new XmlDumper($container);
268+
269+
$this->assertEquals(file_get_contents(self::$fixturesPath.'/xml/services_with_enumeration.xml'), $dumper->dump());
270+
}
252271
}

src/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.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\YamlDumper;
2323
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
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\Yaml\Parser;
2628
use Symfony\Component\Yaml\Yaml;
2729

@@ -129,6 +131,23 @@ public function testServiceClosure()
129131
$this->assertStringEqualsFile(self::$fixturesPath.'/yaml/services_with_service_closure.yml', $dumper->dump());
130132
}
131133

134+
/**
135+
* @requires PHP 8.1
136+
*/
137+
public function testDumpHandlesEnumeration()
138+
{
139+
$container = new ContainerBuilder();
140+
$container
141+
->register(FooClassWithEnumAttribute::class, FooClassWithEnumAttribute::class)
142+
->setPublic(true)
143+
->addArgument(FooUnitEnum::BAR);
144+
145+
$container->compile();
146+
$dumper = new YamlDumper($container);
147+
148+
$this->assertEquals(file_get_contents(self::$fixturesPath.'/yaml/services_with_enumeration.yml'), $dumper->dump());
149+
}
150+
132151
private function assertEqualYamlStructure(string $expected, string $yaml, string $message = '')
133152
{
134153
$parser = new Parser();
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
@@ -37,6 +37,8 @@
3737
use Symfony\Component\DependencyInjection\Tests\Fixtures\Bar;
3838
use Symfony\Component\DependencyInjection\Tests\Fixtures\BarInterface;
3939
use Symfony\Component\DependencyInjection\Tests\Fixtures\CaseSensitiveClass;
40+
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithEnumAttribute;
41+
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooUnitEnum;
4042
use Symfony\Component\DependencyInjection\Tests\Fixtures\NamedArgumentsDummy;
4143
use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype;
4244
use Symfony\Component\ExpressionLanguage\Expression;
@@ -827,6 +829,32 @@ public function testInstanceof()
827829
$this->assertSame(['foo' => [[]], 'bar' => [[]]], $definition->getTags());
828830
}
829831

832+
/**
833+
* @requires PHP 8.1
834+
*/
835+
public function testEnumeration()
836+
{
837+
$container = new ContainerBuilder();
838+
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
839+
$loader->load('services_with_enumeration.xml');
840+
$container->compile();
841+
842+
$definition = $container->getDefinition(FooClassWithEnumAttribute::class);
843+
$this->assertSame([FooUnitEnum::BAR], $definition->getArguments());
844+
}
845+
846+
/**
847+
* @requires PHP 8.1
848+
*/
849+
public function testInvalidEnumeration()
850+
{
851+
$container = new ContainerBuilder();
852+
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
853+
854+
$this->expectException(\Error::class);
855+
$loader->load('services_with_invalid_enumeration.xml');
856+
}
857+
830858
public function testInstanceOfAndChildDefinitionNotAllowed()
831859
{
832860
$this->expectException(InvalidArgumentException::class);

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

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
use Symfony\Component\DependencyInjection\Tests\Fixtures\Bar;
3838
use Symfony\Component\DependencyInjection\Tests\Fixtures\BarInterface;
3939
use Symfony\Component\DependencyInjection\Tests\Fixtures\CaseSensitiveClass;
40+
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithEnumAttribute;
41+
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooUnitEnum;
4042
use Symfony\Component\DependencyInjection\Tests\Fixtures\NamedArgumentsDummy;
4143
use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype;
4244
use Symfony\Component\ExpressionLanguage\Expression;
@@ -909,6 +911,33 @@ public function testDefaultValueOfTagged()
909911
$this->assertNull($iteratorArgument->getIndexAttribute());
910912
}
911913

914+
/**
915+
* @requires PHP 8.1
916+
*/
917+
public function testEnumeration()
918+
{
919+
$container = new ContainerBuilder();
920+
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
921+
$loader->load('services_with_enumeration.yml');
922+
$container->compile();
923+
924+
$definition = $container->getDefinition(FooClassWithEnumAttribute::class);
925+
$this->assertSame([FooUnitEnum::BAR], $definition->getArguments());
926+
}
927+
928+
/**
929+
* @requires PHP 8.1
930+
*/
931+
public function testInvalidEnumeration()
932+
{
933+
$container = new ContainerBuilder();
934+
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
935+
936+
$this->expectException(InvalidArgumentException::class);
937+
$this->expectExceptionMessage('The constant "Symfony\Component\DependencyInjection\Tests\Fixtures\FooUnitEnum::BAZ" is not defined');
938+
$loader->load('services_with_invalid_enumeration.yml');
939+
}
940+
912941
public function testReturnsClone()
913942
{
914943
$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('!php/const %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);
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\Yaml\Tests\Fixtures;
4+
5+
enum FooUnitEnum
6+
{
7+
case BAR;
8+
}

src/Symfony/Component/Yaml/Tests/InlineTest.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Symfony\Component\Yaml\Exception\ParseException;
1616
use Symfony\Component\Yaml\Inline;
1717
use Symfony\Component\Yaml\Tag\TaggedValue;
18+
use Symfony\Component\Yaml\Tests\Fixtures\FooUnitEnum;
1819
use Symfony\Component\Yaml\Yaml;
1920

2021
class InlineTest extends TestCase
@@ -577,6 +578,14 @@ public function testDumpDateTime($dateTime, $expected)
577578
$this->assertSame($expected, Inline::dump($dateTime));
578579
}
579580

581+
/**
582+
* @requires PHP 8.1
583+
*/
584+
public function testDumpUnitEnum()
585+
{
586+
$this->assertSame("!php/const Symfony\Component\Yaml\Tests\Fixtures\FooUnitEnum::BAR", Inline::dump(FooUnitEnum::BAR));
587+
}
588+
580589
public function getDateTimeDumpTests()
581590
{
582591
$tests = [];

0 commit comments

Comments
 (0)
0