[Form] Fixed: FormTypeInterface::getParent() supports returning FormTypeInterface instances again
This commit is contained in:
parent
7a233bc7a6
commit
a38232ae0e
@ -80,16 +80,7 @@ class FormFactory implements FormFactoryInterface
|
||||
}
|
||||
|
||||
if ($type instanceof FormTypeInterface) {
|
||||
// An unresolved type instance was passed. Type extensions
|
||||
// are not supported for these. If you want to use type
|
||||
// extensions, you should create form extensions or register
|
||||
// your type in the Dependency Injection configuration instead.
|
||||
$parentType = $type->getParent();
|
||||
$type = $this->resolvedTypeFactory->createResolvedType(
|
||||
$type,
|
||||
array(),
|
||||
$parentType ? $this->registry->getType($parentType) : null
|
||||
);
|
||||
$type = $this->resolveType($type);
|
||||
} elseif (is_string($type)) {
|
||||
$type = $this->registry->getType($type);
|
||||
} elseif (!$type instanceof ResolvedFormTypeInterface) {
|
||||
@ -196,4 +187,32 @@ class FormFactory implements FormFactoryInterface
|
||||
{
|
||||
return $this->registry->getType($name)->getInnerType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps a type into a ResolvedFormTypeInterface implementation and connects
|
||||
* it with its parent type.
|
||||
*
|
||||
* @param FormTypeInterface $type The type to resolve.
|
||||
*
|
||||
* @return ResolvedFormTypeInterface The resolved type.
|
||||
*/
|
||||
private function resolveType(FormTypeInterface $type)
|
||||
{
|
||||
$parentType = $type->getParent();
|
||||
|
||||
if ($parentType instanceof FormTypeInterface) {
|
||||
$parentType = $this->resolveType($parentType);
|
||||
} elseif (null !== $parentType) {
|
||||
$parentType = $this->registry->getType($parentType);
|
||||
}
|
||||
|
||||
return $this->resolvedTypeFactory->createResolvedType(
|
||||
$type,
|
||||
// Type extensions are not supported for unregistered type instances,
|
||||
// i.e. type instances that are passed to the FormFactory directly,
|
||||
// nor for their parents, if getParent() also returns a type instance.
|
||||
array(),
|
||||
$parentType
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -95,27 +95,46 @@ class FormRegistry implements FormRegistryInterface
|
||||
throw new FormException(sprintf('Could not load type "%s"', $name));
|
||||
}
|
||||
|
||||
$parentType = $type->getParent();
|
||||
$typeExtensions = array();
|
||||
|
||||
foreach ($this->extensions as $extension) {
|
||||
/* @var FormExtensionInterface $extension */
|
||||
$typeExtensions = array_merge(
|
||||
$typeExtensions,
|
||||
$extension->getTypeExtensions($name)
|
||||
);
|
||||
}
|
||||
|
||||
$this->addType($this->resolvedTypeFactory->createResolvedType(
|
||||
$type,
|
||||
$typeExtensions,
|
||||
$parentType ? $this->getType($parentType) : null
|
||||
));
|
||||
$this->resolveAndAddType($type);
|
||||
}
|
||||
|
||||
return $this->types[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps a type into a ResolvedFormTypeInterface implementation and connects
|
||||
* it with its parent type.
|
||||
*
|
||||
* @param FormTypeInterface $type The type to resolve.
|
||||
*
|
||||
* @return ResolvedFormTypeInterface The resolved type.
|
||||
*/
|
||||
private function resolveAndAddType(FormTypeInterface $type)
|
||||
{
|
||||
$parentType = $type->getParent();
|
||||
|
||||
if ($parentType instanceof FormTypeInterface) {
|
||||
$this->resolveAndAddType($parentType);
|
||||
$parentType = $parentType->getName();
|
||||
}
|
||||
|
||||
$typeExtensions = array();
|
||||
|
||||
foreach ($this->extensions as $extension) {
|
||||
/* @var FormExtensionInterface $extension */
|
||||
$typeExtensions = array_merge(
|
||||
$typeExtensions,
|
||||
$extension->getTypeExtensions($type->getName())
|
||||
);
|
||||
}
|
||||
|
||||
$this->addType($this->resolvedTypeFactory->createResolvedType(
|
||||
$type,
|
||||
$typeExtensions,
|
||||
$parentType ? $this->getType($parentType) : null
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@ -78,7 +78,11 @@ interface FormTypeInterface
|
||||
/**
|
||||
* Returns the name of the parent type.
|
||||
*
|
||||
* @return string|null The name of the parent type if any, null otherwise.
|
||||
* You can also return a type instance from this method, although doing so
|
||||
* is discouraged because it leads to a performance penalty. The support
|
||||
* for returning type instances may be dropped from future releases.
|
||||
*
|
||||
* @return string|null|FormTypeInterface The name of the parent type if any, null otherwise.
|
||||
*/
|
||||
public function getParent();
|
||||
|
||||
|
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form\Tests\Fixtures;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormFactoryInterface;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
|
||||
|
||||
class FooSubTypeWithParentInstance extends AbstractType
|
||||
{
|
||||
public function getName()
|
||||
{
|
||||
return 'foo_sub_type_parent_instance';
|
||||
}
|
||||
|
||||
public function getParent()
|
||||
{
|
||||
return new FooType();
|
||||
}
|
||||
}
|
@ -21,6 +21,8 @@ use Symfony\Component\Form\Tests\Fixtures\Author;
|
||||
use Symfony\Component\Form\Tests\Fixtures\AuthorType;
|
||||
use Symfony\Component\Form\Tests\Fixtures\TestExtension;
|
||||
use Symfony\Component\Form\Tests\Fixtures\FooType;
|
||||
use Symfony\Component\Form\Tests\Fixtures\FooSubType;
|
||||
use Symfony\Component\Form\Tests\Fixtures\FooSubTypeWithParentInstance;
|
||||
use Symfony\Component\Form\Tests\Fixtures\FooTypeBarExtension;
|
||||
use Symfony\Component\Form\Tests\Fixtures\FooTypeBazExtension;
|
||||
|
||||
@ -139,7 +141,7 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase
|
||||
public function testCreateNamedBuilderWithTypeInstance()
|
||||
{
|
||||
$options = array('a' => '1', 'b' => '2');
|
||||
$type = $this->getMockType();
|
||||
$type = new FooType();
|
||||
$resolvedType = $this->getMockResolvedType();
|
||||
|
||||
$this->resolvedTypeFactory->expects($this->once())
|
||||
@ -155,6 +157,56 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertSame('BUILDER', $this->factory->createNamedBuilder('name', $type, null, $options));
|
||||
}
|
||||
|
||||
public function testCreateNamedBuilderWithTypeInstanceWithParentType()
|
||||
{
|
||||
$options = array('a' => '1', 'b' => '2');
|
||||
$type = new FooSubType();
|
||||
$resolvedType = $this->getMockResolvedType();
|
||||
$parentResolvedType = $this->getMockResolvedType();
|
||||
|
||||
$this->registry->expects($this->once())
|
||||
->method('getType')
|
||||
->with('foo')
|
||||
->will($this->returnValue($parentResolvedType));
|
||||
|
||||
$this->resolvedTypeFactory->expects($this->once())
|
||||
->method('createResolvedType')
|
||||
->with($type, array(), $parentResolvedType)
|
||||
->will($this->returnValue($resolvedType));
|
||||
|
||||
$resolvedType->expects($this->once())
|
||||
->method('createBuilder')
|
||||
->with($this->factory, 'name', $options)
|
||||
->will($this->returnValue('BUILDER'));
|
||||
|
||||
$this->assertSame('BUILDER', $this->factory->createNamedBuilder('name', $type, null, $options));
|
||||
}
|
||||
|
||||
public function testCreateNamedBuilderWithTypeInstanceWithParentTypeInstance()
|
||||
{
|
||||
$options = array('a' => '1', 'b' => '2');
|
||||
$type = new FooSubTypeWithParentInstance();
|
||||
$resolvedType = $this->getMockResolvedType();
|
||||
$parentResolvedType = $this->getMockResolvedType();
|
||||
|
||||
$this->resolvedTypeFactory->expects($this->at(0))
|
||||
->method('createResolvedType')
|
||||
->with($type->getParent())
|
||||
->will($this->returnValue($parentResolvedType));
|
||||
|
||||
$this->resolvedTypeFactory->expects($this->at(1))
|
||||
->method('createResolvedType')
|
||||
->with($type, array(), $parentResolvedType)
|
||||
->will($this->returnValue($resolvedType));
|
||||
|
||||
$resolvedType->expects($this->once())
|
||||
->method('createBuilder')
|
||||
->with($this->factory, 'name', $options)
|
||||
->will($this->returnValue('BUILDER'));
|
||||
|
||||
$this->assertSame('BUILDER', $this->factory->createNamedBuilder('name', $type, null, $options));
|
||||
}
|
||||
|
||||
public function testCreateNamedBuilderWithResolvedTypeInstance()
|
||||
{
|
||||
$options = array('a' => '1', 'b' => '2');
|
||||
|
@ -12,6 +12,7 @@
|
||||
namespace Symfony\Component\Form;
|
||||
|
||||
use Symfony\Component\Form\Tests\Fixtures\TestExtension;
|
||||
use Symfony\Component\Form\Tests\Fixtures\FooSubTypeWithParentInstance;
|
||||
use Symfony\Component\Form\Tests\Fixtures\FooSubType;
|
||||
use Symfony\Component\Form\Tests\Fixtures\FooTypeBazExtension;
|
||||
use Symfony\Component\Form\Tests\Fixtures\FooTypeBarExtension;
|
||||
@ -153,6 +154,35 @@ class FormRegistryTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertSame($resolvedType, $this->registry->getType('foo_sub_type'));
|
||||
}
|
||||
|
||||
public function testGetTypeConnectsParentIfGetParentReturnsInstance()
|
||||
{
|
||||
$type = new FooSubTypeWithParentInstance();
|
||||
$parentResolvedType = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface');
|
||||
$resolvedType = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface');
|
||||
|
||||
$this->extension1->addType($type);
|
||||
|
||||
$this->resolvedTypeFactory->expects($this->at(0))
|
||||
->method('createResolvedType')
|
||||
->with($this->isInstanceOf('Symfony\Component\Form\Tests\Fixtures\FooType'))
|
||||
->will($this->returnValue($parentResolvedType));
|
||||
|
||||
$this->resolvedTypeFactory->expects($this->at(1))
|
||||
->method('createResolvedType')
|
||||
->with($type, array(), $parentResolvedType)
|
||||
->will($this->returnValue($resolvedType));
|
||||
|
||||
$parentResolvedType->expects($this->any())
|
||||
->method('getName')
|
||||
->will($this->returnValue('foo'));
|
||||
|
||||
$resolvedType->expects($this->any())
|
||||
->method('getName')
|
||||
->will($this->returnValue('foo_sub_type_parent_instance'));
|
||||
|
||||
$this->assertSame($resolvedType, $this->registry->getType('foo_sub_type_parent_instance'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Symfony\Component\Form\Exception\FormException
|
||||
*/
|
||||
|
Reference in New Issue
Block a user