merged branch bschussek/issue4385 (PR #4386)
Commits -------bad6d04
[Form] Added accessor FormConfigInterface::getByReference() and let Form clone objects if not by referencefc23701
[Form] Correctly highlighted BC breaks in the CHANGELOGd1864c7
[Form] Fixed: Virtual forms are ignored when prepopulating a form Discussion ---------- [Form] Fixed: PropertyPathMapper did not always ignore virtual forms Bug fix: yes Feature addition: no Backwards compatibility break: no Symfony2 tests pass: yes Fixes the following tickets: #4385 Todo: - --------------------------------------------------------------------------- by travisbot at 2012-05-23T12:13:49Z This pull request [fails](http://travis-ci.org/symfony/symfony/builds/1410299) (merged a7f90944 intoe0238071
). --------------------------------------------------------------------------- by travisbot at 2012-05-23T12:27:30Z This pull request [fails](http://travis-ci.org/symfony/symfony/builds/1410430) (merged 52510fee intoe0238071
). --------------------------------------------------------------------------- by travisbot at 2012-05-23T12:37:00Z This pull request [fails](http://travis-ci.org/symfony/symfony/builds/1410485) (merged ca5aee9c intoe0238071
). --------------------------------------------------------------------------- by travisbot at 2012-05-23T13:01:10Z This pull request [fails](http://travis-ci.org/symfony/symfony/builds/1410669) (mergedbad6d040
intoe0238071
).
This commit is contained in:
commit
b07fb3c459
@ -71,13 +71,13 @@ CHANGELOG
|
|||||||
* labels don't display field attributes anymore. Label attributes can be
|
* labels don't display field attributes anymore. Label attributes can be
|
||||||
passed in the "label_attr" option/variable
|
passed in the "label_attr" option/variable
|
||||||
* added option "mapped" which should be used instead of setting "property_path" to false
|
* added option "mapped" which should be used instead of setting "property_path" to false
|
||||||
* "data_class" now *must* be set if a form maps to an object and should be left empty otherwise
|
* [BC BREAK] "data_class" now *must* be set if a form maps to an object and should be left empty otherwise
|
||||||
* improved error mapping on forms
|
* improved error mapping on forms
|
||||||
* dot (".") rules are now allowed to map errors assigned to a form to
|
* dot (".") rules are now allowed to map errors assigned to a form to
|
||||||
one of its children
|
one of its children
|
||||||
* errors are not mapped to unsynchronized forms anymore
|
* errors are not mapped to unsynchronized forms anymore
|
||||||
* changed Form constructor to accept a single `FormConfigInterface` object
|
* [BC BREAK] changed Form constructor to accept a single `FormConfigInterface` object
|
||||||
* changed argument order in the FormBuilder constructor
|
* [BC BREAK] changed argument order in the FormBuilder constructor
|
||||||
* deprecated Form methods
|
* deprecated Form methods
|
||||||
* `getTypes`
|
* `getTypes`
|
||||||
* `getErrorBubbling`
|
* `getErrorBubbling`
|
||||||
@ -85,3 +85,6 @@ CHANGELOG
|
|||||||
* `getClientTransformers`
|
* `getClientTransformers`
|
||||||
* deprecated the option "validation_constraint" in favor of the new
|
* deprecated the option "validation_constraint" in favor of the new
|
||||||
option "constraints"
|
option "constraints"
|
||||||
|
* removed superfluous methods from DataMapperInterface
|
||||||
|
* `mapFormToData`
|
||||||
|
* `mapDataToForm`
|
||||||
|
@ -21,9 +21,5 @@ interface DataMapperInterface
|
|||||||
*/
|
*/
|
||||||
function mapDataToForms($data, array $forms);
|
function mapDataToForms($data, array $forms);
|
||||||
|
|
||||||
function mapDataToForm($data, FormInterface $form);
|
|
||||||
|
|
||||||
function mapFormsToData(array $forms, &$data);
|
function mapFormsToData(array $forms, &$data);
|
||||||
|
|
||||||
function mapFormToData(FormInterface $form, &$data);
|
|
||||||
}
|
}
|
||||||
|
@ -32,28 +32,13 @@ class PropertyPathMapper implements DataMapperInterface
|
|||||||
$iterator = new \RecursiveIteratorIterator($iterator);
|
$iterator = new \RecursiveIteratorIterator($iterator);
|
||||||
|
|
||||||
foreach ($iterator as $form) {
|
foreach ($iterator as $form) {
|
||||||
$this->mapDataToForm($data, $form);
|
/* @var FormInterface $form */
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function mapDataToForm($data, FormInterface $form)
|
|
||||||
{
|
|
||||||
if (!empty($data)) {
|
|
||||||
$propertyPath = $form->getPropertyPath();
|
$propertyPath = $form->getPropertyPath();
|
||||||
$config = $form->getConfig();
|
$config = $form->getConfig();
|
||||||
|
|
||||||
if (null !== $propertyPath && $config->getMapped()) {
|
if (null !== $propertyPath && $config->getMapped()) {
|
||||||
$propertyData = $propertyPath->getValue($data);
|
$form->setData($propertyPath->getValue($data));
|
||||||
|
|
||||||
if (is_object($propertyData) && !$form->getAttribute('by_reference')) {
|
|
||||||
$propertyData = clone $propertyData;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$form->setData($propertyData);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -67,15 +52,7 @@ class PropertyPathMapper implements DataMapperInterface
|
|||||||
$iterator = new \RecursiveIteratorIterator($iterator);
|
$iterator = new \RecursiveIteratorIterator($iterator);
|
||||||
|
|
||||||
foreach ($iterator as $form) {
|
foreach ($iterator as $form) {
|
||||||
$this->mapFormToData($form, $data);
|
/* @var FormInterface $form */
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function mapFormToData(FormInterface $form, &$data)
|
|
||||||
{
|
|
||||||
$propertyPath = $form->getPropertyPath();
|
$propertyPath = $form->getPropertyPath();
|
||||||
$config = $form->getConfig();
|
$config = $form->getConfig();
|
||||||
|
|
||||||
@ -85,11 +62,11 @@ class PropertyPathMapper implements DataMapperInterface
|
|||||||
// If the data is identical to the value in $data, we are
|
// If the data is identical to the value in $data, we are
|
||||||
// dealing with a reference
|
// dealing with a reference
|
||||||
$isReference = $form->getData() === $propertyPath->getValue($data);
|
$isReference = $form->getData() === $propertyPath->getValue($data);
|
||||||
$byReference = $form->getAttribute('by_reference');
|
|
||||||
|
|
||||||
if (!(is_object($data) && $isReference && $byReference)) {
|
if (!is_object($data) || !$isReference || !$config->getByReference()) {
|
||||||
$propertyPath->setValue($data, $form->getData());
|
$propertyPath->setValue($data, $form->getData());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,9 +46,9 @@ class FormType extends AbstractType
|
|||||||
// BC compatibility, when "property_path" could be false
|
// BC compatibility, when "property_path" could be false
|
||||||
->setPropertyPath(is_string($options['property_path']) ? $options['property_path'] : null)
|
->setPropertyPath(is_string($options['property_path']) ? $options['property_path'] : null)
|
||||||
->setMapped($options['mapped'])
|
->setMapped($options['mapped'])
|
||||||
|
->setByReference($options['by_reference'])
|
||||||
->setVirtual($options['virtual'])
|
->setVirtual($options['virtual'])
|
||||||
->setAttribute('read_only', $options['read_only'])
|
->setAttribute('read_only', $options['read_only'])
|
||||||
->setAttribute('by_reference', $options['by_reference'])
|
|
||||||
->setAttribute('max_length', $options['max_length'])
|
->setAttribute('max_length', $options['max_length'])
|
||||||
->setAttribute('pattern', $options['pattern'])
|
->setAttribute('pattern', $options['pattern'])
|
||||||
->setAttribute('label', $options['label'] ?: $this->humanize($builder->getName()))
|
->setAttribute('label', $options['label'] ?: $this->humanize($builder->getName()))
|
||||||
|
@ -319,6 +319,10 @@ class Form implements \IteratorAggregate, FormInterface
|
|||||||
throw new AlreadyBoundException('You cannot change the data of a bound form');
|
throw new AlreadyBoundException('You cannot change the data of a bound form');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_object($appData) && !$this->config->getByReference()) {
|
||||||
|
$appData = clone $appData;
|
||||||
|
}
|
||||||
|
|
||||||
$event = new DataEvent($this, $appData);
|
$event = new DataEvent($this, $appData);
|
||||||
$this->config->getEventDispatcher()->dispatch(FormEvents::PRE_SET_DATA, $event);
|
$this->config->getEventDispatcher()->dispatch(FormEvents::PRE_SET_DATA, $event);
|
||||||
|
|
||||||
@ -805,7 +809,7 @@ class Form implements \IteratorAggregate, FormInterface
|
|||||||
$child->setParent($this);
|
$child->setParent($this);
|
||||||
|
|
||||||
if ($this->config->getDataMapper()) {
|
if ($this->config->getDataMapper()) {
|
||||||
$this->config->getDataMapper()->mapDataToForm($this->getClientData(), $child);
|
$this->config->getDataMapper()->mapDataToForms($this->getClientData(), array($child));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
|
@ -41,12 +41,17 @@ class FormConfig implements FormConfigInterface
|
|||||||
/**
|
/**
|
||||||
* @var Boolean
|
* @var Boolean
|
||||||
*/
|
*/
|
||||||
private $mapped;
|
private $mapped = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Boolean
|
* @var Boolean
|
||||||
*/
|
*/
|
||||||
private $virtual;
|
private $byReference = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Boolean
|
||||||
|
*/
|
||||||
|
private $virtual = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array
|
* @var array
|
||||||
@ -76,17 +81,17 @@ class FormConfig implements FormConfigInterface
|
|||||||
/**
|
/**
|
||||||
* @var Boolean
|
* @var Boolean
|
||||||
*/
|
*/
|
||||||
private $required;
|
private $required = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Boolean
|
* @var Boolean
|
||||||
*/
|
*/
|
||||||
private $disabled;
|
private $disabled = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Boolean
|
* @var Boolean
|
||||||
*/
|
*/
|
||||||
private $errorBubbling;
|
private $errorBubbling = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var mixed
|
* @var mixed
|
||||||
@ -294,6 +299,14 @@ class FormConfig implements FormConfigInterface
|
|||||||
return $this->mapped;
|
return $this->mapped;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getByReference()
|
||||||
|
{
|
||||||
|
return $this->byReference;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
@ -550,6 +563,21 @@ class FormConfig implements FormConfigInterface
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether the form's data should be modified by reference.
|
||||||
|
*
|
||||||
|
* @param Boolean $byReference Whether the data should be
|
||||||
|
modified by reference.
|
||||||
|
*
|
||||||
|
* @return self The configuration object.
|
||||||
|
*/
|
||||||
|
public function setByReference($byReference)
|
||||||
|
{
|
||||||
|
$this->byReference = $byReference;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets whether the form should be virtual.
|
* Sets whether the form should be virtual.
|
||||||
*
|
*
|
||||||
|
@ -47,6 +47,13 @@ interface FormConfigInterface
|
|||||||
*/
|
*/
|
||||||
function getMapped();
|
function getMapped();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the form's data should be modified by reference.
|
||||||
|
*
|
||||||
|
* @return Boolean Whether to modify the form's data by reference.
|
||||||
|
*/
|
||||||
|
function getByReference();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the form should be virtual.
|
* Returns whether the form should be virtual.
|
||||||
*
|
*
|
||||||
|
@ -12,6 +12,9 @@
|
|||||||
namespace Symfony\Component\Form\Tests\Extension\Core\DataMapper;
|
namespace Symfony\Component\Form\Tests\Extension\Core\DataMapper;
|
||||||
|
|
||||||
use Symfony\Component\Form\Tests\FormInterface;
|
use Symfony\Component\Form\Tests\FormInterface;
|
||||||
|
use Symfony\Component\Form\Form;
|
||||||
|
use Symfony\Component\Form\FormConfig;
|
||||||
|
use Symfony\Component\Form\FormConfigInterface;
|
||||||
use Symfony\Component\Form\Util\PropertyPath;
|
use Symfony\Component\Form\Util\PropertyPath;
|
||||||
use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper;
|
use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper;
|
||||||
|
|
||||||
@ -44,18 +47,30 @@ abstract class PropertyPathMapperTest_Form implements FormInterface
|
|||||||
|
|
||||||
class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
|
class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var PropertyPathMapper
|
||||||
|
*/
|
||||||
private $mapper;
|
private $mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \PHPUnit_Framework_MockObject_MockObject
|
||||||
|
*/
|
||||||
|
private $dispatcher;
|
||||||
|
|
||||||
protected function setUp()
|
protected function setUp()
|
||||||
{
|
{
|
||||||
|
if (!class_exists('Symfony\Component\EventDispatcher\Event')) {
|
||||||
|
$this->markTestSkipped('The "EventDispatcher" component is not available');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
|
||||||
$this->mapper = new PropertyPathMapper();
|
$this->mapper = new PropertyPathMapper();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function tearDown()
|
/**
|
||||||
{
|
* @param $path
|
||||||
$this->mapper = null;
|
* @return \PHPUnit_Framework_MockObject_MockObject
|
||||||
}
|
*/
|
||||||
|
|
||||||
private function getPropertyPath($path)
|
private function getPropertyPath($path)
|
||||||
{
|
{
|
||||||
return $this->getMockBuilder('Symfony\Component\Form\Util\PropertyPath')
|
return $this->getMockBuilder('Symfony\Component\Form\Util\PropertyPath')
|
||||||
@ -64,44 +79,26 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
|
|||||||
->getMock();
|
->getMock();
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getForm(PropertyPath $propertyPath = null, $byReference, $synchronized = true, $mapped = true, $disabled = false)
|
/**
|
||||||
|
* @param FormConfigInterface $config
|
||||||
|
* @param Boolean $synchronized
|
||||||
|
* @return \PHPUnit_Framework_MockObject_MockObject
|
||||||
|
*/
|
||||||
|
private function getForm(FormConfigInterface $config, $synchronized = true)
|
||||||
{
|
{
|
||||||
$config = $this->getMock('Symfony\Component\Form\FormConfigInterface');
|
$form = $this->getMockBuilder('Symfony\Component\Form\Form')
|
||||||
|
->setConstructorArgs(array($config))
|
||||||
$config->expects($this->any())
|
->setMethods(array('isSynchronized'))
|
||||||
->method('getMapped')
|
->getMock();
|
||||||
->will($this->returnValue($mapped));
|
|
||||||
|
|
||||||
$form = $this->getMockBuilder(__CLASS__ . '_Form')
|
|
||||||
// PHPUnit's getMockForAbstractClass does not behave like in the docs..
|
|
||||||
// If the array is empty, all methods are mocked. If it is not
|
|
||||||
// empty, only abstract methods and the methods in the array are
|
|
||||||
// mocked.
|
|
||||||
->setMethods(array('foo'))
|
|
||||||
->getMockForAbstractClass();
|
|
||||||
|
|
||||||
$form->setAttribute('by_reference', $byReference);
|
|
||||||
|
|
||||||
$form->expects($this->any())
|
|
||||||
->method('getConfig')
|
|
||||||
->will($this->returnValue($config));
|
|
||||||
|
|
||||||
$form->expects($this->any())
|
|
||||||
->method('getPropertyPath')
|
|
||||||
->will($this->returnValue($propertyPath));
|
|
||||||
|
|
||||||
$form->expects($this->any())
|
$form->expects($this->any())
|
||||||
->method('isSynchronized')
|
->method('isSynchronized')
|
||||||
->will($this->returnValue($synchronized));
|
->will($this->returnValue($synchronized));
|
||||||
|
|
||||||
$form->expects($this->any())
|
|
||||||
->method('isDisabled')
|
|
||||||
->will($this->returnValue($disabled));
|
|
||||||
|
|
||||||
return $form;
|
return $form;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testMapDataToFormPassesObjectRefIfByReference()
|
public function testMapDataToFormsPassesObjectRefIfByReference()
|
||||||
{
|
{
|
||||||
$car = new \stdClass();
|
$car = new \stdClass();
|
||||||
$engine = new \stdClass();
|
$engine = new \stdClass();
|
||||||
@ -112,16 +109,19 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
|
|||||||
->with($car)
|
->with($car)
|
||||||
->will($this->returnValue($engine));
|
->will($this->returnValue($engine));
|
||||||
|
|
||||||
$form = $this->getForm($propertyPath, true);
|
$config = new FormConfig('name', '\stdClass', $this->dispatcher);
|
||||||
|
$config->setByReference(true);
|
||||||
|
$config->setPropertyPath($propertyPath);
|
||||||
|
$form = $this->getForm($config);
|
||||||
|
|
||||||
$this->mapper->mapDataToForm($car, $form);
|
$this->mapper->mapDataToForms($car, array($form));
|
||||||
|
|
||||||
// Can't use isIdentical() above because mocks always clone their
|
// Can't use isIdentical() above because mocks always clone their
|
||||||
// arguments which can't be disabled in PHPUnit 3.6
|
// arguments which can't be disabled in PHPUnit 3.6
|
||||||
$this->assertSame($engine, $form->getData());
|
$this->assertSame($engine, $form->getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testMapDataToFormPassesObjectCloneIfNotByReference()
|
public function testMapDataToFormsPassesObjectCloneIfNotByReference()
|
||||||
{
|
{
|
||||||
$car = new \stdClass();
|
$car = new \stdClass();
|
||||||
$engine = new \stdClass();
|
$engine = new \stdClass();
|
||||||
@ -132,26 +132,33 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
|
|||||||
->with($car)
|
->with($car)
|
||||||
->will($this->returnValue($engine));
|
->will($this->returnValue($engine));
|
||||||
|
|
||||||
$form = $this->getForm($propertyPath, false);
|
$config = new FormConfig('name', '\stdClass', $this->dispatcher);
|
||||||
|
$config->setByReference(false);
|
||||||
|
$config->setPropertyPath($propertyPath);
|
||||||
|
$form = $this->getForm($config);
|
||||||
|
|
||||||
$this->mapper->mapDataToForm($car, $form);
|
$this->mapper->mapDataToForms($car, array($form));
|
||||||
|
|
||||||
$this->assertNotSame($engine, $form->getData());
|
$this->assertNotSame($engine, $form->getData());
|
||||||
$this->assertEquals($engine, $form->getData());
|
$this->assertEquals($engine, $form->getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testMapDataToFormIgnoresEmptyPropertyPath()
|
public function testMapDataToFormsIgnoresEmptyPropertyPath()
|
||||||
{
|
{
|
||||||
$car = new \stdClass();
|
$car = new \stdClass();
|
||||||
|
|
||||||
$form = $this->getForm(null, true);
|
$config = new FormConfig(null, '\stdClass', $this->dispatcher);
|
||||||
|
$config->setByReference(true);
|
||||||
|
$form = $this->getForm($config);
|
||||||
|
|
||||||
$this->mapper->mapDataToForm($car, $form);
|
$this->assertNull($form->getPropertyPath());
|
||||||
|
|
||||||
|
$this->mapper->mapDataToForms($car, array($form));
|
||||||
|
|
||||||
$this->assertNull($form->getData());
|
$this->assertNull($form->getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testMapDataToFormIgnoresUnmapped()
|
public function testMapDataToFormsIgnoresUnmapped()
|
||||||
{
|
{
|
||||||
$car = new \stdClass();
|
$car = new \stdClass();
|
||||||
$propertyPath = $this->getPropertyPath('engine');
|
$propertyPath = $this->getPropertyPath('engine');
|
||||||
@ -159,24 +166,64 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
|
|||||||
$propertyPath->expects($this->never())
|
$propertyPath->expects($this->never())
|
||||||
->method('getValue');
|
->method('getValue');
|
||||||
|
|
||||||
$form = $this->getForm($propertyPath, true, true, false);
|
$config = new FormConfig('name', '\stdClass', $this->dispatcher);
|
||||||
|
$config->setByReference(true);
|
||||||
|
$config->setMapped(false);
|
||||||
|
$config->setPropertyPath($propertyPath);
|
||||||
|
$form = $this->getForm($config);
|
||||||
|
|
||||||
$this->mapper->mapDataToForm($car, $form);
|
$this->mapper->mapDataToForms($car, array($form));
|
||||||
|
|
||||||
$this->assertNull($form->getData());
|
$this->assertNull($form->getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testMapDataToFormIgnoresEmptyData()
|
public function testMapDataToFormsIgnoresEmptyData()
|
||||||
{
|
{
|
||||||
$propertyPath = $this->getPropertyPath('engine');
|
$propertyPath = $this->getPropertyPath('engine');
|
||||||
$form = $this->getForm($propertyPath, true);
|
|
||||||
|
|
||||||
$this->mapper->mapDataToForm(null, $form);
|
$propertyPath->expects($this->never())
|
||||||
|
->method('getValue');
|
||||||
|
|
||||||
|
$config = new FormConfig('name', '\stdClass', $this->dispatcher);
|
||||||
|
$config->setByReference(true);
|
||||||
|
$config->setPropertyPath($propertyPath);
|
||||||
|
$form = $this->getForm($config);
|
||||||
|
|
||||||
|
$this->mapper->mapDataToForms(null, array($form));
|
||||||
|
|
||||||
$this->assertNull($form->getData());
|
$this->assertNull($form->getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testMapFormToDataWritesBackIfNotByReference()
|
public function testMapDataToFormsSkipsVirtualForms()
|
||||||
|
{
|
||||||
|
$car = new \stdClass();
|
||||||
|
$engine = new \stdClass();
|
||||||
|
$propertyPath = $this->getPropertyPath('engine');
|
||||||
|
|
||||||
|
$propertyPath->expects($this->once())
|
||||||
|
->method('getValue')
|
||||||
|
->with($car)
|
||||||
|
->will($this->returnValue($engine));
|
||||||
|
|
||||||
|
$config = new FormConfig('name', '\stdClass', $this->dispatcher);
|
||||||
|
$config->setByReference(true);
|
||||||
|
$config->setVirtual(true);
|
||||||
|
$form = $this->getForm($config);
|
||||||
|
|
||||||
|
$config = new FormConfig('engine', '\stdClass', $this->dispatcher);
|
||||||
|
$config->setByReference(true);
|
||||||
|
$config->setPropertyPath($propertyPath);
|
||||||
|
$child = $this->getForm($config);
|
||||||
|
|
||||||
|
$form->add($child);
|
||||||
|
|
||||||
|
$this->mapper->mapDataToForms($car, array($form));
|
||||||
|
|
||||||
|
$this->assertNull($form->getData());
|
||||||
|
$this->assertSame($engine, $child->getData());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMapFormsToDataWritesBackIfNotByReference()
|
||||||
{
|
{
|
||||||
$car = new \stdClass();
|
$car = new \stdClass();
|
||||||
$engine = new \stdClass();
|
$engine = new \stdClass();
|
||||||
@ -186,13 +233,16 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
|
|||||||
->method('setValue')
|
->method('setValue')
|
||||||
->with($car, $engine);
|
->with($car, $engine);
|
||||||
|
|
||||||
$form = $this->getForm($propertyPath, false);
|
$config = new FormConfig('name', '\stdClass', $this->dispatcher);
|
||||||
$form->setData($engine);
|
$config->setByReference(false);
|
||||||
|
$config->setPropertyPath($propertyPath);
|
||||||
|
$config->setData($engine);
|
||||||
|
$form = $this->getForm($config);
|
||||||
|
|
||||||
$this->mapper->mapFormToData($form, $car);
|
$this->mapper->mapFormsToData(array($form), $car);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testMapFormToDataWritesBackIfByReferenceButNoReference()
|
public function testMapFormsToDataWritesBackIfByReferenceButNoReference()
|
||||||
{
|
{
|
||||||
$car = new \stdClass();
|
$car = new \stdClass();
|
||||||
$engine = new \stdClass();
|
$engine = new \stdClass();
|
||||||
@ -202,13 +252,16 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
|
|||||||
->method('setValue')
|
->method('setValue')
|
||||||
->with($car, $engine);
|
->with($car, $engine);
|
||||||
|
|
||||||
$form = $this->getForm($propertyPath, true);
|
$config = new FormConfig('name', '\stdClass', $this->dispatcher);
|
||||||
$form->setData($engine);
|
$config->setByReference(true);
|
||||||
|
$config->setPropertyPath($propertyPath);
|
||||||
|
$config->setData($engine);
|
||||||
|
$form = $this->getForm($config);
|
||||||
|
|
||||||
$this->mapper->mapFormToData($form, $car);
|
$this->mapper->mapFormsToData(array($form), $car);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testMapFormToDataWritesBackIfByReferenceAndReference()
|
public function testMapFormsToDataWritesBackIfByReferenceAndReference()
|
||||||
{
|
{
|
||||||
$car = new \stdClass();
|
$car = new \stdClass();
|
||||||
$engine = new \stdClass();
|
$engine = new \stdClass();
|
||||||
@ -223,13 +276,16 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
|
|||||||
$propertyPath->expects($this->never())
|
$propertyPath->expects($this->never())
|
||||||
->method('setValue');
|
->method('setValue');
|
||||||
|
|
||||||
$form = $this->getForm($propertyPath, true);
|
$config = new FormConfig('name', '\stdClass', $this->dispatcher);
|
||||||
$form->setData($engine);
|
$config->setByReference(true);
|
||||||
|
$config->setPropertyPath($propertyPath);
|
||||||
|
$config->setData($engine);
|
||||||
|
$form = $this->getForm($config);
|
||||||
|
|
||||||
$this->mapper->mapFormToData($form, $car);
|
$this->mapper->mapFormsToData(array($form), $car);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testMapFormToDataIgnoresUnmapped()
|
public function testMapFormsToDataIgnoresUnmapped()
|
||||||
{
|
{
|
||||||
$car = new \stdClass();
|
$car = new \stdClass();
|
||||||
$engine = new \stdClass();
|
$engine = new \stdClass();
|
||||||
@ -238,13 +294,17 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
|
|||||||
$propertyPath->expects($this->never())
|
$propertyPath->expects($this->never())
|
||||||
->method('setValue');
|
->method('setValue');
|
||||||
|
|
||||||
$form = $this->getForm($propertyPath, true, true, false);
|
$config = new FormConfig('name', '\stdClass', $this->dispatcher);
|
||||||
$form->setData($engine);
|
$config->setByReference(true);
|
||||||
|
$config->setPropertyPath($propertyPath);
|
||||||
|
$config->setData($engine);
|
||||||
|
$config->setMapped(false);
|
||||||
|
$form = $this->getForm($config);
|
||||||
|
|
||||||
$this->mapper->mapFormToData($form, $car);
|
$this->mapper->mapFormsToData(array($form), $car);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testMapFormToDataIgnoresEmptyData()
|
public function testMapFormsToDataIgnoresEmptyData()
|
||||||
{
|
{
|
||||||
$car = new \stdClass();
|
$car = new \stdClass();
|
||||||
$propertyPath = $this->getPropertyPath('engine');
|
$propertyPath = $this->getPropertyPath('engine');
|
||||||
@ -252,13 +312,16 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
|
|||||||
$propertyPath->expects($this->never())
|
$propertyPath->expects($this->never())
|
||||||
->method('setValue');
|
->method('setValue');
|
||||||
|
|
||||||
$form = $this->getForm($propertyPath, true);
|
$config = new FormConfig('name', '\stdClass', $this->dispatcher);
|
||||||
$form->setData(null);
|
$config->setByReference(true);
|
||||||
|
$config->setPropertyPath($propertyPath);
|
||||||
|
$config->setData(null);
|
||||||
|
$form = $this->getForm($config);
|
||||||
|
|
||||||
$this->mapper->mapFormToData($form, $car);
|
$this->mapper->mapFormsToData(array($form), $car);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testMapFormToDataIgnoresUnsynchronized()
|
public function testMapFormsToDataIgnoresUnsynchronized()
|
||||||
{
|
{
|
||||||
$car = new \stdClass();
|
$car = new \stdClass();
|
||||||
$engine = new \stdClass();
|
$engine = new \stdClass();
|
||||||
@ -267,13 +330,16 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
|
|||||||
$propertyPath->expects($this->never())
|
$propertyPath->expects($this->never())
|
||||||
->method('setValue');
|
->method('setValue');
|
||||||
|
|
||||||
$form = $this->getForm($propertyPath, true, false);
|
$config = new FormConfig('name', '\stdClass', $this->dispatcher);
|
||||||
$form->setData($engine);
|
$config->setByReference(true);
|
||||||
|
$config->setPropertyPath($propertyPath);
|
||||||
|
$config->setData($engine);
|
||||||
|
$form = $this->getForm($config, false);
|
||||||
|
|
||||||
$this->mapper->mapFormToData($form, $car);
|
$this->mapper->mapFormsToData(array($form), $car);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testMapFormToDataIgnoresDisabled()
|
public function testMapFormsToDataIgnoresDisabled()
|
||||||
{
|
{
|
||||||
$car = new \stdClass();
|
$car = new \stdClass();
|
||||||
$engine = new \stdClass();
|
$engine = new \stdClass();
|
||||||
@ -282,9 +348,45 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
|
|||||||
$propertyPath->expects($this->never())
|
$propertyPath->expects($this->never())
|
||||||
->method('setValue');
|
->method('setValue');
|
||||||
|
|
||||||
$form = $this->getForm($propertyPath, true, true, true, true);
|
$config = new FormConfig('name', '\stdClass', $this->dispatcher);
|
||||||
$form->setData($engine);
|
$config->setByReference(true);
|
||||||
|
$config->setPropertyPath($propertyPath);
|
||||||
|
$config->setData($engine);
|
||||||
|
$config->setDisabled(true);
|
||||||
|
$form = $this->getForm($config);
|
||||||
|
|
||||||
$this->mapper->mapFormToData($form, $car);
|
$this->mapper->mapFormsToData(array($form), $car);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMapFormsToDataSkipsVirtualForms()
|
||||||
|
{
|
||||||
|
$car = new \stdClass();
|
||||||
|
$engine = new \stdClass();
|
||||||
|
$parentPath = $this->getPropertyPath('name');
|
||||||
|
$childPath = $this->getPropertyPath('engine');
|
||||||
|
|
||||||
|
$parentPath->expects($this->never())
|
||||||
|
->method('getValue');
|
||||||
|
$parentPath->expects($this->never())
|
||||||
|
->method('setValue');
|
||||||
|
|
||||||
|
$childPath->expects($this->once())
|
||||||
|
->method('setValue')
|
||||||
|
->with($car, $engine);
|
||||||
|
|
||||||
|
$config = new FormConfig('name', '\stdClass', $this->dispatcher);
|
||||||
|
$config->setPropertyPath($parentPath);
|
||||||
|
$config->setVirtual(true);
|
||||||
|
$form = $this->getForm($config);
|
||||||
|
|
||||||
|
$config = new FormConfig('engine', '\stdClass', $this->dispatcher);
|
||||||
|
$config->setByReference(true);
|
||||||
|
$config->setPropertyPath($childPath);
|
||||||
|
$config->setData($engine);
|
||||||
|
$child = $this->getForm($config);
|
||||||
|
|
||||||
|
$form->add($child);
|
||||||
|
|
||||||
|
$this->mapper->mapFormsToData(array($form), $car);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -464,6 +464,25 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->form->setData(null);
|
$this->form->setData(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testSetDataClonesObjectIfNotByReference()
|
||||||
|
{
|
||||||
|
$data = new \stdClass();
|
||||||
|
$form = $this->getBuilder('name', null, '\stdClass')->setByReference(false)->getForm();
|
||||||
|
$form->setData($data);
|
||||||
|
|
||||||
|
$this->assertNotSame($data, $form->getData());
|
||||||
|
$this->assertEquals($data, $form->getData());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSetDataDoesNotCloneObjectIfByReference()
|
||||||
|
{
|
||||||
|
$data = new \stdClass();
|
||||||
|
$form = $this->getBuilder('name', null, '\stdClass')->setByReference(true)->getForm();
|
||||||
|
$form->setData($data);
|
||||||
|
|
||||||
|
$this->assertSame($data, $form->getData());
|
||||||
|
}
|
||||||
|
|
||||||
public function testSetDataExecutesTransformationChain()
|
public function testSetDataExecutesTransformationChain()
|
||||||
{
|
{
|
||||||
// use real event dispatcher now
|
// use real event dispatcher now
|
||||||
@ -736,8 +755,8 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
$child = $this->getBuilder()->getForm();
|
$child = $this->getBuilder()->getForm();
|
||||||
$mapper->expects($this->once())
|
$mapper->expects($this->once())
|
||||||
->method('mapDataToForm')
|
->method('mapDataToForms')
|
||||||
->with('bar', $child);
|
->with('bar', array($child));
|
||||||
|
|
||||||
$form->add($child);
|
$form->add($child);
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,11 @@ class UnmodifiableFormConfig implements FormConfigInterface
|
|||||||
*/
|
*/
|
||||||
private $mapped;
|
private $mapped;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Boolean
|
||||||
|
*/
|
||||||
|
private $byReference;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Boolean
|
* @var Boolean
|
||||||
*/
|
*/
|
||||||
@ -123,6 +128,7 @@ class UnmodifiableFormConfig implements FormConfigInterface
|
|||||||
$this->name = $config->getName();
|
$this->name = $config->getName();
|
||||||
$this->propertyPath = $config->getPropertyPath();
|
$this->propertyPath = $config->getPropertyPath();
|
||||||
$this->mapped = $config->getMapped();
|
$this->mapped = $config->getMapped();
|
||||||
|
$this->byReference = $config->getByReference();
|
||||||
$this->virtual = $config->getVirtual();
|
$this->virtual = $config->getVirtual();
|
||||||
$this->types = $config->getTypes();
|
$this->types = $config->getTypes();
|
||||||
$this->clientTransformers = $config->getClientTransformers();
|
$this->clientTransformers = $config->getClientTransformers();
|
||||||
@ -170,6 +176,14 @@ class UnmodifiableFormConfig implements FormConfigInterface
|
|||||||
return $this->mapped;
|
return $this->mapped;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getByReference()
|
||||||
|
{
|
||||||
|
return $this->byReference;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
|
Reference in New Issue
Block a user