[Form] Decoupled methods of ResolvedFormType so that they can be overridden individually by decorators

This commit is contained in:
Bernhard Schussek 2013-09-17 11:39:17 +02:00
parent a994a5d410
commit 56d78eda56
8 changed files with 437 additions and 196 deletions

View File

@ -412,7 +412,16 @@ class Button implements \IteratorAggregate, FormInterface
$parent = $this->parent->createView();
}
return $this->config->getType()->createView($this, $parent);
$type = $this->config->getType();
$options = $this->config->getOptions();
$view = $type->createView($this, $parent);
$type->buildView($view, $this, $options);
$type->finishView($view, $this, $options);
return $view;
}
/**

View File

@ -969,7 +969,23 @@ class Form implements \IteratorAggregate, FormInterface
$parent = $this->parent->createView();
}
return $this->config->getType()->createView($this, $parent);
$type = $this->config->getType();
$options = $this->config->getOptions();
// The methods createView(), buildView() and finishView() are called
// explicitly here in order to be able to override either of them
// in a custom resolved form type.
$view = $type->createView($this, $parent);
$type->buildView($view, $this, $options);
foreach ($this->children as $name => $child) {
$view->children[$name] = $child->createView($view);
}
$type->finishView($view, $this, $options);
return $view;
}
/**

View File

@ -84,7 +84,13 @@ class FormFactory implements FormFactoryInterface
throw new UnexpectedTypeException($type, 'string, Symfony\Component\Form\ResolvedFormTypeInterface or Symfony\Component\Form\FormTypeInterface');
}
return $type->createBuilder($this, $name, $options);
$builder = $type->createBuilder($this, $name, $options);
// Explicitly call buildForm() in order to be able to override either
// createBuilder() or buildForm() in the resolved form type
$type->buildForm($builder, $builder->getOptions());
return $builder;
}
/**

View File

@ -114,8 +114,6 @@ class ResolvedFormType implements ResolvedFormTypeInterface
$builder = $this->newBuilder($name, $dataClass, $factory, $options);
$builder->setType($this);
$this->buildForm($builder, $options);
return $builder;
}
@ -124,28 +122,12 @@ class ResolvedFormType implements ResolvedFormTypeInterface
*/
public function createView(FormInterface $form, FormView $parent = null)
{
$options = $form->getConfig()->getOptions();
$view = $this->newView($parent);
$this->buildView($view, $form, $options);
foreach ($form as $name => $child) {
/* @var FormInterface $child */
$view->children[$name] = $child->createView($view);
}
$this->finishView($view, $form, $options);
return $view;
return $this->newView($parent);
}
/**
* Configures a form builder for the type hierarchy.
*
* This method is protected in order to allow implementing classes
* to change or call it in re-implementations of {@link createBuilder()}.
*
* @param FormBuilderInterface $builder The builder to configure.
* @param array $options The options used for the configuration.
*/
@ -166,10 +148,7 @@ class ResolvedFormType implements ResolvedFormTypeInterface
/**
* Configures a form view for the type hierarchy.
*
* This method is protected in order to allow implementing classes
* to change or call it in re-implementations of {@link createView()}.
*
* It is called before the children of the view are built.
* This method is called before the children of the view are built.
*
* @param FormView $view The form view to configure.
* @param FormInterface $form The form corresponding to the view.
@ -192,10 +171,7 @@ class ResolvedFormType implements ResolvedFormTypeInterface
/**
* Finishes a form view for the type hierarchy.
*
* This method is protected in order to allow implementing classes
* to change or call it in re-implementations of {@link createView()}.
*
* It is called after the children of the view have been built.
* This method is called after the children of the view have been built.
*
* @param FormView $view The form view to configure.
* @param FormInterface $form The form corresponding to the view.
@ -218,9 +194,6 @@ class ResolvedFormType implements ResolvedFormTypeInterface
/**
* Returns the configured options resolver used for this type.
*
* This method is protected in order to allow implementing classes
* to change or call it in re-implementations of {@link createBuilder()}.
*
* @return \Symfony\Component\OptionsResolver\OptionsResolverInterface The options resolver.
*/
public function getOptionsResolver()

View File

@ -60,9 +60,9 @@ abstract class AbstractFormTest extends \PHPUnit_Framework_TestCase
*
* @return FormBuilder
*/
protected function getBuilder($name = 'name', EventDispatcherInterface $dispatcher = null, $dataClass = null)
protected function getBuilder($name = 'name', EventDispatcherInterface $dispatcher = null, $dataClass = null, array $options = array())
{
return new FormBuilder($name, $dataClass, $dispatcher ?: $this->dispatcher, $this->factory);
return new FormBuilder($name, $dataClass, $dispatcher ?: $this->dispatcher, $this->factory, $options);
}
/**

View File

@ -15,6 +15,7 @@ use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper;
use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\Forms;
use Symfony\Component\Form\FormView;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\Form\Tests\Fixtures\FixedDataTransformer;
@ -806,6 +807,65 @@ class CompoundFormTest extends AbstractFormTest
$this->assertEquals("name:\n ERROR: Error!\nfoo:\n No errors\n", $parent->getErrorsAsString());
}
// Basic cases are covered in SimpleFormTest
public function testCreateViewWithChildren()
{
$type = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface');
$options = array('a' => 'Foo', 'b' => 'Bar');
$field1 = $this->getMockForm('foo');
$field2 = $this->getMockForm('bar');
$view = new FormView();
$field1View = new FormView();
$field2View = new FormView();
$this->form = $this->getBuilder('form', null, null, $options)
->setCompound(true)
->setDataMapper($this->getDataMapper())
->setType($type)
->getForm();
$this->form->add($field1);
$this->form->add($field2);
$test = $this;
$assertChildViewsEqual = function (array $childViews) use ($test) {
return function (FormView $view) use ($test, $childViews) {
/* @var \PHPUnit_Framework_TestCase $test */
$test->assertSame($childViews, $view->children);
};
};
// First create the view
$type->expects($this->once())
->method('createView')
->will($this->returnValue($view));
// Then build it for the form itself
$type->expects($this->once())
->method('buildView')
->with($view, $this->form, $options)
->will($this->returnCallback($assertChildViewsEqual(array())));
// Then add the first child form
$field1->expects($this->once())
->method('createView')
->will($this->returnValue($field1View));
// Then the second child form
$field2->expects($this->once())
->method('createView')
->will($this->returnValue($field2View));
// Again build the view for the form itself. This time the child views
// exist.
$type->expects($this->once())
->method('finishView')
->with($view, $this->form, $options)
->will($this->returnCallback($assertChildViewsEqual(array('foo' => $field1View, 'bar' => $field2View))));
$this->assertSame($view, $this->form->createView());
}
protected function createForm()
{
return $this->getBuilder()

View File

@ -46,6 +46,11 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase
*/
private $resolvedTypeFactory;
/**
* @var \PHPUnit_Framework_MockObject_MockObject
*/
private $builder;
/**
* @var FormFactory
*/
@ -57,6 +62,7 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase
$this->guesser1 = $this->getMock('Symfony\Component\Form\FormTypeGuesserInterface');
$this->guesser2 = $this->getMock('Symfony\Component\Form\FormTypeGuesserInterface');
$this->registry = $this->getMock('Symfony\Component\Form\FormRegistryInterface');
$this->builder = $this->getMock('Symfony\Component\Form\Test\FormBuilderInterface');
$this->factory = new FormFactory($this->registry, $this->resolvedTypeFactory);
$this->registry->expects($this->any())
@ -70,6 +76,7 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase
public function testCreateNamedBuilderWithTypeName()
{
$options = array('a' => '1', 'b' => '2');
$resolvedOptions = array('a' => '2', 'b' => '3');
$resolvedType = $this->getMockResolvedType();
$this->registry->expects($this->once())
@ -80,14 +87,23 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase
$resolvedType->expects($this->once())
->method('createBuilder')
->with($this->factory, 'name', $options)
->will($this->returnValue('BUILDER'));
->will($this->returnValue($this->builder));
$this->assertSame('BUILDER', $this->factory->createNamedBuilder('name', 'type', null, $options));
$this->builder->expects($this->any())
->method('getOptions')
->will($this->returnValue($resolvedOptions));
$resolvedType->expects($this->once())
->method('buildForm')
->with($this->builder, $resolvedOptions);
$this->assertSame($this->builder, $this->factory->createNamedBuilder('name', 'type', null, $options));
}
public function testCreateNamedBuilderWithTypeInstance()
{
$options = array('a' => '1', 'b' => '2');
$resolvedOptions = array('a' => '2', 'b' => '3');
$type = new FooType();
$resolvedType = $this->getMockResolvedType();
@ -99,14 +115,23 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase
$resolvedType->expects($this->once())
->method('createBuilder')
->with($this->factory, 'name', $options)
->will($this->returnValue('BUILDER'));
->will($this->returnValue($this->builder));
$this->assertSame('BUILDER', $this->factory->createNamedBuilder('name', $type, null, $options));
$this->builder->expects($this->any())
->method('getOptions')
->will($this->returnValue($resolvedOptions));
$resolvedType->expects($this->once())
->method('buildForm')
->with($this->builder, $resolvedOptions);
$this->assertSame($this->builder, $this->factory->createNamedBuilder('name', $type, null, $options));
}
public function testCreateNamedBuilderWithTypeInstanceWithParentType()
{
$options = array('a' => '1', 'b' => '2');
$resolvedOptions = array('a' => '2', 'b' => '3');
$type = new FooSubType();
$resolvedType = $this->getMockResolvedType();
$parentResolvedType = $this->getMockResolvedType();
@ -124,14 +149,23 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase
$resolvedType->expects($this->once())
->method('createBuilder')
->with($this->factory, 'name', $options)
->will($this->returnValue('BUILDER'));
->will($this->returnValue($this->builder));
$this->assertSame('BUILDER', $this->factory->createNamedBuilder('name', $type, null, $options));
$this->builder->expects($this->any())
->method('getOptions')
->will($this->returnValue($resolvedOptions));
$resolvedType->expects($this->once())
->method('buildForm')
->with($this->builder, $resolvedOptions);
$this->assertSame($this->builder, $this->factory->createNamedBuilder('name', $type, null, $options));
}
public function testCreateNamedBuilderWithTypeInstanceWithParentTypeInstance()
{
$options = array('a' => '1', 'b' => '2');
$resolvedOptions = array('a' => '2', 'b' => '3');
$type = new FooSubTypeWithParentInstance();
$resolvedType = $this->getMockResolvedType();
$parentResolvedType = $this->getMockResolvedType();
@ -149,28 +183,46 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase
$resolvedType->expects($this->once())
->method('createBuilder')
->with($this->factory, 'name', $options)
->will($this->returnValue('BUILDER'));
->will($this->returnValue($this->builder));
$this->assertSame('BUILDER', $this->factory->createNamedBuilder('name', $type, null, $options));
$this->builder->expects($this->any())
->method('getOptions')
->will($this->returnValue($resolvedOptions));
$resolvedType->expects($this->once())
->method('buildForm')
->with($this->builder, $resolvedOptions);
$this->assertSame($this->builder, $this->factory->createNamedBuilder('name', $type, null, $options));
}
public function testCreateNamedBuilderWithResolvedTypeInstance()
{
$options = array('a' => '1', 'b' => '2');
$resolvedOptions = array('a' => '2', 'b' => '3');
$resolvedType = $this->getMockResolvedType();
$resolvedType->expects($this->once())
->method('createBuilder')
->with($this->factory, 'name', $options)
->will($this->returnValue('BUILDER'));
->will($this->returnValue($this->builder));
$this->assertSame('BUILDER', $this->factory->createNamedBuilder('name', $resolvedType, null, $options));
$this->builder->expects($this->any())
->method('getOptions')
->will($this->returnValue($resolvedOptions));
$resolvedType->expects($this->once())
->method('buildForm')
->with($this->builder, $resolvedOptions);
$this->assertSame($this->builder, $this->factory->createNamedBuilder('name', $resolvedType, null, $options));
}
public function testCreateNamedBuilderFillsDataOption()
{
$givenOptions = array('a' => '1', 'b' => '2');
$expectedOptions = array_merge($givenOptions, array('data' => 'DATA'));
$resolvedOptions = array('a' => '2', 'b' => '3', 'data' => 'DATA');
$resolvedType = $this->getMockResolvedType();
$this->registry->expects($this->once())
@ -181,14 +233,23 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase
$resolvedType->expects($this->once())
->method('createBuilder')
->with($this->factory, 'name', $expectedOptions)
->will($this->returnValue('BUILDER'));
->will($this->returnValue($this->builder));
$this->assertSame('BUILDER', $this->factory->createNamedBuilder('name', 'type', 'DATA', $givenOptions));
$this->builder->expects($this->any())
->method('getOptions')
->will($this->returnValue($resolvedOptions));
$resolvedType->expects($this->once())
->method('buildForm')
->with($this->builder, $resolvedOptions);
$this->assertSame($this->builder, $this->factory->createNamedBuilder('name', 'type', 'DATA', $givenOptions));
}
public function testCreateNamedBuilderDoesNotOverrideExistingDataOption()
{
$options = array('a' => '1', 'b' => '2', 'data' => 'CUSTOM');
$resolvedOptions = array('a' => '2', 'b' => '3', 'data' => 'CUSTOM');
$resolvedType = $this->getMockResolvedType();
$this->registry->expects($this->once())
@ -199,9 +260,17 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase
$resolvedType->expects($this->once())
->method('createBuilder')
->with($this->factory, 'name', $options)
->will($this->returnValue('BUILDER'));
->will($this->returnValue($this->builder));
$this->assertSame('BUILDER', $this->factory->createNamedBuilder('name', 'type', 'DATA', $options));
$this->builder->expects($this->any())
->method('getOptions')
->will($this->returnValue($resolvedOptions));
$resolvedType->expects($this->once())
->method('buildForm')
->with($this->builder, $resolvedOptions);
$this->assertSame($this->builder, $this->factory->createNamedBuilder('name', 'type', 'DATA', $options));
}
/**
@ -216,8 +285,8 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase
public function testCreateUsesTypeNameIfTypeGivenAsString()
{
$options = array('a' => '1', 'b' => '2');
$resolvedOptions = array('a' => '2', 'b' => '3');
$resolvedType = $this->getMockResolvedType();
$builder = $this->getMockFormBuilder();
$this->registry->expects($this->once())
->method('getType')
@ -227,9 +296,17 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase
$resolvedType->expects($this->once())
->method('createBuilder')
->with($this->factory, 'TYPE', $options)
->will($this->returnValue($builder));
->will($this->returnValue($this->builder));
$builder->expects($this->once())
$this->builder->expects($this->any())
->method('getOptions')
->will($this->returnValue($resolvedOptions));
$resolvedType->expects($this->once())
->method('buildForm')
->with($this->builder, $resolvedOptions);
$this->builder->expects($this->once())
->method('getForm')
->will($this->returnValue('FORM'));
@ -239,8 +316,8 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase
public function testCreateUsesTypeNameIfTypeGivenAsObject()
{
$options = array('a' => '1', 'b' => '2');
$resolvedOptions = array('a' => '2', 'b' => '3');
$resolvedType = $this->getMockResolvedType();
$builder = $this->getMockFormBuilder();
$resolvedType->expects($this->once())
->method('getName')
@ -249,9 +326,17 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase
$resolvedType->expects($this->once())
->method('createBuilder')
->with($this->factory, 'TYPE', $options)
->will($this->returnValue($builder));
->will($this->returnValue($this->builder));
$builder->expects($this->once())
$this->builder->expects($this->any())
->method('getOptions')
->will($this->returnValue($resolvedOptions));
$resolvedType->expects($this->once())
->method('buildForm')
->with($this->builder, $resolvedOptions);
$this->builder->expects($this->once())
->method('getForm')
->will($this->returnValue('FORM'));
@ -261,8 +346,8 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase
public function testCreateNamed()
{
$options = array('a' => '1', 'b' => '2');
$resolvedOptions = array('a' => '2', 'b' => '3');
$resolvedType = $this->getMockResolvedType();
$builder = $this->getMockFormBuilder();
$this->registry->expects($this->once())
->method('getType')
@ -272,9 +357,17 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase
$resolvedType->expects($this->once())
->method('createBuilder')
->with($this->factory, 'name', $options)
->will($this->returnValue($builder));
->will($this->returnValue($this->builder));
$builder->expects($this->once())
$this->builder->expects($this->any())
->method('getOptions')
->will($this->returnValue($resolvedOptions));
$resolvedType->expects($this->once())
->method('buildForm')
->with($this->builder, $resolvedOptions);
$this->builder->expects($this->once())
->method('getForm')
->will($this->returnValue('FORM'));
@ -294,9 +387,9 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase
->with('firstName', 'text', null, array())
->will($this->returnValue('builderInstance'));
$builder = $factory->createBuilderForProperty('Application\Author', 'firstName');
$this->builder = $factory->createBuilderForProperty('Application\Author', 'firstName');
$this->assertEquals('builderInstance', $builder);
$this->assertEquals('builderInstance', $this->builder);
}
public function testCreateBuilderForPropertyCreatesFormWithHighestConfidence()
@ -326,9 +419,9 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase
->with('firstName', 'password', null, array('max_length' => 7))
->will($this->returnValue('builderInstance'));
$builder = $factory->createBuilderForProperty('Application\Author', 'firstName');
$this->builder = $factory->createBuilderForProperty('Application\Author', 'firstName');
$this->assertEquals('builderInstance', $builder);
$this->assertEquals('builderInstance', $this->builder);
}
public function testCreateBuilderCreatesTextFormIfNoGuess()
@ -345,9 +438,9 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase
->with('firstName', 'text')
->will($this->returnValue('builderInstance'));
$builder = $factory->createBuilderForProperty('Application\Author', 'firstName');
$this->builder = $factory->createBuilderForProperty('Application\Author', 'firstName');
$this->assertEquals('builderInstance', $builder);
$this->assertEquals('builderInstance', $this->builder);
}
public function testOptionsCanBeOverridden()
@ -368,14 +461,14 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase
->with('firstName', 'text', null, array('max_length' => 11))
->will($this->returnValue('builderInstance'));
$builder = $factory->createBuilderForProperty(
$this->builder = $factory->createBuilderForProperty(
'Application\Author',
'firstName',
null,
array('max_length' => 11)
);
$this->assertEquals('builderInstance', $builder);
$this->assertEquals('builderInstance', $this->builder);
}
public function testCreateBuilderUsesMaxLengthIfFound()
@ -403,12 +496,12 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase
->with('firstName', 'text', null, array('max_length' => 20))
->will($this->returnValue('builderInstance'));
$builder = $factory->createBuilderForProperty(
$this->builder = $factory->createBuilderForProperty(
'Application\Author',
'firstName'
);
$this->assertEquals('builderInstance', $builder);
$this->assertEquals('builderInstance', $this->builder);
}
public function testCreateBuilderUsesRequiredSettingWithHighestConfidence()
@ -436,12 +529,12 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase
->with('firstName', 'text', null, array('required' => false))
->will($this->returnValue('builderInstance'));
$builder = $factory->createBuilderForProperty(
$this->builder = $factory->createBuilderForProperty(
'Application\Author',
'firstName'
);
$this->assertEquals('builderInstance', $builder);
$this->assertEquals('builderInstance', $this->builder);
}
public function testCreateBuilderUsesPatternIfFound()
@ -469,12 +562,12 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase
->with('firstName', 'text', null, array('pattern' => '[a-zA-Z]'))
->will($this->returnValue('builderInstance'));
$builder = $factory->createBuilderForProperty(
$this->builder = $factory->createBuilderForProperty(
'Application\Author',
'firstName'
);
$this->assertEquals('builderInstance', $builder);
$this->assertEquals('builderInstance', $this->builder);
}
private function getMockFactory(array $methods = array())
@ -494,9 +587,4 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase
{
return $this->getMock('Symfony\Component\Form\FormTypeInterface');
}
private function getMockFormBuilder()
{
return $this->getMock('Symfony\Component\Form\Test\FormBuilderInterface');
}
}

View File

@ -36,12 +36,71 @@ class ResolvedFormTypeTest extends \PHPUnit_Framework_TestCase
* @var \PHPUnit_Framework_MockObject_MockObject
*/
private $dataMapper;
private $parentType;
private $type;
private $extension1;
private $extension2;
private $parentResolvedType;
private $resolvedType;
protected function setUp()
{
$this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
$this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface');
$this->dataMapper = $this->getMock('Symfony\Component\Form\DataMapperInterface');
$this->parentType = $this->getMockFormType();
$this->type = $this->getMockFormType();
$this->extension1 = $this->getMockFormTypeExtension();
$this->extension2 = $this->getMockFormTypeExtension();
$this->parentResolvedType = new ResolvedFormType($this->parentType);
$this->resolvedType = new ResolvedFormType($this->type, array($this->extension1, $this->extension2), $this->parentResolvedType);
}
public function testGetOptionsResolver()
{
if (version_compare(\PHPUnit_Runner_Version::id(), '3.7', '<')) {
$this->markTestSkipped('This test requires PHPUnit 3.7.');
}
$test = $this;
$i = 0;
$assertIndexAndAddOption = function ($index, $option, $default) use (&$i, $test) {
return function (OptionsResolverInterface $resolver) use (&$i, $test, $index, $option, $default) {
/* @var \PHPUnit_Framework_TestCase $test */
$test->assertEquals($index, $i, 'Executed at index '.$index);
++$i;
$resolver->setDefaults(array($option => $default));
};
};
// First the default options are generated for the super type
$this->parentType->expects($this->once())
->method('setDefaultOptions')
->will($this->returnCallback($assertIndexAndAddOption(0, 'a', 'a_default')));
// The form type itself
$this->type->expects($this->once())
->method('setDefaultOptions')
->will($this->returnCallback($assertIndexAndAddOption(1, 'b', 'b_default')));
// And its extensions
$this->extension1->expects($this->once())
->method('setDefaultOptions')
->will($this->returnCallback($assertIndexAndAddOption(2, 'c', 'c_default')));
$this->extension2->expects($this->once())
->method('setDefaultOptions')
->will($this->returnCallback($assertIndexAndAddOption(3, 'd', 'd_default')));
$givenOptions = array('a' => 'a_custom', 'c' => 'c_custom');
$resolvedOptions = array('a' => 'a_custom', 'b' => 'b_default', 'c' => 'c_custom', 'd' => 'd_default');
$resolver = $this->resolvedType->getOptionsResolver();
$this->assertEquals($resolvedOptions, $resolver->resolve($givenOptions));
}
public function testCreateBuilder()
@ -50,13 +109,70 @@ class ResolvedFormTypeTest extends \PHPUnit_Framework_TestCase
$this->markTestSkipped('This test requires PHPUnit 3.7.');
}
$parentType = $this->getMockFormType();
$type = $this->getMockFormType();
$extension1 = $this->getMockFormTypeExtension();
$extension2 = $this->getMockFormTypeExtension();
$givenOptions = array('a' => 'a_custom', 'c' => 'c_custom');
$resolvedOptions = array('a' => 'a_custom', 'b' => 'b_default', 'c' => 'c_custom', 'd' => 'd_default');
$optionsResolver = $this->getMock('Symfony\Component\OptionsResolver\OptionsResolverInterface');
$parentResolvedType = new ResolvedFormType($parentType);
$resolvedType = new ResolvedFormType($type, array($extension1, $extension2), $parentResolvedType);
$this->resolvedType = $this->getMockBuilder('Symfony\Component\Form\ResolvedFormType')
->setConstructorArgs(array($this->type, array($this->extension1, $this->extension2), $this->parentResolvedType))
->setMethods(array('getOptionsResolver'))
->getMock();
$this->resolvedType->expects($this->once())
->method('getOptionsResolver')
->will($this->returnValue($optionsResolver));
$optionsResolver->expects($this->once())
->method('resolve')
->with($givenOptions)
->will($this->returnValue($resolvedOptions));
$factory = $this->getMockFormFactory();
$builder = $this->resolvedType->createBuilder($factory, 'name', $givenOptions);
$this->assertSame($this->resolvedType, $builder->getType());
$this->assertSame($resolvedOptions, $builder->getOptions());
$this->assertNull($builder->getDataClass());
}
public function testCreateBuilderWithDataClassOption()
{
if (version_compare(\PHPUnit_Runner_Version::id(), '3.7', '<')) {
$this->markTestSkipped('This test requires PHPUnit 3.7.');
}
$givenOptions = array('data_class' => 'Foo');
$resolvedOptions = array('data_class' => '\stdClass');
$optionsResolver = $this->getMock('Symfony\Component\OptionsResolver\OptionsResolverInterface');
$this->resolvedType = $this->getMockBuilder('Symfony\Component\Form\ResolvedFormType')
->setConstructorArgs(array($this->type, array($this->extension1, $this->extension2), $this->parentResolvedType))
->setMethods(array('getOptionsResolver'))
->getMock();
$this->resolvedType->expects($this->once())
->method('getOptionsResolver')
->will($this->returnValue($optionsResolver));
$optionsResolver->expects($this->once())
->method('resolve')
->with($givenOptions)
->will($this->returnValue($resolvedOptions));
$factory = $this->getMockFormFactory();
$builder = $this->resolvedType->createBuilder($factory, 'name', $givenOptions);
$this->assertSame($this->resolvedType, $builder->getType());
$this->assertSame($resolvedOptions, $builder->getOptions());
$this->assertSame('\stdClass', $builder->getDataClass());
}
public function testBuildForm()
{
if (version_compare(\PHPUnit_Runner_Version::id(), '3.7', '<')) {
$this->markTestSkipped('This test requires PHPUnit 3.7.');
}
$test = $this;
$i = 0;
@ -70,169 +186,142 @@ class ResolvedFormTypeTest extends \PHPUnit_Framework_TestCase
};
};
$assertIndexAndAddOption = function ($index, $option, $default) use ($assertIndex) {
$assertIndex = $assertIndex($index);
$options = array('a' => 'Foo', 'b' => 'Bar');
$builder = $this->getMock('Symfony\Component\Form\Test\FormBuilderInterface');
return function (OptionsResolverInterface $resolver) use ($assertIndex, $index, $option, $default) {
$assertIndex();
$resolver->setDefaults(array($option => $default));
};
};
// First the default options are generated for the super type
$parentType->expects($this->once())
->method('setDefaultOptions')
->will($this->returnCallback($assertIndexAndAddOption(0, 'a', 'a_default')));
// The form type itself
$type->expects($this->once())
->method('setDefaultOptions')
->will($this->returnCallback($assertIndexAndAddOption(1, 'b', 'b_default')));
// And its extensions
$extension1->expects($this->once())
->method('setDefaultOptions')
->will($this->returnCallback($assertIndexAndAddOption(2, 'c', 'c_default')));
$extension2->expects($this->once())
->method('setDefaultOptions')
->will($this->returnCallback($assertIndexAndAddOption(3, 'd', 'd_default')));
$givenOptions = array('a' => 'a_custom', 'c' => 'c_custom');
$resolvedOptions = array('a' => 'a_custom', 'b' => 'b_default', 'c' => 'c_custom', 'd' => 'd_default');
// Then the form is built for the super type
$parentType->expects($this->once())
// First the form is built for the super type
$this->parentType->expects($this->once())
->method('buildForm')
->with($this->anything(), $resolvedOptions)
->will($this->returnCallback($assertIndex(4)));
->with($builder, $options)
->will($this->returnCallback($assertIndex(0)));
// Then the type itself
$type->expects($this->once())
$this->type->expects($this->once())
->method('buildForm')
->with($this->anything(), $resolvedOptions)
->will($this->returnCallback($assertIndex(5)));
->with($builder, $options)
->will($this->returnCallback($assertIndex(1)));
// Then its extensions
$extension1->expects($this->once())
$this->extension1->expects($this->once())
->method('buildForm')
->with($this->anything(), $resolvedOptions)
->will($this->returnCallback($assertIndex(6)));
->with($builder, $options)
->will($this->returnCallback($assertIndex(2)));
$extension2->expects($this->once())
$this->extension2->expects($this->once())
->method('buildForm')
->with($this->anything(), $resolvedOptions)
->will($this->returnCallback($assertIndex(7)));
->with($builder, $options)
->will($this->returnCallback($assertIndex(3)));
$factory = $this->getMockFormFactory();
$builder = $resolvedType->createBuilder($factory, 'name', $givenOptions);
$this->assertSame($resolvedType, $builder->getType());
$this->resolvedType->buildForm($builder, $options);
}
public function testCreateView()
{
$parentType = $this->getMockFormType();
$type = $this->getMockFormType();
$field1Type = $this->getMockFormType();
$field2Type = $this->getMockFormType();
$extension1 = $this->getMockFormTypeExtension();
$extension2 = $this->getMockFormTypeExtension();
$form = $this->getMock('Symfony\Component\Form\Test\FormInterface');
$parentResolvedType = new ResolvedFormType($parentType);
$resolvedType = new ResolvedFormType($type, array($extension1, $extension2), $parentResolvedType);
$field1ResolvedType = new ResolvedFormType($field1Type);
$field2ResolvedType = new ResolvedFormType($field2Type);
$view = $this->resolvedType->createView($form);
$this->assertInstanceOf('Symfony\Component\Form\FormView', $view);
$this->assertNull($view->parent);
}
public function testCreateViewWithParent()
{
$form = $this->getMock('Symfony\Component\Form\Test\FormInterface');
$parentView = $this->getMock('Symfony\Component\Form\FormView');
$view = $this->resolvedType->createView($form, $parentView);
$this->assertInstanceOf('Symfony\Component\Form\FormView', $view);
$this->assertSame($parentView, $view->parent);
}
public function testBuildView()
{
$options = array('a' => '1', 'b' => '2');
$form = $this->getBuilder('name', $options)
->setCompound(true)
->setDataMapper($this->dataMapper)
->setType($resolvedType)
->add($this->getBuilder('foo')->setType($field1ResolvedType))
->add($this->getBuilder('bar')->setType($field2ResolvedType))
->getForm();
$form = $this->getMock('Symfony\Component\Form\Test\FormInterface');
$view = $this->getMock('Symfony\Component\Form\FormView');
$test = $this;
$i = 0;
$assertIndexAndNbOfChildViews = function ($index, $nbOfChildViews) use (&$i, $test) {
return function (FormView $view) use (&$i, $test, $index, $nbOfChildViews) {
$assertIndex = function ($index) use (&$i, $test) {
return function () use (&$i, $test, $index) {
/* @var \PHPUnit_Framework_TestCase $test */
$test->assertEquals($index, $i, 'Executed at index '.$index);
$test->assertCount($nbOfChildViews, $view);
++$i;
};
};
// First the super type
$parentType->expects($this->once())
$this->parentType->expects($this->once())
->method('buildView')
->with($this->anything(), $form, $options)
->will($this->returnCallback($assertIndexAndNbOfChildViews(0, 0)));
->with($view, $form, $options)
->will($this->returnCallback($assertIndex(0)));
// Then the type itself
$type->expects($this->once())
$this->type->expects($this->once())
->method('buildView')
->with($this->anything(), $form, $options)
->will($this->returnCallback($assertIndexAndNbOfChildViews(1, 0)));
->with($view, $form, $options)
->will($this->returnCallback($assertIndex(1)));
// Then its extensions
$extension1->expects($this->once())
$this->extension1->expects($this->once())
->method('buildView')
->with($this->anything(), $form, $options)
->will($this->returnCallback($assertIndexAndNbOfChildViews(2, 0)));
->with($view, $form, $options)
->will($this->returnCallback($assertIndex(2)));
$extension2->expects($this->once())
$this->extension2->expects($this->once())
->method('buildView')
->with($this->anything(), $form, $options)
->will($this->returnCallback($assertIndexAndNbOfChildViews(3, 0)));
->with($view, $form, $options)
->will($this->returnCallback($assertIndex(3)));
// Now the first child form
$field1Type->expects($this->once())
->method('buildView')
->will($this->returnCallback($assertIndexAndNbOfChildViews(4, 0)));
$field1Type->expects($this->once())
$this->resolvedType->buildView($view, $form, $options);
}
public function testFinishView()
{
$options = array('a' => '1', 'b' => '2');
$form = $this->getMock('Symfony\Component\Form\Test\FormInterface');
$view = $this->getMock('Symfony\Component\Form\FormView');
$test = $this;
$i = 0;
$assertIndex = function ($index) use (&$i, $test) {
return function () use (&$i, $test, $index) {
/* @var \PHPUnit_Framework_TestCase $test */
$test->assertEquals($index, $i, 'Executed at index '.$index);
++$i;
};
};
// First the super type
$this->parentType->expects($this->once())
->method('finishView')
->will($this->returnCallback($assertIndexAndNbOfChildViews(5, 0)));
// And the second child form
$field2Type->expects($this->once())
->method('buildView')
->will($this->returnCallback($assertIndexAndNbOfChildViews(6, 0)));
$field2Type->expects($this->once())
->method('finishView')
->will($this->returnCallback($assertIndexAndNbOfChildViews(7, 0)));
// Again first the parent
$parentType->expects($this->once())
->method('finishView')
->with($this->anything(), $form, $options)
->will($this->returnCallback($assertIndexAndNbOfChildViews(8, 2)));
->with($view, $form, $options)
->will($this->returnCallback($assertIndex(0)));
// Then the type itself
$type->expects($this->once())
$this->type->expects($this->once())
->method('finishView')
->with($this->anything(), $form, $options)
->will($this->returnCallback($assertIndexAndNbOfChildViews(9, 2)));
->with($view, $form, $options)
->will($this->returnCallback($assertIndex(1)));
// Then its extensions
$extension1->expects($this->once())
$this->extension1->expects($this->once())
->method('finishView')
->with($this->anything(), $form, $options)
->will($this->returnCallback($assertIndexAndNbOfChildViews(10, 2)));
->with($view, $form, $options)
->will($this->returnCallback($assertIndex(2)));
$extension2->expects($this->once())
$this->extension2->expects($this->once())
->method('finishView')
->with($this->anything(), $form, $options)
->will($this->returnCallback($assertIndexAndNbOfChildViews(11, 2)));
->with($view, $form, $options)
->will($this->returnCallback($assertIndex(3)));
$parentView = new FormView();
$view = $resolvedType->createView($form, $parentView);
$this->assertSame($parentView, $view->parent);
$this->resolvedType->finishView($view, $form, $options);
}
/**