Merge branch 'form-submit-2.2' into form-submit-2.3
Conflicts: src/Symfony/Component/Form/Form.php src/Symfony/Component/Form/Tests/AbstractFormTest.php src/Symfony/Component/Form/Tests/CompoundFormTest.php src/Symfony/Component/Form/Util/VirtualFormAwareIterator.php
This commit is contained in:
commit
5d60a4fa0a
@ -536,7 +536,10 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
$submittedData = array();
|
||||
}
|
||||
|
||||
foreach ($this->children as $name => $child) {
|
||||
for (reset($this->children); false !== current($this->children); next($this->children)) {
|
||||
$child = current($this->children);
|
||||
$name = key($this->children);
|
||||
|
||||
if (array_key_exists($name, $submittedData) || $clearMissing) {
|
||||
$child->submit(isset($submittedData[$name]) ? $submittedData[$name] : null, $clearMissing);
|
||||
unset($submittedData[$name]);
|
||||
@ -762,7 +765,7 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function all()
|
||||
public function &all()
|
||||
{
|
||||
return $this->children;
|
||||
}
|
||||
@ -833,7 +836,8 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
$child->setParent($this);
|
||||
|
||||
if (!$this->lockSetData && $this->defaultDataSet && !$this->config->getInheritData()) {
|
||||
$childrenIterator = new InheritDataAwareIterator(array($child));
|
||||
$children = array($child);
|
||||
$childrenIterator = new InheritDataAwareIterator($children);
|
||||
$childrenIterator = new \RecursiveIteratorIterator($childrenIterator);
|
||||
$this->config->getDataMapper()->mapDataToForms($viewData, $childrenIterator);
|
||||
}
|
||||
|
@ -399,6 +399,34 @@ class CompoundFormTest extends AbstractFormTest
|
||||
$form->setData('foo');
|
||||
}
|
||||
|
||||
public function testSubmitSupportsDynamicAdditionAndRemovalOfChildren()
|
||||
{
|
||||
$child = $this->getMockForm('child');
|
||||
$childToBeRemoved = $this->getMockForm('removed');
|
||||
$childToBeAdded = $this->getMockForm('added');
|
||||
|
||||
$this->form->add($child);
|
||||
$this->form->add($childToBeRemoved);
|
||||
|
||||
$form = $this->form;
|
||||
|
||||
$child->expects($this->once())
|
||||
->method('submit')
|
||||
->will($this->returnCallback(function () use ($form, $childToBeAdded) {
|
||||
$form->remove('removed');
|
||||
$form->add($childToBeAdded);
|
||||
}));
|
||||
|
||||
$childToBeRemoved->expects($this->never())
|
||||
->method('submit');
|
||||
|
||||
$childToBeAdded->expects($this->once())
|
||||
->method('submit');
|
||||
|
||||
// pass NULL to all children
|
||||
$this->form->submit(array());
|
||||
}
|
||||
|
||||
public function testSubmitMapsSubmittedChildrenOntoExistingViewData()
|
||||
{
|
||||
$test = $this;
|
||||
|
@ -0,0 +1,122 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form\Tests\Util;
|
||||
|
||||
use Symfony\Component\Form\Util\InheritDataAwareIterator;
|
||||
|
||||
/**
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class InheritDataAwareIteratorTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testSupportDynamicModification()
|
||||
{
|
||||
$form = $this->getMockForm('form');
|
||||
$formToBeAdded = $this->getMockForm('added');
|
||||
$formToBeRemoved = $this->getMockForm('removed');
|
||||
|
||||
$forms = array('form' => $form, 'removed' => $formToBeRemoved);
|
||||
$iterator = new InheritDataAwareIterator($forms);
|
||||
|
||||
$iterator->rewind();
|
||||
$this->assertTrue($iterator->valid());
|
||||
$this->assertSame('form', $iterator->key());
|
||||
$this->assertSame($form, $iterator->current());
|
||||
|
||||
// dynamic modification
|
||||
unset($forms['removed']);
|
||||
$forms['added'] = $formToBeAdded;
|
||||
|
||||
// continue iteration
|
||||
$iterator->next();
|
||||
$this->assertTrue($iterator->valid());
|
||||
$this->assertSame('added', $iterator->key());
|
||||
$this->assertSame($formToBeAdded, $iterator->current());
|
||||
|
||||
// end of array
|
||||
$iterator->next();
|
||||
$this->assertFalse($iterator->valid());
|
||||
}
|
||||
|
||||
public function testSupportDynamicModificationInRecursiveCall()
|
||||
{
|
||||
$inheritingForm = $this->getMockForm('inheriting');
|
||||
$form = $this->getMockForm('form');
|
||||
$formToBeAdded = $this->getMockForm('added');
|
||||
$formToBeRemoved = $this->getMockForm('removed');
|
||||
|
||||
$inheritingForm->getConfig()->expects($this->any())
|
||||
->method('getInheritData')
|
||||
->will($this->returnValue(true));
|
||||
|
||||
$inheritingForm->add($form);
|
||||
$inheritingForm->add($formToBeRemoved);
|
||||
|
||||
$forms = array('inheriting' => $inheritingForm);
|
||||
$iterator = new InheritDataAwareIterator($forms);
|
||||
|
||||
$iterator->rewind();
|
||||
$this->assertTrue($iterator->valid());
|
||||
$this->assertSame('inheriting', $iterator->key());
|
||||
$this->assertSame($inheritingForm, $iterator->current());
|
||||
$this->assertTrue($iterator->hasChildren());
|
||||
|
||||
// enter nested iterator
|
||||
$nestedIterator = $iterator->getChildren();
|
||||
$this->assertSame('form', $nestedIterator->key());
|
||||
$this->assertSame($form, $nestedIterator->current());
|
||||
$this->assertFalse($nestedIterator->hasChildren());
|
||||
|
||||
// dynamic modification
|
||||
$inheritingForm->remove('removed');
|
||||
$inheritingForm->add($formToBeAdded);
|
||||
|
||||
// continue iteration - nested iterator discovers change in the form
|
||||
$nestedIterator->next();
|
||||
$this->assertTrue($nestedIterator->valid());
|
||||
$this->assertSame('added', $nestedIterator->key());
|
||||
$this->assertSame($formToBeAdded, $nestedIterator->current());
|
||||
|
||||
// end of array
|
||||
$nestedIterator->next();
|
||||
$this->assertFalse($nestedIterator->valid());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*
|
||||
* @return \PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected function getMockForm($name = 'name')
|
||||
{
|
||||
$config = $this->getMock('Symfony\Component\Form\FormConfigInterface');
|
||||
|
||||
$config->expects($this->any())
|
||||
->method('getName')
|
||||
->will($this->returnValue($name));
|
||||
$config->expects($this->any())
|
||||
->method('getCompound')
|
||||
->will($this->returnValue(true));
|
||||
$config->expects($this->any())
|
||||
->method('getDataMapper')
|
||||
->will($this->returnValue($this->getMock('Symfony\Component\Form\DataMapperInterface')));
|
||||
$config->expects($this->any())
|
||||
->method('getEventDispatcher')
|
||||
->will($this->returnValue($this->getMock('Symfony\Component\EventDispatcher\EventDispatcher')));
|
||||
|
||||
return $this->getMockBuilder('Symfony\Component\Form\Form')
|
||||
->setConstructorArgs(array($config))
|
||||
->disableArgumentCloning()
|
||||
->setMethods(array('getViewData'))
|
||||
->getMock();
|
||||
}
|
||||
}
|
@ -12,24 +12,17 @@
|
||||
namespace Symfony\Component\Form\Util;
|
||||
|
||||
/**
|
||||
* Iterator that returns only forms from a form tree that do not inherit their
|
||||
* parent data.
|
||||
* Iterator that traverses an array of forms.
|
||||
*
|
||||
* If the iterator encounters a form that inherits its parent data, it enters
|
||||
* the form and traverses its children as well.
|
||||
* Contrary to \ArrayIterator, this iterator recognizes changes in the original
|
||||
* array during iteration.
|
||||
*
|
||||
* You can wrap the iterator into a {@link \RecursiveIterator} in order to
|
||||
* enter any child form that inherits its parent's data and iterate the children
|
||||
* of that form as well.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class InheritDataAwareIterator extends VirtualFormAwareIterator
|
||||
{
|
||||
/**
|
||||
* Creates a new iterator.
|
||||
*
|
||||
* @param \Symfony\Component\Form\FormInterface[] $forms An array
|
||||
*/
|
||||
public function __construct(array $forms)
|
||||
{
|
||||
// Skip the deprecation error
|
||||
\ArrayIterator::__construct($forms);
|
||||
}
|
||||
}
|
||||
|
@ -12,39 +12,93 @@
|
||||
namespace Symfony\Component\Form\Util;
|
||||
|
||||
/**
|
||||
* Iterator that returns only forms from a form tree that do not inherit their
|
||||
* parent data.
|
||||
* Iterator that traverses an array of forms.
|
||||
*
|
||||
* If the iterator encounters a form that inherits its parent data, it enters
|
||||
* the form and traverses its children as well.
|
||||
* Contrary to \ArrayIterator, this iterator recognizes changes in the original
|
||||
* array during iteration.
|
||||
*
|
||||
* You can wrap the iterator into a {@link \RecursiveIterator} in order to
|
||||
* enter any child form that inherits its parent's data and iterate the children
|
||||
* of that form as well.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*
|
||||
* @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
|
||||
* {@link InheritDataAwareIterator} instead.
|
||||
*/
|
||||
class VirtualFormAwareIterator extends \ArrayIterator implements \RecursiveIterator
|
||||
class VirtualFormAwareIterator implements \RecursiveIterator
|
||||
{
|
||||
/**
|
||||
* @var \Symfony\Component\Form\FormInterface[]
|
||||
*/
|
||||
private $forms;
|
||||
|
||||
/**
|
||||
* Creates a new iterator.
|
||||
*
|
||||
* @param \Symfony\Component\Form\FormInterface[] $forms An array
|
||||
* @param \Symfony\Component\Form\FormInterface[] $forms An array of forms
|
||||
*/
|
||||
public function __construct(array $forms)
|
||||
public function __construct(array &$forms)
|
||||
{
|
||||
// Uncomment this as soon as the deprecation note should be shown
|
||||
// trigger_error('VirtualFormAwareIterator is deprecated since version 2.3 and will be removed in 3.0. Use InheritDataAwareIterator instead.', E_USER_DEPRECATED);
|
||||
|
||||
parent::__construct($forms);
|
||||
$this->forms = &$forms;
|
||||
}
|
||||
|
||||
/**
|
||||
*{@inheritdoc}
|
||||
*/
|
||||
public function current()
|
||||
{
|
||||
return current($this->forms);
|
||||
}
|
||||
|
||||
/**
|
||||
*{@inheritdoc}
|
||||
*/
|
||||
public function next()
|
||||
{
|
||||
next($this->forms);
|
||||
}
|
||||
|
||||
/**
|
||||
*{@inheritdoc}
|
||||
*/
|
||||
public function key()
|
||||
{
|
||||
return key($this->forms);
|
||||
}
|
||||
|
||||
/**
|
||||
*{@inheritdoc}
|
||||
*/
|
||||
public function valid()
|
||||
{
|
||||
return null !== key($this->forms);
|
||||
}
|
||||
|
||||
/**
|
||||
*{@inheritdoc}
|
||||
*/
|
||||
public function rewind()
|
||||
{
|
||||
reset($this->forms);
|
||||
}
|
||||
|
||||
/**
|
||||
*{@inheritdoc}
|
||||
*/
|
||||
public function getChildren()
|
||||
{
|
||||
return new static($this->current()->all());
|
||||
}
|
||||
|
||||
/**
|
||||
*{@inheritdoc}
|
||||
*/
|
||||
public function hasChildren()
|
||||
{
|
||||
return $this->current()->getConfig()->getInheritData();
|
||||
return (bool) $this->current()->getConfig()->getInheritData();
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user