diff --git a/UPGRADE-2.3.md b/UPGRADE-2.3.md index f58f837b64..1f43bf1aab 100644 --- a/UPGRADE-2.3.md +++ b/UPGRADE-2.3.md @@ -1,4 +1,4 @@ -UPGRADE FROM 2.2 to 2.3 +UPGRADE FROM 2.2 to 2.3 ======================= ### Form @@ -35,6 +35,79 @@ UPGRADE FROM 2.2 to 2.3 "validation_groups" => false "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 diff --git a/UPGRADE-3.0.md b/UPGRADE-3.0.md index 42b0542845..580c8e8b42 100644 --- a/UPGRADE-3.0.md +++ b/UPGRADE-3.0.md @@ -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 * The `enctype` method of the `form` helper was removed. You should use the diff --git a/src/Symfony/Component/Form/ButtonBuilder.php b/src/Symfony/Component/Form/ButtonBuilder.php index fb77ef00ff..66ce61ab53 100644 --- a/src/Symfony/Component/Form/ButtonBuilder.php +++ b/src/Symfony/Component/Form/ButtonBuilder.php @@ -492,6 +492,18 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface 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. * @@ -759,6 +771,16 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface return null; } + /** + * Unsupported method. + * + * @return null Always returns null. + */ + public function getInheritData() + { + return null; + } + /** * Returns all options passed during the construction of the button. * diff --git a/src/Symfony/Component/Form/CHANGELOG.md b/src/Symfony/Component/Form/CHANGELOG.md index 40976fa8d0..b7b6b08245 100644 --- a/src/Symfony/Component/Form/CHANGELOG.md +++ b/src/Symfony/Component/Form/CHANGELOG.md @@ -9,6 +9,7 @@ CHANGELOG * added FormProcessorInterface and FormInterface::process() * deprecated passing a Request instance to FormInterface::bind() * added options "method" and "action" to FormType + * deprecated option "virtual", renamed it to "inherit_data" 2.2.0 ----- diff --git a/src/Symfony/Component/Form/Extension/Core/DataMapper/PropertyPathMapper.php b/src/Symfony/Component/Form/Extension/Core/DataMapper/PropertyPathMapper.php index f691ecca21..cb59baa075 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataMapper/PropertyPathMapper.php +++ b/src/Symfony/Component/Form/Extension/Core/DataMapper/PropertyPathMapper.php @@ -56,7 +56,7 @@ class PropertyPathMapper implements DataMapperInterface $iterator = new \RecursiveIteratorIterator($iterator); foreach ($iterator as $form) { - /* @var FormInterface $form */ + /* @var \Symfony\Component\Form\FormInterface $form */ $propertyPath = $form->getPropertyPath(); $config = $form->getConfig(); @@ -83,7 +83,7 @@ class PropertyPathMapper implements DataMapperInterface $iterator = new \RecursiveIteratorIterator($iterator); foreach ($iterator as $form) { - /* @var FormInterface $form */ + /* @var \Symfony\Component\Form\FormInterface $form */ $propertyPath = $form->getPropertyPath(); $config = $form->getConfig(); diff --git a/src/Symfony/Component/Form/Extension/Core/Type/FormType.php b/src/Symfony/Component/Form/Extension/Core/Type/FormType.php index e51dba870e..31835357c1 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/FormType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/FormType.php @@ -48,7 +48,7 @@ class FormType extends BaseType ->setPropertyPath($options['property_path']) ->setMapped($options['mapped']) ->setByReference($options['by_reference']) - ->setVirtual($options['virtual']) + ->setInheritData($options['inherit_data']) ->setCompound($options['compound']) ->setData(isset($options['data']) ? $options['data'] : null) ->setDataLocked(isset($options['data'])) @@ -95,8 +95,8 @@ class FormType extends BaseType 'size' => null, 'label_attr' => $options['label_attr'], 'compound' => $form->getConfig()->getCompound(), - 'method' => $form->getConfig()->getMethod(), - 'action' => $form->getConfig()->getAction(), + 'method' => $form->getConfig()->getMethod(), + 'action' => $form->getConfig()->getAction(), )); } @@ -169,7 +169,7 @@ class FormType extends BaseType 'by_reference' => true, 'error_bubbling' => $errorBubbling, 'label_attr' => array(), - 'virtual' => false, + 'inherit_data' => false, 'compound' => true, 'method' => 'POST', // According to RFC 2396 (http://www.ietf.org/rfc/rfc2396.txt) diff --git a/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapper.php b/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapper.php index 1c1e64f94f..4eb9126b6b 100644 --- a/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapper.php +++ b/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapper.php @@ -88,8 +88,8 @@ class ViolationMapper implements ViolationMapperInterface } // This case happens if an error happened in the data under a - // virtual form that does not match any of the children of - // the virtual form. + // form inheriting its parent data that does not match any of the + // children of that form. if (null !== $violationPath && !$match) { // If we could not map the error to anything more specific // 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( new VirtualFormAwareIterator($form->all()) ); @@ -253,8 +253,8 @@ class ViolationMapper implements ViolationMapperInterface // Process child form $scope = $scope->get($it->current()); - if ($scope->getConfig()->getVirtual()) { - // Form is virtual + if ($scope->getConfig()->getInheritData()) { + // Form inherits its parent data // Cut the piece out of the property path and proceed $propertyPathBuilder->remove($i); } elseif (!$scope->getConfig()->getMapped()) { diff --git a/src/Symfony/Component/Form/FormConfigBuilder.php b/src/Symfony/Component/Form/FormConfigBuilder.php index 694b94555e..26cea6b7f4 100644 --- a/src/Symfony/Component/Form/FormConfigBuilder.php +++ b/src/Symfony/Component/Form/FormConfigBuilder.php @@ -80,7 +80,7 @@ class FormConfigBuilder implements FormConfigBuilderInterface /** * @var Boolean */ - private $virtual = false; + private $inheritData = false; /** * @var Boolean @@ -341,9 +341,24 @@ class FormConfigBuilder implements FormConfigBuilderInterface /** * {@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() { - 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} */ - public function setVirtual($virtual) + public function setInheritData($inheritData) { if ($this->locked) { 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; } + /** + * 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} */ diff --git a/src/Symfony/Component/Form/FormConfigBuilderInterface.php b/src/Symfony/Component/Form/FormConfigBuilderInterface.php index 34b217e623..a35be27db2 100644 --- a/src/Symfony/Component/Form/FormConfigBuilderInterface.php +++ b/src/Symfony/Component/Form/FormConfigBuilderInterface.php @@ -180,13 +180,13 @@ interface FormConfigBuilderInterface extends FormConfigInterface 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. */ - public function setVirtual($virtual); + public function setInheritData($inheritData); /** * Sets whether the form should be compound. diff --git a/src/Symfony/Component/Form/FormConfigInterface.php b/src/Symfony/Component/Form/FormConfigInterface.php index e00ce27f43..3aa00d4dbd 100644 --- a/src/Symfony/Component/Form/FormConfigInterface.php +++ b/src/Symfony/Component/Form/FormConfigInterface.php @@ -55,15 +55,11 @@ interface FormConfigInterface 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 - * should ignore virtual forms and map to the children of the - * virtual form instead. - * - * @return Boolean Whether the form is virtual. + * @return Boolean Whether the form should inherit its parent's data. */ - public function getVirtual(); + public function getInheritData(); /** * Returns whether the form is compound. diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php index 8af2fd5f07..32ef587862 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php @@ -182,7 +182,7 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase $this->assertNull($form->getData()); } - public function testMapDataToFormsSkipsVirtualForms() + public function testMapDataToFormsSkipsFormsInheritingParentData() { $car = new \stdClass(); $engine = new \stdClass(); @@ -195,7 +195,7 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(true); - $config->setVirtual(true); + $config->setInheritData(true); $config->setCompound(true); $config->setDataMapper($this->getDataMapper()); $form = $this->getForm($config); @@ -348,7 +348,7 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase $this->mapper->mapFormsToData(array($form), $car); } - public function testMapFormsToDataSkipsVirtualForms() + public function testMapFormsToDataSkipsFormsInheritingParentData() { $car = new \stdClass(); $engine = new \stdClass(); @@ -366,7 +366,7 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setPropertyPath($parentPath); - $config->setVirtual(true); + $config->setInheritData(true); $config->setCompound(true); $config->setDataMapper($this->getDataMapper()); $form = $this->getForm($config); diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php index 83a5db6e10..516b62299d 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php @@ -71,13 +71,13 @@ class ViolationMapperTest extends \PHPUnit_Framework_TestCase $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( 'error_mapping' => $errorMapping, )); $config->setMapped(true); - $config->setVirtual($virtual); + $config->setInheritData($inheritData); $config->setPropertyPath($propertyPath); $config->setCompound(true); $config->setDataMapper($this->getDataMapper()); @@ -118,7 +118,7 @@ class ViolationMapperTest extends \PHPUnit_Framework_TestCase return new FormError($this->message, $this->messageTemplate, $this->params); } - public function testMapToVirtualFormIfDataDoesNotMatch() + public function testMapToFormInheritingParentDataIfDataDoesNotMatch() { $violation = $this->getConstraintViolation('children[address].data.foo'); $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'); } - public function testAbortVirtualFormMappingIfNotSynchronized() + public function testAbortFormInheritingParentDataMappingIfNotSynchronized() { $violation = $this->getConstraintViolation('children[address].children[street].data.foo'); $parent = $this->getForm('parent'); @@ -1446,7 +1446,7 @@ class ViolationMapperTest extends \PHPUnit_Framework_TestCase } } - public function provideVirtualFormErrorTests() + public function provideFormInheritingParentDataErrorTests() { return array( // 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); $parent = $this->getForm('parent'); diff --git a/src/Symfony/Component/Form/Util/VirtualFormAwareIterator.php b/src/Symfony/Component/Form/Util/VirtualFormAwareIterator.php index c1322bb35d..92e9da0d51 100644 --- a/src/Symfony/Component/Form/Util/VirtualFormAwareIterator.php +++ b/src/Symfony/Component/Form/Util/VirtualFormAwareIterator.php @@ -12,10 +12,11 @@ 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 - * group and traverses its children as well. + * If the iterator encounters a form that inherits its parent data, it enters + * the form and traverses its children as well. * * @author Bernhard Schussek */ @@ -28,6 +29,6 @@ class VirtualFormAwareIterator extends \ArrayIterator implements \RecursiveItera public function hasChildren() { - return $this->current()->getConfig()->getVirtual(); + return $this->current()->getConfig()->getInheritData(); } }