Skip to content

Instantly share code, notes, and snippets.

@jeremyb
Last active December 18, 2015 09:49
Show Gist options
  • Save jeremyb/5764427 to your computer and use it in GitHub Desktop.
Save jeremyb/5764427 to your computer and use it in GitHub Desktop.
<?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;
use Symfony\Component\Form\Tests\Extension\Core\Type\TypeTestCase;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
/**
* This form type will be included as virtual in the 2 Author form types below.
*/
class AddressType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('address')
->add('city')
;
$builder->addEventListener(FormEvents::PRE_SET_DATA, function(FormEvent $event) {
$form = $event->getForm();
$data = $event->getData();
if (isset($data['country'])) {
$form->add('country');
}
});
}
public function getName()
{
return 'address';
}
}
/**
* First way to embed Address in Author, just adding it to the builder.
*/
class AuthorWithAddressType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('firstName')
->add('lastName')
->add('address', new AddressType(), array(
'virtual' => true,
//'inherit_data' => true,
))
;
}
public function getName()
{
return 'author';
}
}
/**
* Second way to embed Address in Author through the FormEvents::PRE_SET_DATA event.
*/
class AuthorWithAddressByEventType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('firstName')
->add('lastName')
;
$formFactory = $builder->getFormFactory();
$builder->addEventListener(FormEvents::PRE_SET_DATA, function(FormEvent $event) use ($formFactory) {
$form = $event->getForm();
$data = $event->getData();
$form->add($formFactory->createNamed('address', new AddressType(), $data, array(
'virtual' => true,
//'inherit_data' => true,
//'auto_initialize' => false, // uncomment this line for Symfony 2.3
)));
});
}
public function getName()
{
return 'author';
}
}
class FormVirtualTest extends TypeTestCase
{
/**
* Just a simple test to validate that the form works fine.
*/
public function testVirtual()
{
$form = $this->factory->create(new AuthorWithAddressType(), array(
'firstName' => 'John',
'lastName' => 'Doe',
'city' => 'New York',
));
$this->assertEquals('John', $form['firstName']->getData());
$this->assertEquals('Doe', $form['lastName']->getData());
$this->assertEquals('New York', $form['address']['city']->getData());
$this->assertFalse($form['address']->has('country'));
}
/**
* Now I try to specify a value for country field, the expected result is to find a "country"
* field on the address form but no data is passed to the virtual form, so this test fails.
*/
public function testVirtualWithCountry()
{
$form = $this->factory->create(new AuthorWithAddressType(), array(
'country' => 'USA',
));
$this->assertTrue($form['address']->has('country'));
}
/**
* This test loads the address virtual form through the "PRE_SET_DATA" event and injects the form data.
* This test is successful in Symfony 2.2 but fails in 2.3.
* To execute this test in Symfony 2.3 you have to uncomment "auto_initialize" option on line 61.
*/
public function testVirtualAndEvents()
{
$form = $this->factory->create(new AuthorWithAddressByEventType(), array(
'country' => 'USA',
));
$this->assertTrue($form['address']->has('country'));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment