[Form] Added accessor FormConfigInterface::getByReference() and let Form clone objects if not by reference

This commit is contained in:
Bernhard Schussek 2012-05-23 14:51:26 +02:00
parent fc2370104f
commit bad6d040d7
8 changed files with 90 additions and 25 deletions

View File

@ -37,13 +37,7 @@ class PropertyPathMapper implements DataMapperInterface
$config = $form->getConfig();
if (null !== $propertyPath && $config->getMapped()) {
$propertyData = $propertyPath->getValue($data);
if (is_object($propertyData) && !$form->getAttribute('by_reference')) {
$propertyData = clone $propertyData;
}
$form->setData($propertyData);
$form->setData($propertyPath->getValue($data));
}
}
}
@ -68,9 +62,8 @@ class PropertyPathMapper implements DataMapperInterface
// If the data is identical to the value in $data, we are
// dealing with a reference
$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());
}
}

View File

@ -46,9 +46,9 @@ class FormType extends AbstractType
// BC compatibility, when "property_path" could be false
->setPropertyPath(is_string($options['property_path']) ? $options['property_path'] : null)
->setMapped($options['mapped'])
->setByReference($options['by_reference'])
->setVirtual($options['virtual'])
->setAttribute('read_only', $options['read_only'])
->setAttribute('by_reference', $options['by_reference'])
->setAttribute('max_length', $options['max_length'])
->setAttribute('pattern', $options['pattern'])
->setAttribute('label', $options['label'] ?: $this->humanize($builder->getName()))

View File

@ -319,6 +319,10 @@ class Form implements \IteratorAggregate, FormInterface
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);
$this->config->getEventDispatcher()->dispatch(FormEvents::PRE_SET_DATA, $event);

View File

@ -43,6 +43,11 @@ class FormConfig implements FormConfigInterface
*/
private $mapped = true;
/**
* @var Boolean
*/
private $byReference = true;
/**
* @var Boolean
*/
@ -294,6 +299,14 @@ class FormConfig implements FormConfigInterface
return $this->mapped;
}
/**
* {@inheritdoc}
*/
public function getByReference()
{
return $this->byReference;
}
/**
* {@inheritdoc}
*/
@ -550,6 +563,21 @@ class FormConfig implements FormConfigInterface
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.
*

View File

@ -47,6 +47,13 @@ interface FormConfigInterface
*/
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.
*

View File

@ -110,7 +110,7 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
->will($this->returnValue($engine));
$config = new FormConfig('name', '\stdClass', $this->dispatcher);
$config->setAttribute('by_reference', true);
$config->setByReference(true);
$config->setPropertyPath($propertyPath);
$form = $this->getForm($config);
@ -133,7 +133,7 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
->will($this->returnValue($engine));
$config = new FormConfig('name', '\stdClass', $this->dispatcher);
$config->setAttribute('by_reference', false);
$config->setByReference(false);
$config->setPropertyPath($propertyPath);
$form = $this->getForm($config);
@ -148,7 +148,7 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
$car = new \stdClass();
$config = new FormConfig(null, '\stdClass', $this->dispatcher);
$config->setAttribute('by_reference', true);
$config->setByReference(true);
$form = $this->getForm($config);
$this->assertNull($form->getPropertyPath());
@ -167,7 +167,7 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
->method('getValue');
$config = new FormConfig('name', '\stdClass', $this->dispatcher);
$config->setAttribute('by_reference', true);
$config->setByReference(true);
$config->setMapped(false);
$config->setPropertyPath($propertyPath);
$form = $this->getForm($config);
@ -185,7 +185,7 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
->method('getValue');
$config = new FormConfig('name', '\stdClass', $this->dispatcher);
$config->setAttribute('by_reference', true);
$config->setByReference(true);
$config->setPropertyPath($propertyPath);
$form = $this->getForm($config);
@ -206,12 +206,12 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
->will($this->returnValue($engine));
$config = new FormConfig('name', '\stdClass', $this->dispatcher);
$config->setAttribute('by_reference', true);
$config->setByReference(true);
$config->setVirtual(true);
$form = $this->getForm($config);
$config = new FormConfig('engine', '\stdClass', $this->dispatcher);
$config->setAttribute('by_reference', true);
$config->setByReference(true);
$config->setPropertyPath($propertyPath);
$child = $this->getForm($config);
@ -234,7 +234,7 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
->with($car, $engine);
$config = new FormConfig('name', '\stdClass', $this->dispatcher);
$config->setAttribute('by_reference', false);
$config->setByReference(false);
$config->setPropertyPath($propertyPath);
$config->setData($engine);
$form = $this->getForm($config);
@ -253,7 +253,7 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
->with($car, $engine);
$config = new FormConfig('name', '\stdClass', $this->dispatcher);
$config->setAttribute('by_reference', true);
$config->setByReference(true);
$config->setPropertyPath($propertyPath);
$config->setData($engine);
$form = $this->getForm($config);
@ -277,7 +277,7 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
->method('setValue');
$config = new FormConfig('name', '\stdClass', $this->dispatcher);
$config->setAttribute('by_reference', true);
$config->setByReference(true);
$config->setPropertyPath($propertyPath);
$config->setData($engine);
$form = $this->getForm($config);
@ -295,7 +295,7 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
->method('setValue');
$config = new FormConfig('name', '\stdClass', $this->dispatcher);
$config->setAttribute('by_reference', true);
$config->setByReference(true);
$config->setPropertyPath($propertyPath);
$config->setData($engine);
$config->setMapped(false);
@ -313,7 +313,7 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
->method('setValue');
$config = new FormConfig('name', '\stdClass', $this->dispatcher);
$config->setAttribute('by_reference', true);
$config->setByReference(true);
$config->setPropertyPath($propertyPath);
$config->setData(null);
$form = $this->getForm($config);
@ -331,7 +331,7 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
->method('setValue');
$config = new FormConfig('name', '\stdClass', $this->dispatcher);
$config->setAttribute('by_reference', true);
$config->setByReference(true);
$config->setPropertyPath($propertyPath);
$config->setData($engine);
$form = $this->getForm($config, false);
@ -349,7 +349,7 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
->method('setValue');
$config = new FormConfig('name', '\stdClass', $this->dispatcher);
$config->setAttribute('by_reference', true);
$config->setByReference(true);
$config->setPropertyPath($propertyPath);
$config->setData($engine);
$config->setDisabled(true);
@ -380,7 +380,7 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
$form = $this->getForm($config);
$config = new FormConfig('engine', '\stdClass', $this->dispatcher);
$config->setAttribute('by_reference', true);
$config->setByReference(true);
$config->setPropertyPath($childPath);
$config->setData($engine);
$child = $this->getForm($config);

View File

@ -464,6 +464,25 @@ class FormTest extends \PHPUnit_Framework_TestCase
$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()
{
// use real event dispatcher now

View File

@ -42,6 +42,11 @@ class UnmodifiableFormConfig implements FormConfigInterface
*/
private $mapped;
/**
* @var Boolean
*/
private $byReference;
/**
* @var Boolean
*/
@ -123,6 +128,7 @@ class UnmodifiableFormConfig implements FormConfigInterface
$this->name = $config->getName();
$this->propertyPath = $config->getPropertyPath();
$this->mapped = $config->getMapped();
$this->byReference = $config->getByReference();
$this->virtual = $config->getVirtual();
$this->types = $config->getTypes();
$this->clientTransformers = $config->getClientTransformers();
@ -170,6 +176,14 @@ class UnmodifiableFormConfig implements FormConfigInterface
return $this->mapped;
}
/**
* {@inheritdoc}
*/
public function getByReference()
{
return $this->byReference;
}
/**
* {@inheritdoc}
*/