[Form] Renamed option "virtual" to "inherit_data"

This commit is contained in:
Bernhard Schussek 2013-01-04 16:34:38 +01:00
parent d450477ef3
commit 8ea5e1a678
13 changed files with 202 additions and 41 deletions

View File

@ -1,4 +1,4 @@
UPGRADE FROM 2.2 to 2.3 UPGRADE FROM 2.2 to 2.3
======================= =======================
### Form ### Form
@ -35,6 +35,79 @@ UPGRADE FROM 2.2 to 2.3
"validation_groups" => false "validation_groups" => false
"validation_groups" => array() "validation_groups" => array()
``` ```
* The array type hint from DataMapperInterface was removed. You should adapt
implementations of that interface accordingly.
Before:
```
use Symfony\Component\Form\DataMapperInterface;
class MyDataMapper
{
public function mapFormsToData(array $forms, $data)
{
// ...
}
public function mapDataToForms($data, array $forms)
{
// ...
}
}
```
After:
```
use Symfony\Component\Form\DataMapperInterface;
class MyDataMapper
{
public function mapFormsToData($forms, $data)
{
// ...
}
public function mapDataToForms($data, $forms)
{
// ...
}
}
```
Instead of an array, the methods here are now passed a
RecursiveIteratorIterator containing an InheritDataAwareIterator by default,
so you don't need to handle forms inheriting their parent data (former
"virtual forms") in the data mapper anymore.
Before:
```
use Symfony\Component\Form\Util\VirtualFormAwareIterator;
public function mapFormsToData(array $forms, $data)
{
$iterator = new \RecursiveIteratorIterator(
new VirtualFormAwareIterator($forms)
);
foreach ($iterator as $form) {
// ...
}
}
```
After:
```
public function mapFormsToData($forms, $data)
{
foreach ($forms as $form) {
// ...
}
}
```
### PropertyAccess ### PropertyAccess

View File

@ -57,6 +57,42 @@ UPGRADE FROM 2.x to 3.0
} }
``` ```
* The option "virtual" was renamed to "inherit_data".
Before:
```
$builder->add('address', 'form', array(
'virtual' => true,
));
```
After:
```
$builder->add('address', 'form', array(
'inherit_data' => true,
));
```
* The class VirtualFormAwareIterator was renamed to InheritDataAwareIterator.
Before:
```
use Symfony\Component\Form\Util\VirtualFormAwareIterator;
$iterator = new VirtualFormAwareIterator($forms);
```
After:
```
use Symfony\Component\Form\Util\InheritDataAwareIterator;
$iterator = new InheritDataAwareIterator($forms);
```
### FrameworkBundle ### FrameworkBundle
* The `enctype` method of the `form` helper was removed. You should use the * The `enctype` method of the `form` helper was removed. You should use the

View File

@ -492,6 +492,18 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface
throw new \BadMethodCallException('Buttons do not support form processors.'); throw new \BadMethodCallException('Buttons do not support form processors.');
} }
/**
* Unsupported method.
*
* @param Boolean $inheritData
*
* @throws \BadMethodCallException
*/
public function setInheritData($inheritData)
{
throw new \BadMethodCallException('Buttons do not support data inheritance.');
}
/** /**
* Builds and returns the button configuration. * Builds and returns the button configuration.
* *
@ -759,6 +771,16 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface
return null; return null;
} }
/**
* Unsupported method.
*
* @return null Always returns null.
*/
public function getInheritData()
{
return null;
}
/** /**
* Returns all options passed during the construction of the button. * Returns all options passed during the construction of the button.
* *

View File

@ -9,6 +9,7 @@ CHANGELOG
* added FormProcessorInterface and FormInterface::process() * added FormProcessorInterface and FormInterface::process()
* deprecated passing a Request instance to FormInterface::bind() * deprecated passing a Request instance to FormInterface::bind()
* added options "method" and "action" to FormType * added options "method" and "action" to FormType
* deprecated option "virtual", renamed it to "inherit_data"
2.2.0 2.2.0
----- -----

View File

@ -56,7 +56,7 @@ class PropertyPathMapper implements DataMapperInterface
$iterator = new \RecursiveIteratorIterator($iterator); $iterator = new \RecursiveIteratorIterator($iterator);
foreach ($iterator as $form) { foreach ($iterator as $form) {
/* @var FormInterface $form */ /* @var \Symfony\Component\Form\FormInterface $form */
$propertyPath = $form->getPropertyPath(); $propertyPath = $form->getPropertyPath();
$config = $form->getConfig(); $config = $form->getConfig();
@ -83,7 +83,7 @@ class PropertyPathMapper implements DataMapperInterface
$iterator = new \RecursiveIteratorIterator($iterator); $iterator = new \RecursiveIteratorIterator($iterator);
foreach ($iterator as $form) { foreach ($iterator as $form) {
/* @var FormInterface $form */ /* @var \Symfony\Component\Form\FormInterface $form */
$propertyPath = $form->getPropertyPath(); $propertyPath = $form->getPropertyPath();
$config = $form->getConfig(); $config = $form->getConfig();

View File

@ -48,7 +48,7 @@ class FormType extends BaseType
->setPropertyPath($options['property_path']) ->setPropertyPath($options['property_path'])
->setMapped($options['mapped']) ->setMapped($options['mapped'])
->setByReference($options['by_reference']) ->setByReference($options['by_reference'])
->setVirtual($options['virtual']) ->setInheritData($options['inherit_data'])
->setCompound($options['compound']) ->setCompound($options['compound'])
->setData(isset($options['data']) ? $options['data'] : null) ->setData(isset($options['data']) ? $options['data'] : null)
->setDataLocked(isset($options['data'])) ->setDataLocked(isset($options['data']))
@ -95,8 +95,8 @@ class FormType extends BaseType
'size' => null, 'size' => null,
'label_attr' => $options['label_attr'], 'label_attr' => $options['label_attr'],
'compound' => $form->getConfig()->getCompound(), 'compound' => $form->getConfig()->getCompound(),
'method' => $form->getConfig()->getMethod(), 'method' => $form->getConfig()->getMethod(),
'action' => $form->getConfig()->getAction(), 'action' => $form->getConfig()->getAction(),
)); ));
} }
@ -169,7 +169,7 @@ class FormType extends BaseType
'by_reference' => true, 'by_reference' => true,
'error_bubbling' => $errorBubbling, 'error_bubbling' => $errorBubbling,
'label_attr' => array(), 'label_attr' => array(),
'virtual' => false, 'inherit_data' => false,
'compound' => true, 'compound' => true,
'method' => 'POST', 'method' => 'POST',
// According to RFC 2396 (http://www.ietf.org/rfc/rfc2396.txt) // According to RFC 2396 (http://www.ietf.org/rfc/rfc2396.txt)

View File

@ -88,8 +88,8 @@ class ViolationMapper implements ViolationMapperInterface
} }
// This case happens if an error happened in the data under a // This case happens if an error happened in the data under a
// virtual form that does not match any of the children of // form inheriting its parent data that does not match any of the
// the virtual form. // children of that form.
if (null !== $violationPath && !$match) { if (null !== $violationPath && !$match) {
// If we could not map the error to anything more specific // If we could not map the error to anything more specific
// than the root element, map it to the innermost directly // than the root element, map it to the innermost directly
@ -162,7 +162,7 @@ class ViolationMapper implements ViolationMapperInterface
} }
} }
// Ignore virtual forms when iterating the children // Skip forms inheriting their parent data when iterating the children
$childIterator = new \RecursiveIteratorIterator( $childIterator = new \RecursiveIteratorIterator(
new VirtualFormAwareIterator($form->all()) new VirtualFormAwareIterator($form->all())
); );
@ -253,8 +253,8 @@ class ViolationMapper implements ViolationMapperInterface
// Process child form // Process child form
$scope = $scope->get($it->current()); $scope = $scope->get($it->current());
if ($scope->getConfig()->getVirtual()) { if ($scope->getConfig()->getInheritData()) {
// Form is virtual // Form inherits its parent data
// Cut the piece out of the property path and proceed // Cut the piece out of the property path and proceed
$propertyPathBuilder->remove($i); $propertyPathBuilder->remove($i);
} elseif (!$scope->getConfig()->getMapped()) { } elseif (!$scope->getConfig()->getMapped()) {

View File

@ -80,7 +80,7 @@ class FormConfigBuilder implements FormConfigBuilderInterface
/** /**
* @var Boolean * @var Boolean
*/ */
private $virtual = false; private $inheritData = false;
/** /**
* @var Boolean * @var Boolean
@ -341,9 +341,24 @@ class FormConfigBuilder implements FormConfigBuilderInterface
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function getInheritData()
{
return $this->inheritData;
}
/**
* Alias of {@link getInheritData()}.
*
* @return FormConfigBuilder The configuration object.
*
* @deprecated Deprecated since version 2.2, to be removed in 2.3. Use
* {@link getInheritData()} instead.
*/
public function getVirtual() public function getVirtual()
{ {
return $this->virtual; trigger_error('getVirtual() is deprecated since version 2.2 and will be removed in 2.3. Use getInheritData() instead.', E_USER_DEPRECATED);
return $this->getInheritData();
} }
/** /**
@ -676,17 +691,34 @@ class FormConfigBuilder implements FormConfigBuilderInterface
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function setVirtual($virtual) public function setInheritData($inheritData)
{ {
if ($this->locked) { if ($this->locked) {
throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
} }
$this->virtual = $virtual; $this->inheritData = $inheritData;
return $this; return $this;
} }
/**
* Alias of {@link setInheritData()}.
*
* @param Boolean $inheritData Whether the form should inherit its parent's data.
*
* @return FormConfigBuilder The configuration object.
*
* @deprecated Deprecated since version 2.2, to be removed in 2.3. Use
* {@link setInheritData()} instead.
*/
public function setVirtual($inheritData)
{
trigger_error('setVirtual() is deprecated since version 2.2 and will be removed in 2.3. Use setInheritData() instead.', E_USER_DEPRECATED);
$this->setInheritData($inheritData);
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */

View File

@ -180,13 +180,13 @@ interface FormConfigBuilderInterface extends FormConfigInterface
public function setByReference($byReference); public function setByReference($byReference);
/** /**
* Sets whether the form should be virtual. * Sets whether the form should read and write the data of its parent.
* *
* @param Boolean $virtual Whether the form should be virtual. * @param Boolean $inheritData Whether the form should inherit its parent's data.
* *
* @return self The configuration object. * @return self The configuration object.
*/ */
public function setVirtual($virtual); public function setInheritData($inheritData);
/** /**
* Sets whether the form should be compound. * Sets whether the form should be compound.

View File

@ -55,15 +55,11 @@ interface FormConfigInterface
public function getByReference(); public function getByReference();
/** /**
* Returns whether the form should be virtual. * Returns whether the form should read and write the data of its parent.
* *
* When mapping data to the children of a form, the data mapper * @return Boolean Whether the form should inherit its parent's data.
* should ignore virtual forms and map to the children of the
* virtual form instead.
*
* @return Boolean Whether the form is virtual.
*/ */
public function getVirtual(); public function getInheritData();
/** /**
* Returns whether the form is compound. * Returns whether the form is compound.

View File

@ -182,7 +182,7 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
$this->assertNull($form->getData()); $this->assertNull($form->getData());
} }
public function testMapDataToFormsSkipsVirtualForms() public function testMapDataToFormsSkipsFormsInheritingParentData()
{ {
$car = new \stdClass(); $car = new \stdClass();
$engine = new \stdClass(); $engine = new \stdClass();
@ -195,7 +195,7 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
$config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher);
$config->setByReference(true); $config->setByReference(true);
$config->setVirtual(true); $config->setInheritData(true);
$config->setCompound(true); $config->setCompound(true);
$config->setDataMapper($this->getDataMapper()); $config->setDataMapper($this->getDataMapper());
$form = $this->getForm($config); $form = $this->getForm($config);
@ -348,7 +348,7 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
$this->mapper->mapFormsToData(array($form), $car); $this->mapper->mapFormsToData(array($form), $car);
} }
public function testMapFormsToDataSkipsVirtualForms() public function testMapFormsToDataSkipsFormsInheritingParentData()
{ {
$car = new \stdClass(); $car = new \stdClass();
$engine = new \stdClass(); $engine = new \stdClass();
@ -366,7 +366,7 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
$config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher);
$config->setPropertyPath($parentPath); $config->setPropertyPath($parentPath);
$config->setVirtual(true); $config->setInheritData(true);
$config->setCompound(true); $config->setCompound(true);
$config->setDataMapper($this->getDataMapper()); $config->setDataMapper($this->getDataMapper());
$form = $this->getForm($config); $form = $this->getForm($config);

View File

@ -71,13 +71,13 @@ class ViolationMapperTest extends \PHPUnit_Framework_TestCase
$this->params = array('foo' => 'bar'); $this->params = array('foo' => 'bar');
} }
protected function getForm($name = 'name', $propertyPath = null, $dataClass = null, $errorMapping = array(), $virtual = false, $synchronized = true) protected function getForm($name = 'name', $propertyPath = null, $dataClass = null, $errorMapping = array(), $inheritData = false, $synchronized = true)
{ {
$config = new FormConfigBuilder($name, $dataClass, $this->dispatcher, array( $config = new FormConfigBuilder($name, $dataClass, $this->dispatcher, array(
'error_mapping' => $errorMapping, 'error_mapping' => $errorMapping,
)); ));
$config->setMapped(true); $config->setMapped(true);
$config->setVirtual($virtual); $config->setInheritData($inheritData);
$config->setPropertyPath($propertyPath); $config->setPropertyPath($propertyPath);
$config->setCompound(true); $config->setCompound(true);
$config->setDataMapper($this->getDataMapper()); $config->setDataMapper($this->getDataMapper());
@ -118,7 +118,7 @@ class ViolationMapperTest extends \PHPUnit_Framework_TestCase
return new FormError($this->message, $this->messageTemplate, $this->params); return new FormError($this->message, $this->messageTemplate, $this->params);
} }
public function testMapToVirtualFormIfDataDoesNotMatch() public function testMapToFormInheritingParentDataIfDataDoesNotMatch()
{ {
$violation = $this->getConstraintViolation('children[address].data.foo'); $violation = $this->getConstraintViolation('children[address].data.foo');
$parent = $this->getForm('parent'); $parent = $this->getForm('parent');
@ -183,7 +183,7 @@ class ViolationMapperTest extends \PHPUnit_Framework_TestCase
$this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one'); $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one');
} }
public function testAbortVirtualFormMappingIfNotSynchronized() public function testAbortFormInheritingParentDataMappingIfNotSynchronized()
{ {
$violation = $this->getConstraintViolation('children[address].children[street].data.foo'); $violation = $this->getConstraintViolation('children[address].children[street].data.foo');
$parent = $this->getForm('parent'); $parent = $this->getForm('parent');
@ -1446,7 +1446,7 @@ class ViolationMapperTest extends \PHPUnit_Framework_TestCase
} }
} }
public function provideVirtualFormErrorTests() public function provideFormInheritingParentDataErrorTests()
{ {
return array( return array(
// mapping target, child name, its property path, grand child name, its property path, violation path // mapping target, child name, its property path, grand child name, its property path, violation path
@ -1472,9 +1472,9 @@ class ViolationMapperTest extends \PHPUnit_Framework_TestCase
} }
/** /**
* @dataProvider provideVirtualFormErrorTests * @dataProvider provideFormInheritingParentDataErrorTests
*/ */
public function testVirtualFormErrorMapping($target, $childName, $childPath, $grandChildName, $grandChildPath, $violationPath) public function testFormInheritingParentDataErrorMapping($target, $childName, $childPath, $grandChildName, $grandChildPath, $violationPath)
{ {
$violation = $this->getConstraintViolation($violationPath); $violation = $this->getConstraintViolation($violationPath);
$parent = $this->getForm('parent'); $parent = $this->getForm('parent');

View File

@ -12,10 +12,11 @@
namespace Symfony\Component\Form\Util; namespace Symfony\Component\Form\Util;
/** /**
* Iterator that traverses fields of a field group * Iterator that returns only forms from a form tree that do not inherit their
* parent data.
* *
* If the iterator encounters a virtual field group, it enters the field * If the iterator encounters a form that inherits its parent data, it enters
* group and traverses its children as well. * the form and traverses its children as well.
* *
* @author Bernhard Schussek <bschussek@gmail.com> * @author Bernhard Schussek <bschussek@gmail.com>
*/ */
@ -28,6 +29,6 @@ class VirtualFormAwareIterator extends \ArrayIterator implements \RecursiveItera
public function hasChildren() public function hasChildren()
{ {
return $this->current()->getConfig()->getVirtual(); return $this->current()->getConfig()->getInheritData();
} }
} }