[Form] Fixed reference handling in forms. Sometimes data wasn't written into the domain object, resulting in failed validation.

This commit is contained in:
Bernhard Schussek 2011-02-09 01:15:49 +01:00 committed by Fabien Potencier
parent 81765f8b6a
commit 7dbc09ed8b
2 changed files with 37 additions and 5 deletions

View File

@ -911,12 +911,18 @@ class Form extends Field implements \IteratorAggregate, FormInterface
*/
public function writeProperty(&$objectOrArray)
{
$data = $this->getData();
$isReference = false;
// Don't update parent if data is a composite type (object or array)
// and "by_reference" option is true, because then we expect that
// we are working with a reference to the parent's data
if (!is_object($data) || !is_object($objectOrArray) || !$this->getOption('by_reference')) {
// If the data is identical to the value in $objectOrArray, we are
// dealing with a reference
if ($this->getPropertyPath() !== null) {
$isReference = $this->getData() === $this->getPropertyPath()->getValue($objectOrArray);
}
// Don't write into $objectOrArray if $objectOrArray is an object,
// $isReference is true (see above) and the option "by_reference" is
// true as well
if (!is_object($objectOrArray) || !$isReference || !$this->getOption('by_reference')) {
parent::writeProperty($objectOrArray);
}
}

View File

@ -1246,6 +1246,32 @@ class FormTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('Foo', $author->getReference()->firstName);
}
public function testSubformCallsSettersIfTheObjectChanged()
{
// no reference
$author = new FormTest_AuthorWithoutRefSetter(null);
$newReference = new Author();
$form = new Form('author', array('validator' => $this->createMockValidator()));
$form->setData($author);
$refForm = new Form('referenceCopy');
$refForm->add(new TestField('firstName'));
$form->add($refForm);
$refForm->setData($newReference); // new author object
$form->bind($this->createPostRequest(array(
'author' => array(
// referenceCopy has a getter that returns a copy
'referenceCopy' => array(
'firstName' => 'Foo',
)
)
)));
$this->assertEquals('Foo', $author->getReferenceCopy()->firstName);
}
public function testSubformCallsSettersIfByReferenceIsFalse()
{
$author = new FormTest_AuthorWithoutRefSetter(new Author());