Skip to content

Commit e33fcd2

Browse files
committed
[Form] Added default implementation of AbstractType::getName()
1 parent dd7583d commit e33fcd2

File tree

6 files changed

+283
-6
lines changed

6 files changed

+283
-6
lines changed

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/FormPass.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,13 @@ public function process(ContainerBuilder $container)
3434
$types = array();
3535

3636
foreach ($container->findTaggedServiceIds('form.type') as $serviceId => $tag) {
37-
$alias = isset($tag[0]['alias'])
38-
? $tag[0]['alias']
39-
: $serviceId;
37+
if (isset($tag[0]['alias'])) {
38+
$alias = $tag[0]['alias'];
39+
} else {
40+
// The alias defaults to the FQCN
41+
$serviceDefinition = $container->getDefinition($serviceId);
42+
$alias = $serviceDefinition->getClass();
43+
}
4044

4145
// Flip, because we want tag aliases (= type identifiers) as keys
4246
$types[$alias] = $serviceId;
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;
13+
14+
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\FormPass;
15+
use Symfony\Component\DependencyInjection\ContainerBuilder;
16+
use Symfony\Component\DependencyInjection\Definition;
17+
use Symfony\Component\DependencyInjection\Reference;
18+
use Symfony\Component\Form\AbstractType;
19+
20+
/**
21+
* @author Bernhard Schussek <bschussek@gmail.com>
22+
*/
23+
class FormPassTest extends \PHPUnit_Framework_TestCase
24+
{
25+
public function testDoNothingIfFormExtensionNotLoaded()
26+
{
27+
$container = new ContainerBuilder();
28+
$container->addCompilerPass(new FormPass());
29+
30+
$container->compile();
31+
32+
$this->assertFalse($container->hasDefinition('form.extension'));
33+
}
34+
35+
public function testAddTaggedTypes()
36+
{
37+
$container = new ContainerBuilder();
38+
$container->addCompilerPass(new FormPass());
39+
40+
$extDefinition = new Definition('Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension');
41+
$extDefinition->setArguments(array(
42+
new Reference('service_container'),
43+
array(),
44+
array(),
45+
array(),
46+
));
47+
48+
$definition1 = new Definition(__CLASS__.'_Type1');
49+
$definition1->addTag('form.type');
50+
$definition2 = new Definition(__CLASS__.'_Type2');
51+
$definition2->addTag('form.type', array('alias' => 'mytype2'));
52+
53+
$container->setDefinition('form.extension', $extDefinition);
54+
$container->setDefinition('my.type1', $definition1);
55+
$container->setDefinition('my.type2', $definition2);
56+
57+
$container->compile();
58+
59+
$extDefinition = $container->getDefinition('form.extension');
60+
61+
$this->assertSame(array(
62+
__CLASS__.'_Type1' => 'my.type1',
63+
'mytype2' => 'my.type2',
64+
), $extDefinition->getArgument(1));
65+
}
66+
67+
public function testAddTaggedTypeExtensions()
68+
{
69+
$container = new ContainerBuilder();
70+
$container->addCompilerPass(new FormPass());
71+
72+
$extDefinition = new Definition('Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension');
73+
$extDefinition->setArguments(array(
74+
new Reference('service_container'),
75+
array(),
76+
array(),
77+
array(),
78+
));
79+
80+
$definition1 = new Definition('stdClass');
81+
$definition1->addTag('form.type_extension', array('alias' => 'type1'));
82+
$definition2 = new Definition('stdClass');
83+
$definition2->addTag('form.type_extension', array('alias' => 'type1'));
84+
$definition3 = new Definition('stdClass');
85+
$definition3->addTag('form.type_extension', array('alias' => 'type2'));
86+
87+
$container->setDefinition('form.extension', $extDefinition);
88+
$container->setDefinition('my.type_extension1', $definition1);
89+
$container->setDefinition('my.type_extension2', $definition2);
90+
$container->setDefinition('my.type_extension3', $definition3);
91+
92+
$container->compile();
93+
94+
$extDefinition = $container->getDefinition('form.extension');
95+
96+
$this->assertSame(array(
97+
'type1' => array(
98+
'my.type_extension1',
99+
'my.type_extension2',
100+
),
101+
'type2' => array(
102+
'my.type_extension3',
103+
),
104+
), $extDefinition->getArgument(2));
105+
}
106+
107+
public function testAddTaggedGuessers()
108+
{
109+
$container = new ContainerBuilder();
110+
$container->addCompilerPass(new FormPass());
111+
112+
$extDefinition = new Definition('Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension');
113+
$extDefinition->setArguments(array(
114+
new Reference('service_container'),
115+
array(),
116+
array(),
117+
array(),
118+
));
119+
120+
$definition1 = new Definition('stdClass');
121+
$definition1->addTag('form.type_guesser');
122+
$definition2 = new Definition('stdClass');
123+
$definition2->addTag('form.type_guesser');
124+
125+
$container->setDefinition('form.extension', $extDefinition);
126+
$container->setDefinition('my.guesser1', $definition1);
127+
$container->setDefinition('my.guesser2', $definition2);
128+
129+
$container->compile();
130+
131+
$extDefinition = $container->getDefinition('form.extension');
132+
133+
$this->assertSame(array(
134+
'my.guesser1',
135+
'my.guesser2',
136+
), $extDefinition->getArgument(3));
137+
}
138+
}
139+
140+
class FormPassTest_Type1 extends AbstractType
141+
{
142+
}
143+
144+
class FormPassTest_Type2 extends AbstractType
145+
{
146+
}

src/Symfony/Component/Form/AbstractType.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,14 @@ public function configureOptions(OptionsResolver $resolver)
6161
{
6262
}
6363

64+
/**
65+
* {@inheritdoc}
66+
*/
67+
public function getName()
68+
{
69+
return get_class($this);
70+
}
71+
6472
/**
6573
* {@inheritdoc}
6674
*/

src/Symfony/Component/Form/FormFactory.php

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,23 @@ public function createForProperty($class, $property, $data = null, array $option
6060
*/
6161
public function createBuilder($type = 'form', $data = null, array $options = array())
6262
{
63-
$name = $type instanceof FormTypeInterface || $type instanceof ResolvedFormTypeInterface
64-
? $type->getName()
65-
: $type;
63+
if (!$type instanceof FormTypeInterface && !$type instanceof ResolvedFormTypeInterface) {
64+
$type = $this->registry->getType($type);
65+
}
66+
67+
$typeName = $type->getName();
68+
69+
if (false === ($pos = strrpos($typeName, '\\'))) {
70+
// No FQCN - leave unchanged for BC
71+
$name = $typeName;
72+
} else {
73+
// FQCN - strip namespace and "Type" suffix
74+
$name = strtolower(substr($typeName, $pos + 1));
75+
76+
if ('type' === substr($name, -4)) {
77+
$name = substr($name, 0, -4);
78+
}
79+
}
6680

6781
return $this->createNamedBuilder($name, $type, $data, $options);
6882
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Form\Tests;
13+
14+
use Symfony\Component\Form\AbstractType;
15+
16+
/**
17+
* @author Bernhard Schussek <bschussek@gmail.com>
18+
*/
19+
class AbstractTypeTest extends \PHPUnit_Framework_TestCase
20+
{
21+
public function testGetName()
22+
{
23+
$type = new AbstractTypeTest_Type();
24+
25+
$this->assertSame('Symfony\Component\Form\Tests\AbstractTypeTest_Type', $type->getName());
26+
}
27+
}
28+
29+
class AbstractTypeTest_Type extends AbstractType
30+
{
31+
}

src/Symfony/Component/Form/Tests/FormFactoryTest.php

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,10 @@ public function testCreateUsesTypeNameIfTypeGivenAsString()
287287
$resolvedOptions = array('a' => '2', 'b' => '3');
288288
$resolvedType = $this->getMockResolvedType();
289289

290+
$resolvedType->expects($this->once())
291+
->method('getName')
292+
->willReturn('TYPE');
293+
290294
$this->registry->expects($this->once())
291295
->method('getType')
292296
->with('TYPE')
@@ -312,6 +316,76 @@ public function testCreateUsesTypeNameIfTypeGivenAsString()
312316
$this->assertSame('FORM', $this->factory->create('TYPE', null, $options));
313317
}
314318

319+
public function testCreateStripsNamespaceOffTypeName()
320+
{
321+
$options = array('a' => '1', 'b' => '2');
322+
$resolvedOptions = array('a' => '2', 'b' => '3');
323+
$resolvedType = $this->getMockResolvedType();
324+
325+
$resolvedType->expects($this->once())
326+
->method('getName')
327+
->willReturn('Vendor\Name\Space\UserForm');
328+
329+
$this->registry->expects($this->once())
330+
->method('getType')
331+
->with('TYPE')
332+
->will($this->returnValue($resolvedType));
333+
334+
$resolvedType->expects($this->once())
335+
->method('createBuilder')
336+
->with($this->factory, 'userform', $options)
337+
->will($this->returnValue($this->builder));
338+
339+
$this->builder->expects($this->any())
340+
->method('getOptions')
341+
->will($this->returnValue($resolvedOptions));
342+
343+
$resolvedType->expects($this->once())
344+
->method('buildForm')
345+
->with($this->builder, $resolvedOptions);
346+
347+
$this->builder->expects($this->once())
348+
->method('getForm')
349+
->will($this->returnValue('FORM'));
350+
351+
$this->assertSame('FORM', $this->factory->create('TYPE', null, $options));
352+
}
353+
354+
public function testCreateStripsTypeSuffixOffTypeName()
355+
{
356+
$options = array('a' => '1', 'b' => '2');
357+
$resolvedOptions = array('a' => '2', 'b' => '3');
358+
$resolvedType = $this->getMockResolvedType();
359+
360+
$resolvedType->expects($this->once())
361+
->method('getName')
362+
->willReturn('Vendor\Name\Space\UserType');
363+
364+
$this->registry->expects($this->once())
365+
->method('getType')
366+
->with('TYPE')
367+
->will($this->returnValue($resolvedType));
368+
369+
$resolvedType->expects($this->once())
370+
->method('createBuilder')
371+
->with($this->factory, 'user', $options)
372+
->will($this->returnValue($this->builder));
373+
374+
$this->builder->expects($this->any())
375+
->method('getOptions')
376+
->will($this->returnValue($resolvedOptions));
377+
378+
$resolvedType->expects($this->once())
379+
->method('buildForm')
380+
->with($this->builder, $resolvedOptions);
381+
382+
$this->builder->expects($this->once())
383+
->method('getForm')
384+
->will($this->returnValue('FORM'));
385+
386+
$this->assertSame('FORM', $this->factory->create('TYPE', null, $options));
387+
}
388+
315389
public function testCreateUsesTypeNameIfTypeGivenAsObject()
316390
{
317391
$options = array('a' => '1', 'b' => '2');

0 commit comments

Comments
 (0)