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

Appearance settings

Commit 27e2a1a

Browse filesBrowse files
author
Hugo Hamon
committed
[Form] use new service locator in DependencyInjectionExtension class, so that form types can be made private at some point.
1 parent 3e9b8f3 commit 27e2a1a
Copy full SHA for 27e2a1a

File tree

6 files changed

+313
-238
lines changed
Filter options

6 files changed

+313
-238
lines changed

‎src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml
+3-5Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,11 @@
3030

3131
<!-- DependencyInjectionExtension -->
3232
<service id="form.extension" class="Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension" public="false">
33-
<argument type="service" id="service_container" />
33+
<argument type="service-locator" />
3434
<!-- All services with tag "form.type" are inserted here by FormPass -->
35-
<argument type="collection" />
35+
<argument type="iterator" />
3636
<!-- All services with tag "form.type_extension" are inserted here by FormPass -->
37-
<argument type="collection" />
38-
<!-- All services with tag "form.type_guesser" are inserted here by FormPass -->
39-
<argument type="collection" />
37+
<argument type="iterator" />
4038
</service>
4139

4240
<!-- ValidatorTypeGuesser -->

‎src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/FormPassTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/FormPassTest.php
+81-82Lines changed: 81 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\FormPass;
16+
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
17+
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
1618
use Symfony\Component\DependencyInjection\ContainerBuilder;
1719
use Symfony\Component\DependencyInjection\Definition;
1820
use Symfony\Component\DependencyInjection\Reference;
@@ -27,8 +29,7 @@ class FormPassTest extends TestCase
2729
{
2830
public function testDoNothingIfFormExtensionNotLoaded()
2931
{
30-
$container = new ContainerBuilder();
31-
$container->addCompilerPass(new FormPass());
32+
$container = $this->createContainerBuilder();
3233

3334
$container->compile();
3435

@@ -37,47 +38,37 @@ public function testDoNothingIfFormExtensionNotLoaded()
3738

3839
public function testAddTaggedTypes()
3940
{
40-
$container = new ContainerBuilder();
41-
$container->addCompilerPass(new FormPass());
42-
43-
$extDefinition = new Definition('Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension');
44-
$extDefinition->setArguments(array(
45-
new Reference('service_container'),
46-
array(),
47-
array(),
48-
array(),
49-
));
41+
$container = $this->createContainerBuilder();
5042

51-
$container->setDefinition('form.extension', $extDefinition);
43+
$container->setDefinition('form.extension', $this->createExtensionDefinition());
5244
$container->register('my.type1', __CLASS__.'_Type1')->addTag('form.type');
5345
$container->register('my.type2', __CLASS__.'_Type2')->addTag('form.type');
5446

5547
$container->compile();
5648

5749
$extDefinition = $container->getDefinition('form.extension');
58-
59-
$this->assertEquals(array(
60-
__CLASS__.'_Type1' => 'my.type1',
61-
__CLASS__.'_Type2' => 'my.type2',
62-
), $extDefinition->getArgument(1));
50+
$locator = $extDefinition->getArgument(0);
51+
52+
$this->assertInstanceOf(ServiceLocatorArgument::class, $locator);
53+
$this->assertEquals(
54+
new ServiceLocatorArgument(array(
55+
__CLASS__.'_Type1' => new Reference('my.type1'),
56+
__CLASS__.'_Type2' => new Reference('my.type2'),
57+
'my.type1' => new Reference('my.type1'),
58+
'my.type2' => new Reference('my.type2'),
59+
)),
60+
$locator
61+
);
6362
}
6463

6564
/**
6665
* @dataProvider addTaggedTypeExtensionsDataProvider
6766
*/
68-
public function testAddTaggedTypeExtensions(array $extensions, array $expectedRegisteredExtensions)
67+
public function testAddTaggedTypeExtensions(array $extensions, IteratorArgument $expectedRegisteredExtensions)
6968
{
70-
$container = new ContainerBuilder();
71-
$container->addCompilerPass(new FormPass());
69+
$container = $this->createContainerBuilder();
7270

73-
$extDefinition = new Definition('Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension', array(
74-
new Reference('service_container'),
75-
array(),
76-
array(),
77-
array(),
78-
));
79-
80-
$container->setDefinition('form.extension', $extDefinition);
71+
$container->setDefinition('form.extension', $this->createExtensionDefinition());
8172

8273
foreach ($extensions as $serviceId => $tag) {
8374
$container->register($serviceId, 'stdClass')->addTag('form.type_extension', $tag);
@@ -86,7 +77,7 @@ public function testAddTaggedTypeExtensions(array $extensions, array $expectedRe
8677
$container->compile();
8778

8879
$extDefinition = $container->getDefinition('form.extension');
89-
$this->assertSame($expectedRegisteredExtensions, $extDefinition->getArgument(2));
80+
$this->assertEquals($expectedRegisteredExtensions, $extDefinition->getArgument(1));
9081
}
9182

9283
/**
@@ -101,10 +92,13 @@ public function addTaggedTypeExtensionsDataProvider()
10192
'my.type_extension2' => array('extended_type' => 'type1'),
10293
'my.type_extension3' => array('extended_type' => 'type2'),
10394
),
104-
array(
105-
'type1' => array('my.type_extension1', 'my.type_extension2'),
106-
'type2' => array('my.type_extension3'),
107-
),
95+
new IteratorArgument(array(
96+
'type1' => new IteratorArgument(array(
97+
new Reference('my.type_extension1'),
98+
new Reference('my.type_extension2'),
99+
)),
100+
'type2' => new IteratorArgument(array(new Reference('my.type_extension3'))),
101+
)),
108102
),
109103
array(
110104
array(
@@ -115,10 +109,18 @@ public function addTaggedTypeExtensionsDataProvider()
115109
'my.type_extension5' => array('extended_type' => 'type2', 'priority' => 1),
116110
'my.type_extension6' => array('extended_type' => 'type2', 'priority' => 1),
117111
),
118-
array(
119-
'type1' => array('my.type_extension2', 'my.type_extension1', 'my.type_extension3'),
120-
'type2' => array('my.type_extension4', 'my.type_extension5', 'my.type_extension6'),
121-
),
112+
new IteratorArgument(array(
113+
'type1' => new IteratorArgument(array(
114+
new Reference('my.type_extension2'),
115+
new Reference('my.type_extension1'),
116+
new Reference('my.type_extension3'),
117+
)),
118+
'type2' => new IteratorArgument(array(
119+
new Reference('my.type_extension4'),
120+
new Reference('my.type_extension5'),
121+
new Reference('my.type_extension6'),
122+
)),
123+
)),
122124
),
123125
);
124126
}
@@ -129,17 +131,9 @@ public function addTaggedTypeExtensionsDataProvider()
129131
*/
130132
public function testAddTaggedFormTypeExtensionWithoutExtendedTypeAttribute()
131133
{
132-
$container = new ContainerBuilder();
133-
$container->addCompilerPass(new FormPass());
134+
$container = $this->createContainerBuilder();
134135

135-
$extDefinition = new Definition('Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension', array(
136-
new Reference('service_container'),
137-
array(),
138-
array(),
139-
array(),
140-
));
141-
142-
$container->setDefinition('form.extension', $extDefinition);
136+
$container->setDefinition('form.extension', $this->createExtensionDefinition());
143137
$container->register('my.type_extension', 'stdClass')
144138
->addTag('form.type_extension');
145139

@@ -148,68 +142,73 @@ public function testAddTaggedFormTypeExtensionWithoutExtendedTypeAttribute()
148142

149143
public function testAddTaggedGuessers()
150144
{
151-
$container = new ContainerBuilder();
152-
$container->addCompilerPass(new FormPass());
153-
154-
$extDefinition = new Definition('Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension');
155-
$extDefinition->setArguments(array(
156-
new Reference('service_container'),
157-
array(),
158-
array(),
159-
array(),
160-
));
145+
$container = $this->createContainerBuilder();
161146

162147
$definition1 = new Definition('stdClass');
163148
$definition1->addTag('form.type_guesser');
164149
$definition2 = new Definition('stdClass');
165150
$definition2->addTag('form.type_guesser');
166151

167-
$container->setDefinition('form.extension', $extDefinition);
152+
$container->setDefinition('form.extension', $this->createExtensionDefinition());
168153
$container->setDefinition('my.guesser1', $definition1);
169154
$container->setDefinition('my.guesser2', $definition2);
170155

171156
$container->compile();
172157

173158
$extDefinition = $container->getDefinition('form.extension');
174-
175-
$this->assertSame(array(
176-
'my.guesser1',
177-
'my.guesser2',
178-
), $extDefinition->getArgument(3));
159+
$iteratorArgument = $extDefinition->getArgument(2);
160+
161+
$this->assertInstanceOf(IteratorArgument::class, $iteratorArgument);
162+
$this->assertEquals(
163+
new IteratorArgument(array(
164+
new Reference('my.guesser1'),
165+
new Reference('my.guesser2'),
166+
)),
167+
$iteratorArgument
168+
);
179169
}
180170

181171
/**
182172
* @dataProvider privateTaggedServicesProvider
183173
*/
184-
public function testPrivateTaggedServices($id, $tagName, $expectedExceptionMessage)
174+
public function testPrivateTaggedServices($id, $tagName, array $tagAttributes = array())
185175
{
186-
$container = new ContainerBuilder();
187-
$container->addCompilerPass(new FormPass());
188-
189-
$extDefinition = new Definition('Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension');
190-
$extDefinition->setArguments(array(
191-
new Reference('service_container'),
192-
array(),
193-
array(),
194-
array(),
195-
));
176+
$container = $this->createContainerBuilder();
196177

197-
$container->setDefinition('form.extension', $extDefinition);
198-
$container->register($id, 'stdClass')->setPublic(false)->addTag($tagName);
199-
200-
$this->setExpectedException('\InvalidArgumentException', $expectedExceptionMessage);
178+
$container->setDefinition('form.extension', $this->createExtensionDefinition());
179+
$container->register($id, 'stdClass')->setPublic(false)->addTag($tagName, $tagAttributes);
201180

202181
$container->compile();
203182
}
204183

205184
public function privateTaggedServicesProvider()
206185
{
207186
return array(
208-
array('my.type', 'form.type', 'The service "my.type" must be public as form types are lazy-loaded'),
209-
array('my.type_extension', 'form.type_extension', 'The service "my.type_extension" must be public as form type extensions are lazy-loaded'),
210-
array('my.guesser', 'form.type_guesser', 'The service "my.guesser" must be public as form type guessers are lazy-loaded'),
187+
array('my.type', 'form.type'),
188+
array('my.type_extension', 'form.type_extension', array('extended_type' => 'Symfony\Component\Form\Extension\Core\Type\FormType')),
189+
array('my.guesser', 'form.type_guesser'),
211190
);
212191
}
192+
193+
private function createContainerBuilder()
194+
{
195+
$container = new ContainerBuilder();
196+
$container->addCompilerPass(new FormPass());
197+
198+
return $container;
199+
}
200+
201+
private function createExtensionDefinition()
202+
{
203+
$definition = new Definition('Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension');
204+
$definition->setArguments(array(
205+
new ServiceLocatorArgument(array()),
206+
new IteratorArgument(array()),
207+
new IteratorArgument(array()),
208+
));
209+
210+
return $definition;
211+
}
213212
}
214213

215214
class FormPassTest_Type1 extends AbstractType

‎src/Symfony/Component/Form/DependencyInjection/FormPass.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/DependencyInjection/FormPass.php
+28-21Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,13 @@
1111

1212
namespace Symfony\Component\Form\DependencyInjection;
1313

14+
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
15+
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
1416
use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait;
1517
use Symfony\Component\DependencyInjection\ContainerBuilder;
1618
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
1719
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
20+
use Symfony\Component\DependencyInjection\Reference;
1821

1922
/**
2023
* Adds all services with the tags "form.type" and "form.type_guesser" as
@@ -47,28 +50,25 @@ public function process(ContainerBuilder $container)
4750

4851
$definition = $container->getDefinition($this->formExtensionService);
4952

53+
// Get service locator argument
54+
$servicesMap = array();
55+
$locator = $definition->getArgument(0);
56+
if ($locator instanceof ServiceLocatorArgument) {
57+
$servicesMap = $locator->getValues();
58+
}
59+
5060
// Builds an array with fully-qualified type class names as keys and service IDs as values
51-
$types = array();
5261
foreach ($container->findTaggedServiceIds($this->formTypeTag) as $serviceId => $tag) {
5362
$serviceDefinition = $container->getDefinition($serviceId);
54-
if (!$serviceDefinition->isPublic()) {
55-
throw new InvalidArgumentException(sprintf('The service "%s" must be public as form types are lazy-loaded.', $serviceId));
56-
}
57-
58-
// Support type access by FQCN
59-
$types[$serviceDefinition->getClass()] = $serviceId;
63+
// Add form type service to the service locator
64+
$servicesMap[$serviceId] = new Reference($serviceId);
65+
$servicesMap[$serviceDefinition->getClass()] = new Reference($serviceId);
6066
}
6167

62-
$definition->replaceArgument(1, $types);
63-
6468
$typeExtensions = array();
65-
6669
foreach ($this->findAndSortTaggedServices($this->formTypeExtensionTag, $container) as $reference) {
6770
$serviceId = (string) $reference;
6871
$serviceDefinition = $container->getDefinition($serviceId);
69-
if (!$serviceDefinition->isPublic()) {
70-
throw new InvalidArgumentException(sprintf('The service "%s" must be public as form type extensions are lazy-loaded.', $serviceId));
71-
}
7272

7373
$tag = $serviceDefinition->getTag($this->formTypeExtensionTag);
7474
if (isset($tag[0]['extended_type'])) {
@@ -80,16 +80,23 @@ public function process(ContainerBuilder $container)
8080
$typeExtensions[$extendedType][] = $serviceId;
8181
}
8282

83-
$definition->replaceArgument(2, $typeExtensions);
83+
$allExtensions = array();
84+
foreach ($typeExtensions as $extendedType => $extensions) {
85+
$allExtensions[$extendedType] = new IteratorArgument(array_map(
86+
function ($extensionId) {
87+
return new Reference($extensionId);
88+
},
89+
$extensions
90+
));
91+
}
8492

85-
$guessers = array_keys($container->findTaggedServiceIds($this->formTypeGuesserTag));
86-
foreach ($guessers as $serviceId) {
87-
$serviceDefinition = $container->getDefinition($serviceId);
88-
if (!$serviceDefinition->isPublic()) {
89-
throw new InvalidArgumentException(sprintf('The service "%s" must be public as form type guessers are lazy-loaded.', $serviceId));
90-
}
93+
$guessers = array();
94+
foreach (array_keys($container->findTaggedServiceIds($this->formTypeGuesserTag)) as $serviceId) {
95+
$guessers[] = new Reference($serviceId);
9196
}
9297

93-
$definition->replaceArgument(3, $guessers);
98+
$definition->replaceArgument(0, new ServiceLocatorArgument($servicesMap));
99+
$definition->replaceArgument(1, new IteratorArgument($allExtensions));
100+
$definition->replaceArgument(2, new IteratorArgument($guessers));
94101
}
95102
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.