8000 [Form] use new service locator in DependencyInjectionExtension class,… · symfony/symfony@0702a5b · GitHub
[go: up one dir, main page]

Skip to content

Commit 0702a5b

Browse 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 a1dbe04 commit 0702a5b

File tree

7 files changed

+321
-237
lines changed

7 files changed

+321
-237
lines changed

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

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,9 @@
3030

3131
<!-- DependencyInjectionExtension -->
3232
<service id="form.extension" class="Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension" public="false">
33-
<argument type="service" id="service_container" />
34-
<!-- All services with tag "form.type" are inserted here by FormPass -->
35-
<argument type="collection" />
36-
<!-- 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" />
33+
<argument type="service-locator" /><!-- All services with tag "form.type" are stored in a service locator by FormPass -->
34+
<argument type="collection" /><!-- All services with tag "form.type_extension" are stored here by FormPass -->
35+
<argument type="iterator" /><!-- All services with tag "form.type_guesser" are stored here by FormPass -->
4036
</service>
4137

4238
<!-- ValidatorTypeGuesser -->

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

Lines changed: 72 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,34 @@ 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->assertEquals(
53+
new ServiceLocatorArgument(array(
54+
__CLASS__.'_Type1' => new Reference('my.type1'),
55+
__CLASS__.'_Type2' => new Reference('my.type2'),
56+
)),
57+
$locator
58+
);
6359
}
6460

6561
/**
6662
* @dataProvider addTaggedTypeExtensionsDataProvider
6763
*/
6864
public function testAddTaggedTypeExtensions(array $extensions, array $expectedRegisteredExtensions)
6965
{
70-
$container = new ContainerBuilder();
71-
$container->addCompilerPass(new FormPass());
66+
$container = $this->createContainerBuilder();
7267

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);
68+
$container->setDefinition('form.extension', $this->createExtensionDefinition());
8169

8270
foreach ($extensions as $serviceId => $tag) {
8371
$container->register($serviceId, 'stdClass')->addTag('form.type_extension', $tag);
@@ -86,7 +74,7 @@ public function testAddTaggedTypeExtensions(array $extensions, array $expectedRe
8674
$container->compile();
8775

8876
$extDefinition = $container->getDefinition('form.extension');
89-
$this->assertSame($expectedRegisteredExtensions, $extDefinition->getArgument(2));
77+
$this->assertEquals($expectedRegisteredExtensions, $extDefinition->getArgument(1));
9078
}
9179

9280
/**
@@ -102,8 +90,11 @@ public function addTaggedTypeExtensionsDataProvider()
10290
'my.type_extension3' => array('extended_type' => 'type2'),
10391
),
10492
array(
105-
'type1' => array('my.type_extension1', 'my.type_extension2'),
106-
'type2' => array('my.type_extension3'),
93+
'type1' => new IteratorArgument(array(
94+
new Reference('my.type_extension1'),
95+
new Reference('my.type_extension2'),
96+
)),
97+
'type2' => new IteratorArgument(array(new Reference('my.type_extension3'))),
10798
),
10899
),
109100
array(
@@ -116,8 +107,16 @@ public function addTaggedTypeExtensionsDataProvider()
116107
'my.type_extension6' => array('extended_type' => 'type2', 'priority' => 1),
117108
),
118109
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'),
110+
'type1' => new IteratorArgument(array(
111+
new Reference('my.type_extension2'),
112+
new Reference('my.type_extension1'),
113+
new Reference('my.type_extension3'),
114+
)),
115+
'type2' => new IteratorArgument(array(
116+
new Reference('my.type_extension4'),
117+
new Reference('my.type_extension5'),
118+
new Reference('my.type_extension6'),
119+
)),
121120
),
122121
),
123122
);
@@ -129,17 +128,9 @@ public function addTaggedTypeExtensionsDataProvider()
129128
*/
130129
public function testAddTaggedFormTypeExtensionWithoutExtendedTypeAttribute()
131130
{
132-
$container = new ContainerBuilder();
133-
$container->addCompilerPass(new FormPass());
134-
135-
$extDefinition = new Definition('Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension', array(
136-
new Reference('service_container'),
137-
array(),
138-
array(),
139-
array(),
140-
));
131+
$container = $this->createContainerBuilder();
141132

142-
$container->setDefinition('form.extension', $extDefinition);
133+
$container->setDefinition('form.extension', $this->createExtensionDefinition());
143134
$container->register('my.type_extension', 'stdClass')
144135
->addTag('form.type_extension');
145136

@@ -148,73 +139,72 @@ public function testAddTaggedFormTypeExtensionWithoutExtendedTypeAttribute()
148139

149140
public function testAddTaggedGuessers()
150141
{
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-
));
142+
$container = $this->createContainerBuilder();
161143

162144
$definition1 = new Definition('stdClass');
163145
$definition1->addTag('form.type_guesser');
164146
$definition2 = new Definition('stdClass');
165147
$definition2->addTag('form.type_guesser');
166148

167-
$container->setDefinition('form.extension', $extDefinition);
149+
$container->setDefinition('form.extension', $this->createExtensionDefinition());
168150
$container->setDefinition('my.guesser1', $definition1);
169151
$container->setDefinition('my.guesser2', $definition2);
170152

171153
$container->compile();
172154

173155
$extDefinition = $container->getDefinition('form.extension');
174-
175-
$this->assertSame(array(
176-
'my.guesser1',
177-
'my.guesser2',
178-
), $extDefinition->getArgument(3));
156+
$iteratorArgument = $extDefinition->getArgument(2);
157+
158+
$this->assertEquals(
159+
new IteratorArgument(array(
160+
new Reference('my.guesser1'),
161+
new Reference('my.guesser2'),
162+
)),
163+
$iteratorArgument
164+
);
179165
}
180166

181167
/**
182168
* @dataProvider privateTaggedServicesProvider
183169
*/
184-
public function testPrivateTaggedServices($id, $tagName, $expectedExceptionMessage)
170+
public function testPrivateTaggedServices($id, $tagName, array $tagAttributes = array())
185171
{
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-
));
196-
197-
$container->setDefinition('form.extension', $extDefinition);
198-
$container->register($id, 'stdClass')->setPublic(false)->addTag($tagName);
172+
$container = $this->createContainerBuilder();
199173

200-
if (method_exists($this, 'expectException')) {
201-
$this->expectException('InvalidArgumentException');
202-
$this->expectExceptionMessage($expectedExceptionMessage);
203-
} else {
204-
$this->setExpectedException('InvalidArgumentException', $expectedExceptionMessage);
205-
}
174+
$container->setDefinition('form.extension', $this->createExtensionDefinition());
175+
$container->register($id, 'stdClass')->setPublic(false)->addTag($tagName, $tagAttributes);
206176

207177
$container->compile();
208178
}
209179

210180
public function privateTaggedServicesProvider()
211181
{
212182
return array(
213-
array('my.type', 'form.type', 'The service "my.type" must be public as form types are lazy-loaded'),
214-
array('my.type_extension', 'form.type_extension', 'The service "my.type_extension" must be public as form type extensions are lazy-loaded'),
215-
array('my.guesser', 'form.type_guesser', 'The service "my.guesser" must be public as form type guessers are lazy-loaded'),
183+
array('my.type', 'form.type'),
184+
array('my.type_extension', 'form.type_extension', array('extended_type' => 'Symfony\Component\Form\Extension\Core\Type\FormType')),
185+
array('my.guesser', 'form.type_guesser'),
216186
);
217187
}
188+
189+
private function createContainerBuilder()
190+
{
191+
$container = new ContainerBuilder();
192+
$container->addCompilerPass(new FormPass());
193+
194+
return $container;
195+
}
196+
197+
private function createExtensionDe 10000 finition()
198+
{
199+
$definition = new Definition('Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension');
200+
$definition->setArguments(array(
201+
new ServiceLocatorArgument(array()),
202+
new IteratorArgument(array()),
203+
new IteratorArgument(array()),
204+
));
205+
206+
return $definition;
207+
}
218208
}
219209

220210
class FormPassTest_Type1 extends AbstractType

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

Lines changed: 46 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,14 @@
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;
19+
use Symfony\Component\DependencyInjection\Definition;
1720
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
21+
use Symfony\Component\DependencyInjection\Reference;
1822

1923
/**
2024
* Adds all services with the tags "form.type" and "form.type_guesser" as
@@ -46,50 +50,69 @@ public function process(ContainerBuilder $container)
4650
}
4751

4852
$definition = $container->getDefinition($this->formExtensionService);
53+
$definition->replaceArgument(0, $this->processFormTypes($container, $definition));
54+
$definition->replaceArgument(1, $this->processFormTypeExtensions($container));
55+
$definition->replaceArgument(2, $this->processFormTypeGuessers($container));
56+
}
57+
58+
private function processFormTypes(ContainerBuilder $container, Definition $definition)
59+
{
60+
// Get service locator argument
61+
$servicesMap = array();
62+
$locator = $definition->getArgument(0);
63+
if ($locator instanceof ServiceLocatorArgument) {
64+
$servicesMap = $locator->getValues();
65+
}
4966

5067
// Builds an array with fully-qualified type class names as keys and service IDs as values
51-
$types = array();
5268
foreach ($container->findTaggedServiceIds($this->formTypeTag) as $serviceId => $tag) {
5369
$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;
70+
// Add form type service to the service locator
71+
$servicesMap[$serviceDefinition->getClass()] = new Reference($serviceId);
6072
}
6173

62-
$definition->replaceArgument(1, $types);
74+
return new ServiceLocatorArgument($servicesMap);
75+
}
6376

77+
private function processFormTypeExtensions(ContainerBuilder $container)
78+
{
6479
$typeExtensions = array();
65-
66-
foreach ($this->findAndSortTaggedServices($this->formTypeExtensionTag, $container) as $reference) {
67-
$serviceId = (string) $reference;
80+
foreach ($this->findAndSortTaggedServices($this->formTypeExtensionTag,
81+
$container) as $reference) {
82+
$serviceId = (string)$reference;
6883
$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-
}
7284

7385
$tag = $serviceDefinition->getTag($this->formTypeExtensionTag);
7486
if (isset($tag[0]['extended_type'])) {
7587
$extendedType = $tag[0]['extended_type'];
7688
} else {
77-
throw new InvalidArgumentException(sprintf('"%s" tagged services must have the extended type configured using the extended_type/extended-type attribute, none was configured for the "%s" service.', $this->formTypeExtensionTag, $serviceId));
89+
throw new InvalidArgumentException(sprintf('"%s" tagged services must have the extended type configured using the extended_type/extended-type attribute, none was configured for the "%s" service.',
90+
$this->formTypeExtensionTag, $serviceId));
7891
}
7992

8093
$typeExtensions[$extendedType][] = $serviceId;
8194
}
8295

83-
$definition->replaceArgument(2, $typeExtensions);
96+
$allExtensions = array();
97+
foreach ($typeExtensions as $extendedType => $extensions) {
98+
$allExtensions[$extendedType] = new IteratorArgument(array_map(
99+
function ($extensionId) {
100+
return new Reference($extensionId);
101+
},
102+
$extensions
103+
));
104+
}
84105

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-
}
106+
return $allExtensions;
107+
}
108+
109+
private function processFormTypeGuessers(ContainerBuilder $container)
110+
{
111+
$guessers = array();
112+
foreach (array_keys($container->findTaggedServiceIds($this->formTypeGuesserTag)) as $serviceId) {
113+
$guessers[] = new Reference($serviceId);
91114
}
92115

93-
$definition->replaceArgument(3, $guessers);
116+
return new IteratorArgument($guessers);
94117
}
95118
}

0 commit comments

Comments
 (0)
0