Skip to content

Commit 997b97b

Browse files
bug #51307 [DependencyInjection] fix dump xml with array/object/enum default value (Jean-Beru)
This PR was squashed before being merged into the 5.4 branch. Discussion ---------- [DependencyInjection] fix dump xml with array/object/enum default value | Q | A | ------------- | --- | Branch? | 5.4 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | Fix #48178 | License | MIT | Doc PR | This PR fixes #48178 when attempting to dump the container in these conditions: * The constructor has in its arguments a non-empty array, an object or an enum with a default value * A second argument is placed after * A third argument is placed after and is using configuration Example (might be more explicit): ```php class Foo { public function __construct( array $array = ['a', 'b', 'c'], bool $firstOptional = false, bool $secondOptional = false ) {} } ``` ```yaml services: Foo: arguments: secondOptional: true ``` :warning: This PR might cause Git conflicts in 6.3 and 6.4 versions. Do I have to create a dedicated PR for these versions ? Commits ------- ddc699a [DependencyInjection] fix dump xml with array/object/enum default value
2 parents 400ee5c + ddc699a commit 997b97b

12 files changed

+219
-2
lines changed

src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php

+5-2
Original file line numberDiff line numberDiff line change
@@ -212,13 +212,16 @@ private function autowireCalls(\ReflectionClass $reflectionClass, bool $isRoot,
212212
unset($arguments[$j]);
213213
$arguments[$namedArguments[$j]] = $value;
214214
}
215-
if ($namedArguments || !$value instanceof $this->defaultArgument) {
215+
if (!$value instanceof $this->defaultArgument) {
216216
continue;
217217
}
218218

219219
if (\PHP_VERSION_ID >= 80100 && (\is_array($value->value) ? $value->value : \is_object($value->value))) {
220-
unset($arguments[$j]);
221220
$namedArguments = $value->names;
221+
}
222+
223+
if ($namedArguments) {
224+
unset($arguments[$j]);
222225
} else {
223226
$arguments[$j] = $value->value;
224227
}

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

+32
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,15 @@
1717
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
1818
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
1919
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
20+
use Symfony\Component\DependencyInjection\Compiler\AutowirePass;
2021
use Symfony\Component\DependencyInjection\ContainerBuilder;
2122
use Symfony\Component\DependencyInjection\ContainerInterface;
2223
use Symfony\Component\DependencyInjection\Dumper\XmlDumper;
2324
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
2425
use Symfony\Component\DependencyInjection\Reference;
26+
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithDefaultArrayAttribute;
27+
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithDefaultEnumAttribute;
28+
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithDefaultObjectAttribute;
2529
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithEnumAttribute;
2630
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooUnitEnum;
2731
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooWithAbstractArgument;
@@ -287,6 +291,34 @@ public function testDumpHandlesEnumeration()
287291
$this->assertEquals(file_get_contents(self::$fixturesPath.'/xml/services_with_enumeration.xml'), $dumper->dump());
288292
}
289293

294+
/**
295+
* @requires PHP 8.1
296+
*
297+
* @dataProvider provideDefaultClasses
298+
*/
299+
public function testDumpHandlesDefaultAttribute($class, $expectedFile)
300+
{
301+
$container = new ContainerBuilder();
302+
$container
303+
->register('foo', $class)
304+
->setPublic(true)
305+
->setAutowired(true)
306+
->setArguments([2 => true]);
307+
308+
(new AutowirePass())->process($container);
309+
310+
$dumper = new XmlDumper($container);
311+
312+
$this->assertSame(file_get_contents(self::$fixturesPath.'/xml/'.$expectedFile), $dumper->dump());
313+
}
314+
315+
public static function provideDefaultClasses()
316+
{
317+
yield [FooClassWithDefaultArrayAttribute::class, 'services_with_default_array.xml'];
318+
yield [FooClassWithDefaultObjectAttribute::class, 'services_with_default_object.xml'];
319+
yield [FooClassWithDefaultEnumAttribute::class, 'services_with_default_enumeration.xml'];
320+
}
321+
290322
public function testDumpServiceWithAbstractArgument()
291323
{
292324
$container = new ContainerBuilder();

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

+32
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,16 @@
1717
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
1818
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
1919
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
20+
use Symfony\Component\DependencyInjection\Compiler\AutowirePass;
2021
use Symfony\Component\DependencyInjection\ContainerBuilder;
2122
use Symfony\Component\DependencyInjection\ContainerInterface;
2223
use Symfony\Component\DependencyInjection\Definition;
2324
use Symfony\Component\DependencyInjection\Dumper\YamlDumper;
2425
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
2526
use Symfony\Component\DependencyInjection\Reference;
27+
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithDefaultArrayAttribute;
28+
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithDefaultEnumAttribute;
29+
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithDefaultObjectAttribute;
2630
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithEnumAttribute;
2731
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooUnitEnum;
2832
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooWithAbstractArgument;
@@ -153,6 +157,34 @@ public function testDumpHandlesEnumeration()
153157
$this->assertEquals(file_get_contents(self::$fixturesPath.'/yaml/services_with_enumeration.yml'), $dumper->dump());
154158
}
155159

160+
/**
161+
* @requires PHP 8.1
162+
*
163+
* @dataProvider provideDefaultClasses
164+
*/
165+
public function testDumpHandlesDefaultAttribute($class, $expectedFile)
166+
{
167+
$container = new ContainerBuilder();
168+
$container
169+
->register('foo', $class)
170+
->setPublic(true)
171+
->setAutowired(true)
172+
->setArguments([2 => true]);
173+
174+
(new AutowirePass())->process($container);
175+
176+
$dumper = new YamlDumper($container);
177+
178+
$this->assertSame(file_get_contents(self::$fixturesPath.'/yaml/'.$expectedFile), $dumper->dump());
179+
}
180+
181+
public static function provideDefaultClasses()
182+
{
183+
yield [FooClassWithDefaultArrayAttribute::class, 'services_with_default_array.yml'];
184+
yield [FooClassWithDefaultObjectAttribute::class, 'services_with_default_object.yml'];
185+
yield [FooClassWithDefaultEnumAttribute::class, 'services_with_default_enumeration.yml'];
186+
}
187+
156188
public function testDumpServiceWithAbstractArgument()
157189
{
158190
$container = new ContainerBuilder();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
namespace Symfony\Component\DependencyInjection\Tests\Fixtures;
4+
5+
class FooClassWithDefaultArrayAttribute
6+
{
7+
public function __construct(
8+
array $array = ['a', 'b', 'c'],
9+
bool $firstOptional = false,
10+
bool $secondOptional = false
11+
) {}
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
namespace Symfony\Component\DependencyInjection\Tests\Fixtures;
4+
5+
class FooClassWithDefaultEnumAttribute
6+
{
7+
public function __construct(
8+
FooUnitEnum $enum = FooUnitEnum::FOO,
9+
bool $firstOptional = false,
10+
bool $secondOptional = false,
11+
) {}
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
namespace Symfony\Component\DependencyInjection\Tests\Fixtures;
4+
5+
class FooClassWithDefaultObjectAttribute
6+
{
7+
public function __construct(
8+
object $object = new \stdClass(),
9+
bool $firstOptional = false,
10+
bool $secondOptional = false,
11+
) {}
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
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="foo" class="Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithDefaultArrayAttribute" public="true" autowire="true">
6+
<argument key="secondOptional">true</argument>
7+
</service>
8+
<service id="Psr\Container\ContainerInterface" alias="service_container">
9+
<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>
10+
</service>
11+
<service id="Symfony\Component\DependencyInjection\ContainerInterface" alias="service_container">
12+
<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>
13+
</service>
14+
</services>
15+
</container>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
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="foo" class="Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithDefaultEnumAttribute" public="true" autowire="true">
6+
<argument key="secondOptional">true</argument>
7+
</service>
8+
<service id="Psr\Container\ContainerInterface" alias="service_container">
9+
<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>
10+
</service>
11+
<service id="Symfony\Component\DependencyInjection\ContainerInterface" alias="service_container">
12+
<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>
13+
</service>
14+
</services>
15+
</container>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
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="foo" class="Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithDefaultObjectAttribute" public="true" autowire="true">
6+
<argument key="secondOptional">true</argument>
7+
</service>
8+
<service id="Psr\Container\ContainerInterface" alias="service_container">
9+
<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>
10+
</service>
11+
<service id="Symfony\Component\DependencyInjection\ContainerInterface" alias="service_container">
12+
<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>
13+
</service>
14+
</services>
15+
</container>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
2+
services:
3+
service_container:
4+
class: Symfony\Component\DependencyInjection\ContainerInterface
5+
public: true
6+
synthetic: true
7+
foo:
8+
class: Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithDefaultArrayAttribute
9+
public: true
10+
autowire: true
11+
arguments: { secondOptional: true }
12+
Psr\Container\ContainerInterface:
13+
alias: service_container
14+
deprecated:
15+
package: symfony/dependency-injection
16+
version: 5.1
17+
message: The "%alias_id%" autowiring alias is deprecated. Define it explicitly in your app if you want to keep using it.
18+
Symfony\Component\DependencyInjection\ContainerInterface:
19+
alias: service_container
20+
deprecated:
21+
package: symfony/dependency-injection
22+
version: 5.1
23+
message: The "%alias_id%" autowiring alias is deprecated. Define it explicitly in your app if you want to keep using it.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
2+
services:
3+
service_container:
4+
class: Symfony\Component\DependencyInjection\ContainerInterface
5+
public: true
6+
synthetic: true
7+
foo:
8+
class: Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithDefaultEnumAttribute
9+
public: true
10+
autowire: true
11+
arguments: { secondOptional: true }
12+
Psr\Container\ContainerInterface:
13+
alias: service_container
14+
deprecated:
15+
package: symfony/dependency-injection
16+
version: 5.1
17+
message: The "%alias_id%" autowiring alias is deprecated. Define it explicitly in your app if you want to keep using it.
18+
Symfony\Component\DependencyInjection\ContainerInterface:
19+
alias: service_container
20+
deprecated:
21+
package: symfony/dependency-injection
22+
version: 5.1
23+
message: The "%alias_id%" autowiring alias is deprecated. Define it explicitly in your app if you want to keep using it.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
2+
services:
3+
service_container:
4+
class: Symfony\Component\DependencyInjection\ContainerInterface
5+
public: true
6+
synthetic: true
7+
foo:
8+
class: Symfony\Component\DependencyInjection\Tests\Fixtures\FooClassWithDefaultObjectAttribute
9+
public: true
10+
autowire: true
11+
arguments: { secondOptional: true }
12+
Psr\Container\ContainerInterface:
13+
alias: service_container
14+
deprecated:
15+
package: symfony/dependency-injection
16+
version: 5.1
17+
message: The "%alias_id%" autowiring alias is deprecated. Define it explicitly in your app if you want to keep using it.
18+
Symfony\Component\DependencyInjection\ContainerInterface:
19+
alias: service_container
20+
deprecated:
21+
package: symfony/dependency-injection
22+
version: 5.1
23+
message: The "%alias_id%" autowiring alias is deprecated. Define it explicitly in your app if you want to keep using it.

0 commit comments

Comments
 (0)