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

Skip to content

Commit e4beebf

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 3e9b8f3 commit e4beebf

File tree

7 files changed

+307
-230
lines changed

7 files changed

+307
-230
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: 74 additions & 77 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,36 @@ 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+
'my.type1' => new Reference('my.type1'),
57+
'my.type2' => new Reference('my.type2'),
58+
)),
59+
$locator
60+
);
6361
}
6462

6563
/**
6664
* @dataProvider addTaggedTypeExtensionsDataProvider
6765
*/
6866
public function testAddTaggedTypeExtensions(array $extensions, array $expectedRegisteredExtensions)
6967
{
70-
$container = new ContainerBuilder();
71-
$container->addCompilerPass(new FormPass());
68+
$container = $this->createContainerBuilder();
7269

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

8272
foreach ($extensions as $serviceId => $tag) {
8373
$container->register($serviceId, 'stdClass')->addTag('form.type_extension', $tag);
@@ -86,7 +76,7 @@ public function testAddTaggedTypeExtensions(array $extensions, array $expectedRe
8676
$container->compile();
8777

8878
$extDefinition = $container->getDefinition('form.extension');
89-
$this->assertSame($expectedRegisteredExtensions, $extDefinition->getArgument(2));
79+
$this->assertEquals($expectedRegisteredExtensions, $extDefinition->getArgument(1));
9080
}
9181

9282
/**
@@ -102,8 +92,11 @@ public function addTaggedTypeExtensionsDataProvider()
10292
'my.type_extension3' => array('extended_type' => 'type2'),
10393
),
10494
array(
105-
'type1' => array('my.type_extension1', 'my.type_extension2'),
106-
'type2' => array('my.type_extension3'),
95+
'type1' => new IteratorArgument(array(
96+
new Reference('my.type_extension1'),
97+
new Reference('my.type_extension2'),
98+
)),
99+
'type2' => new IteratorArgument(array(new Reference('my.type_extension3'))),
107100
),
108101
),
109102
array(
@@ -116,8 +109,16 @@ public function addTaggedTypeExtensionsDataProvider()
116109
'my.type_extension6' => array('extended_type' => 'type2', 'priority' => 1),
117110
),
118111
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'),
112+
'type1' => new IteratorArgument(array(
113+
new Reference('my.type_extension2'),
114+
new Reference('my.type_extension1'),
115+
new Reference('my.type_extension3'),
116+
)),
117+
'type2' => new IteratorArgument(array(
118+
new Reference('my.type_extension4'),
119+
new Reference('my.type_extension5'),
120+
new Reference('my.type_extension6'),
121+
)),
121122
),
122123
),
123124
);
@@ -129,17 +130,9 @@ public function addTaggedTypeExtensionsDataProvider()
129130
*/
130131
public function testAddTaggedFormTypeExtensionWithoutExtendedTypeAttribute()
131132
{
132-
$container = new ContainerBuilder();
133-
$container->addCompilerPass(new FormPass());
133+
$container = $this->createContainerBuilder();
134134

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

@@ -148,68 +141,72 @@ public function testAddTaggedFormTypeExtensionWithoutExtendedTypeAttribute()
148141

149142
public function testAddTaggedGuessers()
150143
{
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-
));
144+
$container = $this->createContainerBuilder();
161145

162146
$definition1 = new Definition('stdClass');
163147
$definition1->addTag('form.type_guesser');
164148
$definition2 = new Definition('stdClass');
165149
$definition2->addTag('form.type_guesser');
166150

167-
$container->setDefinition('form.extension', $extDefinition);
151+
$container->setDefinition('form.extension', $this->createExtensionDefinition());
168152
$container->setDefinition('my.guesser1', $definition1);
169153
$container->setDefinition('my.guesser2', $definition2);
170154

171155
$container->compile();
172156

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

181169
/**
182170
* @dataProvider privateTaggedServicesProvider
183171
*/
184-
public function testPrivateTaggedServices($id, $tagName, $expectedExceptionMessage)
172+
public function testPrivateTaggedServices($id, $tagName, array $tagAttributes = array())
185173
{
186-
$container = new ContainerBuilder();
187-
$container->addCompilerPass(new FormPass());
174+
$container = $this->createContainerBuilder();
188175

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);
199-
200-
$this->setExpectedException('\InvalidArgumentException', $expectedExceptionMessage);
176+
$container->setDefinition('form.extension', $this->createExtensionDefinition());
177+
$container->register($id, 'stdClass')->setPublic(false)->addTag($tagName, $tagAttributes);
201178

202179
$container->compile();
203180
}
204181

205182
public function privateTaggedServicesProvider()
206183
{
207184
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'),
185+
array('my.type', 'form.type'),
186+
array('my.type_extension', 'form.type_extension', array('extended_type' => 'Symfony\Component\Form\Extension\Core\Type\FormType')),
187+
array('my.guesser', 'form.type_guesser'),
211188
);
212189
}
190+
191+
private function createContainerBuilder()
192+
{
193+
$container = new ContainerBuilder();
194+
$container->addCompilerPass(new FormPass());
195+
196+
return $container;
197+
}
198+
199+
private function createExtensionDefinition()
200+
{
201+
$definition = new Definition('Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension');
202+
$definition->setArguments(array(
203+
new ServiceLocatorArgument(array()),
204+
new IteratorArgument(array()),
205+
new IteratorArgument(array()),
206+
));
207+
208+
return $definition;
209+
}
213210
}
214211

215212
class FormPassTest_Type1 extends AbstractType

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

Lines 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, $allExtensions);
100+
$definition->replaceArgument(2, new IteratorArgument($guessers));
94101
}
95102
}

0 commit comments

Comments
 (0)
0