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 0702a5b

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 a1dbe04 commit 0702a5b
Copy full SHA for 0702a5b

File tree

7 files changed

+321
-237
lines changed
Filter options

7 files changed

+321
-237
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-7Lines 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

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/FormPassTest.php
+72-82Lines 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 createExtensionDefinition()
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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/DependencyInjection/FormPass.php
+46-23Lines 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)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.