Skip to content

Commit

Permalink
[DependencyInjection] fix dump xml with array/object/enum default value
Browse files Browse the repository at this point in the history
  • Loading branch information
Jean-Beru authored and nicolas-grekas committed Aug 14, 2023
1 parent 6736a10 commit addc22f
Show file tree
Hide file tree
Showing 12 changed files with 219 additions and 2 deletions.
7 changes: 5 additions & 2 deletions Compiler/AutowirePass.php
Original file line number Diff line number Diff line change
Expand Up @@ -212,13 +212,16 @@ private function autowireCalls(\ReflectionClass $reflectionClass, bool $isRoot,
unset($arguments[$j]);
$arguments[$namedArguments[$j]] = $value;
}
if ($namedArguments || !$value instanceof $this->defaultArgument) {
if (!$value instanceof $this->defaultArgument) {
continue;
}

if (\PHP_VERSION_ID >= 80100 && (\is_array($value->value) ? $value->value : \is_object($value->value))) {
unset($arguments[$j]);
$namedArguments = $value->names;
}

if ($namedArguments) {
unset($arguments[$j]);
} else {
$arguments[$j] = $value->value;
}
Expand Down
32 changes: 32 additions & 0 deletions Tests/Dumper/XmlDumperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,15 @@
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
use Symfony\Component\DependencyInjection\Compiler\AutowirePass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Dumper\XmlDumper;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithDefaultArrayAttribute;
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithDefaultEnumAttribute;
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithDefaultObjectAttribute;
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithEnumAttribute;
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooUnitEnum;
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooWithAbstractArgument;
Expand Down Expand Up @@ -287,6 +291,34 @@ public function testDumpHandlesEnumeration()
$this->assertEquals(file_get_contents(self::$fixturesPath.'/xml/services_with_enumeration.xml'), $dumper->dump());
}

/**
* @requires PHP 8.1
*
* @dataProvider provideDefaultClasses
*/
public function testDumpHandlesDefaultAttribute($class, $expectedFile)
{
$container = new ContainerBuilder();
$container
->register('foo', $class)
->setPublic(true)
->setAutowired(true)
->setArguments([2 => true]);

(new AutowirePass())->process($container);

$dumper = new XmlDumper($container);

$this->assertSame(file_get_contents(self::$fixturesPath.'/xml/'.$expectedFile), $dumper->dump());
}

public static function provideDefaultClasses()
{
yield [FooClassWithDefaultArrayAttribute::class, 'services_with_default_array.xml'];
yield [FooClassWithDefaultObjectAttribute::class, 'services_with_default_object.xml'];
yield [FooClassWithDefaultEnumAttribute::class, 'services_with_default_enumeration.xml'];
}

public function testDumpServiceWithAbstractArgument()
{
$container = new ContainerBuilder();
Expand Down
32 changes: 32 additions & 0 deletions Tests/Dumper/YamlDumperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,16 @@
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
use Symfony\Component\DependencyInjection\Compiler\AutowirePass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Dumper\YamlDumper;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithDefaultArrayAttribute;
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithDefaultEnumAttribute;
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithDefaultObjectAttribute;
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithEnumAttribute;
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooUnitEnum;
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooWithAbstractArgument;
Expand Down Expand Up @@ -153,6 +157,34 @@ public function testDumpHandlesEnumeration()
$this->assertEquals(file_get_contents(self::$fixturesPath.'/yaml/services_with_enumeration.yml'), $dumper->dump());
}

/**
* @requires PHP 8.1
*
* @dataProvider provideDefaultClasses
*/
public function testDumpHandlesDefaultAttribute($class, $expectedFile)
{
$container = new ContainerBuilder();
$container
->register('foo', $class)
->setPublic(true)
->setAutowired(true)
->setArguments([2 => true]);

(new AutowirePass())->process($container);

$dumper = new YamlDumper($container);

$this->assertSame(file_get_contents(self::$fixturesPath.'/yaml/'.$expectedFile), $dumper->dump());
}

public static function provideDefaultClasses()
{
yield [FooClassWithDefaultArrayAttribute::class, 'services_with_default_array.yml'];
yield [FooClassWithDefaultObjectAttribute::class, 'services_with_default_object.yml'];
yield [FooClassWithDefaultEnumAttribute::class, 'services_with_default_enumeration.yml'];
}

public function testDumpServiceWithAbstractArgument()
{
$container = new ContainerBuilder();
Expand Down
12 changes: 12 additions & 0 deletions Tests/Fixtures/FooClassWithDefaultArrayAttribute.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

namespace Symfony\Component\DependencyInjection\Tests\Fixtures;

class FooClassWithDefaultArrayAttribute
{
public function __construct(
array $array = ['a', 'b', 'c'],
bool $firstOptional = false,
bool $secondOptional = false
) {}
}
12 changes: 12 additions & 0 deletions Tests/Fixtures/FooClassWithDefaultEnumAttribute.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

namespace Symfony\Component\DependencyInjection\Tests\Fixtures;

class FooClassWithDefaultEnumAttribute
{
public function __construct(
FooUnitEnum $enum = FooUnitEnum::FOO,
bool $firstOptional = false,
bool $secondOptional = false,
) {}
}
12 changes: 12 additions & 0 deletions Tests/Fixtures/FooClassWithDefaultObjectAttribute.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

namespace Symfony\Component\DependencyInjection\Tests\Fixtures;

class FooClassWithDefaultObjectAttribute
{
public function __construct(
object $object = new \stdClass(),
bool $firstOptional = false,
bool $secondOptional = false,
) {}
}
15 changes: 15 additions & 0 deletions Tests/Fixtures/xml/services_with_default_array.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?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 https://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="service_container" class="Symfony\Component\DependencyInjection\ContainerInterface" public="true" synthetic="true"/>
<service id="foo" class="Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithDefaultArrayAttribute" public="true" autowire="true">
<argument key="secondOptional">true</argument>
</service>
<service id="Psr\Container\ContainerInterface" alias="service_container">
<deprecated package="symfony/dependency-injection" version="5.1">The "%alias_id%" autowiring alias is deprecated. Define it explicitly in your app if you want to keep using it.</deprecated>
</service>
<service id="Symfony\Component\DependencyInjection\ContainerInterface" alias="service_container">
<deprecated package="symfony/dependency-injection" version="5.1">The "%alias_id%" autowiring alias is deprecated. Define it explicitly in your app if you want to keep using it.</deprecated>
</service>
</services>
</container>
15 changes: 15 additions & 0 deletions Tests/Fixtures/xml/services_with_default_enumeration.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?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 https://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="service_container" class="Symfony\Component\DependencyInjection\ContainerInterface" public="true" synthetic="true"/>
<service id="foo" class="Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithDefaultEnumAttribute" public="true" autowire="true">
<argument key="secondOptional">true</argument>
</service>
<service id="Psr\Container\ContainerInterface" alias="service_container">
<deprecated package="symfony/dependency-injection" version="5.1">The "%alias_id%" autowiring alias is deprecated. Define it explicitly in your app if you want to keep using it.</deprecated>
</service>
<service id="Symfony\Component\DependencyInjection\ContainerInterface" alias="service_container">
<deprecated package="symfony/dependency-injection" version="5.1">The "%alias_id%" autowiring alias is deprecated. Define it explicitly in your app if you want to keep using it.</deprecated>
</service>
</services>
</container>
15 changes: 15 additions & 0 deletions Tests/Fixtures/xml/services_with_default_object.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?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 https://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="service_container" class="Symfony\Component\DependencyInjection\ContainerInterface" public="true" synthetic="true"/>
<service id="foo" class="Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithDefaultObjectAttribute" public="true" autowire="true">
<argument key="secondOptional">true</argument>
</service>
<service id="Psr\Container\ContainerInterface" alias="service_container">
<deprecated package="symfony/dependency-injection" version="5.1">The "%alias_id%" autowiring alias is deprecated. Define it explicitly in your app if you want to keep using it.</deprecated>
</service>
<service id="Symfony\Component\DependencyInjection\ContainerInterface" alias="service_container">
<deprecated package="symfony/dependency-injection" version="5.1">The "%alias_id%" autowiring alias is deprecated. Define it explicitly in your app if you want to keep using it.</deprecated>
</service>
</services>
</container>
23 changes: 23 additions & 0 deletions Tests/Fixtures/yaml/services_with_default_array.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@

services:
service_container:
class: Symfony\Component\DependencyInjection\ContainerInterface
public: true
synthetic: true
foo:
class: Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithDefaultArrayAttribute
public: true
autowire: true
arguments: { secondOptional: true }
Psr\Container\ContainerInterface:
alias: service_container
deprecated:
package: symfony/dependency-injection
version: 5.1
message: The "%alias_id%" autowiring alias is deprecated. Define it explicitly in your app if you want to keep using it.
Symfony\Component\DependencyInjection\ContainerInterface:
alias: service_container
deprecated:
package: symfony/dependency-injection
version: 5.1
message: The "%alias_id%" autowiring alias is deprecated. Define it explicitly in your app if you want to keep using it.
23 changes: 23 additions & 0 deletions Tests/Fixtures/yaml/services_with_default_enumeration.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@

services:
service_container:
class: Symfony\Component\DependencyInjection\ContainerInterface
public: true
synthetic: true
foo:
class: Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithDefaultEnumAttribute
public: true
autowire: true
arguments: { secondOptional: true }
Psr\Container\ContainerInterface:
alias: service_container
deprecated:
package: symfony/dependency-injection
version: 5.1
message: The "%alias_id%" autowiring alias is deprecated. Define it explicitly in your app if you want to keep using it.
Symfony\Component\DependencyInjection\ContainerInterface:
alias: service_container
deprecated:
package: symfony/dependency-injection
version: 5.1
message: The "%alias_id%" autowiring alias is deprecated. Define it explicitly in your app if you want to keep using it.
23 changes: 23 additions & 0 deletions Tests/Fixtures/yaml/services_with_default_object.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@

services:
service_container:
class: Symfony\Component\DependencyInjection\ContainerInterface
public: true
synthetic: true
foo:
class: Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithDefaultObjectAttribute
public: true
autowire: true
arguments: { secondOptional: true }
Psr\Container\ContainerInterface:
alias: service_container
deprecated:
package: symfony/dependency-injection
version: 5.1
message: The "%alias_id%" autowiring alias is deprecated. Define it explicitly in your app if you want to keep using it.
Symfony\Component\DependencyInjection\ContainerInterface:
alias: service_container
deprecated:
package: symfony/dependency-injection
version: 5.1
message: The "%alias_id%" autowiring alias is deprecated. Define it explicitly in your app if you want to keep using it.

0 comments on commit addc22f

Please sign in to comment.