Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

[Form] Added an alternative signature Form::add($name, $type, $options)

  • Loading branch information...
commit fb71964adc69690844fca1dd2a035dac24eaa8a9 1 parent d9f7844
@webmozart webmozart authored
View
9 UPGRADE-2.2.md
@@ -37,7 +37,14 @@
### Form
- * The PasswordType is now not trimmed by default.
+ * The PasswordType is now not trimmed by default.
+
+#### Deprecations
+
+ * The methods `getParent()`, `setParent()` and `hasParent()` in
+ `FormBuilderInterface` were deprecated and will be removed in Symfony 2.3.
+ You should not rely on these methods in your form type because the parent
+ of a form can change after building it.
### Routing
View
7 src/Symfony/Bridge/Propel1/Form/EventListener/TranslationFormListener.php
@@ -11,7 +11,6 @@
namespace Symfony\Bridge\Propel1\Form\EventListener;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
-use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
@@ -24,13 +23,11 @@ class TranslationFormListener implements EventSubscriberInterface
{
private $columns;
private $dataClass;
- private $formFactory;
- public function __construct(FormFactoryInterface $formFactory, $columns, $dataClass)
+ public function __construct($columns, $dataClass)
{
$this->columns = $columns;
$this->dataClass = $dataClass;
- $this->formFactory = $formFactory;
}
public static function getSubscribedEvents()
@@ -78,7 +75,7 @@ public function preSetData(FormEvent $event)
$options = array_merge($options, $customOptions);
- $form->add($this->formFactory->createNamed($column, $type, null, $options));
+ $form->add($column, $type, $options);
}
}
}
View
5 src/Symfony/Bridge/Propel1/Form/Type/TranslationType.php
@@ -28,8 +28,9 @@ class TranslationType extends AbstractType
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
- $listener = new TranslationFormListener($builder->getFormFactory(), $options['columns'], $options['data_class']);
- $builder->addEventSubscriber($listener);
+ $builder->addEventSubscriber(
+ new TranslationFormListener($options['columns'], $options['data_class'])
+ );
}
/**
View
2  src/Symfony/Component/Form/CHANGELOG.md
@@ -5,6 +5,8 @@ CHANGELOG
-----
* TrimListener now removes unicode whitespaces
+ * deprecated getParent(), setParent() and hasParent() in FormBuilderInterface
+ * FormInterface::add() now accepts a FormInterface instance OR a field's name, type and options
2.1.0
-----
View
17 src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php
@@ -13,7 +13,6 @@
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
-use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\Form\Exception\UnexpectedTypeException;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
@@ -25,11 +24,6 @@
class ResizeFormListener implements EventSubscriberInterface
{
/**
- * @var FormFactoryInterface
- */
- protected $factory;
-
- /**
* @var string
*/
protected $type;
@@ -51,9 +45,8 @@ class ResizeFormListener implements EventSubscriberInterface
*/
protected $allowDelete;
- public function __construct(FormFactoryInterface $factory, $type, array $options = array(), $allowAdd = false, $allowDelete = false)
+ public function __construct($type, array $options = array(), $allowAdd = false, $allowDelete = false)
{
- $this->factory = $factory;
$this->type = $type;
$this->allowAdd = $allowAdd;
$this->allowDelete = $allowDelete;
@@ -90,9 +83,9 @@ public function preSetData(FormEvent $event)
// Then add all rows again in the correct order
foreach ($data as $name => $value) {
- $form->add($this->factory->createNamed($name, $this->type, null, array_replace(array(
+ $form->add((string) $name, $this->type, array_replace(array(
'property_path' => '['.$name.']',
- ), $this->options)));
+ ), $this->options));
}
}
@@ -122,9 +115,9 @@ public function preBind(FormEvent $event)
if ($this->allowAdd) {
foreach ($data as $name => $value) {
if (!$form->has($name)) {
- $form->add($this->factory->createNamed($name, $this->type, null, array_replace(array(
+ $form->add((string) $name, $this->type, array_replace(array(
'property_path' => '['.$name.']',
- ), $this->options)));
+ ), $this->options));
}
}
}
View
1  src/Symfony/Component/Form/Extension/Core/Type/CollectionType.php
@@ -34,7 +34,6 @@ public function buildForm(FormBuilderInterface $builder, array $options)
}
$resizeListener = new ResizeFormListener(
- $builder->getFormFactory(),
$options['type'],
$options['options'],
$options['allow_add'],
View
19 src/Symfony/Component/Form/Form.php
@@ -12,6 +12,7 @@
namespace Symfony\Component\Form;
use Symfony\Component\Form\Exception\FormException;
+use Symfony\Component\Form\Exception\UnexpectedTypeException;
use Symfony\Component\Form\Exception\AlreadyBoundException;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Symfony\Component\Form\Util\FormUtil;
@@ -859,7 +860,7 @@ public function hasChildren()
/**
* {@inheritdoc}
*/
- public function add(FormInterface $child)
+ public function add($child, $type = null, array $options = array())
{
if ($this->bound) {
throw new AlreadyBoundException('You cannot add children to a bound form');
@@ -888,6 +889,22 @@ public function add(FormInterface $child)
$viewData = $this->getViewData();
}
+ if (!$child instanceof FormInterface) {
+ if (!is_string($child)) {
+ throw new UnexpectedTypeException($child, 'string or Symfony\Component\Form\FormInterface');
+ }
+
+ if (null !== $type && !is_string($type) && !$type instanceof FormTypeInterface) {
+ throw new UnexpectedTypeException($type, 'string or Symfony\Component\Form\FormTypeInterface');
+ }
+
+ if (null === $type) {
+ $child = $this->config->getFormFactory()->createForProperty($this->config->getDataClass(), $child, null, $options);
+ } else {
+ $child = $this->config->getFormFactory()->createNamed($child, $type, null, $options);
+ }
+ }
+
$this->children[$child->getName()] = $child;
$child->setParent($this);
View
21 src/Symfony/Component/Form/FormBuilder.php
@@ -23,13 +23,6 @@
class FormBuilder extends FormConfigBuilder implements \IteratorAggregate, FormBuilderInterface
{
/**
- * The form factory.
- *
- * @var FormFactoryInterface
- */
- private $factory;
-
- /**
* The children of the form builder.
*
* @var array
@@ -63,15 +56,7 @@ public function __construct($name, $dataClass, EventDispatcherInterface $dispatc
{
parent::__construct($name, $dataClass, $dispatcher, $options);
- $this->factory = $factory;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getFormFactory()
- {
- return $this->factory;
+ $this->setFormFactory($factory);
}
/**
@@ -125,10 +110,10 @@ public function create($name, $type = null, array $options = array())
}
if (null !== $type) {
- return $this->factory->createNamedBuilder($name, $type, null, $options, $this);
+ return $this->getFormFactory()->createNamedBuilder($name, $type, null, $options, $this);
}
- return $this->factory->createBuilderForProperty($this->getDataClass(), $name, null, $options, $this);
+ return $this->getFormFactory()->createBuilderForProperty($this->getDataClass(), $name, null, $options, $this);
}
/**
View
23 src/Symfony/Component/Form/FormBuilderInterface.php
@@ -52,6 +52,7 @@ public function create($name, $type = null, array $options = array());
* @throws Exception\FormException if the given child does not exist
*/
public function get($name);
+
/**
* Removes the field with the given name.
*
@@ -78,13 +79,6 @@ public function has($name);
public function all();
/**
- * Returns the associated form factory.
- *
- * @return FormFactoryInterface The factory
- */
- public function getFormFactory();
-
- /**
* Creates the form.
*
* @return Form The form
@@ -97,6 +91,11 @@ public function getForm();
* @param FormBuilderInterface $parent The parent builder
*
* @return FormBuilderInterface The builder object.
+ *
+ * @deprecated Deprecated since version 2.2, to be removed in 2.3. You
+ * should not rely on the parent of a builder, because it is
+ * likely that the parent is only set after turning the builder
+ * into a form.
*/
public function setParent(FormBuilderInterface $parent = null);
@@ -104,6 +103,11 @@ public function setParent(FormBuilderInterface $parent = null);
* Returns the parent builder.
*
* @return FormBuilderInterface The parent builder
+ *
+ * @deprecated Deprecated since version 2.2, to be removed in 2.3. You
+ * should not rely on the parent of a builder, because it is
+ * likely that the parent is only set after turning the builder
+ * into a form.
*/
public function getParent();
@@ -111,6 +115,11 @@ public function getParent();
* Returns whether the builder has a parent.
*
* @return Boolean
+ *
+ * @deprecated Deprecated since version 2.2, to be removed in 2.3. You
+ * should not rely on the parent of a builder, because it is
+ * likely that the parent is only set after turning the builder
+ * into a form.
*/
public function hasParent();
}
View
27 src/Symfony/Component/Form/FormConfigBuilder.php
@@ -132,6 +132,11 @@ class FormConfigBuilder implements FormConfigBuilderInterface
private $dataLocked;
/**
+ * @var FormFactoryInterface
+ */
+ private $formFactory;
+
+ /**
* @var array
*/
private $options;
@@ -614,6 +619,14 @@ public function getDataLocked()
/**
* {@inheritdoc}
*/
+ public function getFormFactory()
+ {
+ return $this->formFactory;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
public function getOptions()
{
return $this->options;
@@ -852,6 +865,20 @@ public function setDataLocked($locked)
/**
* {@inheritdoc}
*/
+ public function setFormFactory(FormFactoryInterface $formFactory)
+ {
+ if ($this->locked) {
+ throw new FormException('The config builder cannot be modified anymore.');
+ }
+
+ $this->formFactory = $formFactory;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
public function getFormConfig()
{
// This method should be idempotent, so clone the builder
View
7 src/Symfony/Component/Form/FormConfigBuilderInterface.php
@@ -242,6 +242,13 @@ public function setData($data);
public function setDataLocked($locked);
/**
+ * Sets the form factory used for creating new forms.
+ *
+ * @param FormFactoryInterface $formFactory The form factory.
+ */
+ public function setFormFactory(FormFactoryInterface $formFactory);
+
+ /**
* Builds and returns the form configuration.
*
* @return FormConfigInterface
View
7 src/Symfony/Component/Form/FormConfigInterface.php
@@ -193,6 +193,13 @@ public function getDataClass();
public function getDataLocked();
/**
+ * Returns the form factory used for creating new forms.
+ *
+ * @return FormFactoryInterface The form factory.
+ */
+ public function getFormFactory();
+
+ /**
* Returns all options passed during the construction of the form.
*
* @return array The passed options.
View
11 src/Symfony/Component/Form/FormInterface.php
@@ -41,14 +41,17 @@ public function getParent();
/**
* Adds a child to the form.
*
- * @param FormInterface $child The FormInterface to add as a child
+ * @param FormInterface|string $child The FormInterface instance or the name of the child.
+ * @param string|null $type The child's type, if a name was passed.
+ * @param array $options The child's options, if a name was passed.
*
* @return FormInterface The form instance
*
- * @throws Exception\AlreadyBoundException If the form has already been bound.
- * @throws Exception\FormException When trying to add a child to a non-compound form.
+ * @throws Exception\AlreadyBoundException If the form has already been bound.
+ * @throws Exception\FormException When trying to add a child to a non-compound form.
+ * @throws Exception\UnexpectedTypeException If $child or $type has an unexpected type.
*/
- public function add(FormInterface $child);
+ public function add($child, $type = null, array $options = array());
/**
* Returns the child with the given name.
View
65 src/Symfony/Component/Form/Tests/CompoundFormTest.php
@@ -33,7 +33,7 @@ public function testValidIfAllChildrenAreValid()
$this->assertTrue($this->form->isValid());
}
- public function testInvalidIfChildrenIsInvalid()
+ public function testInvalidIfChildIsInvalid()
{
$this->form->add($this->getValidForm('firstName'));
$this->form->add($this->getInvalidForm('lastName'));
@@ -135,12 +135,71 @@ public function testAdd()
$child = $this->getBuilder('foo')->getForm();
$this->form->add($child);
+ $this->assertTrue($this->form->has('foo'));
+ $this->assertSame($this->form, $child->getParent());
+ $this->assertSame(array('foo' => $child), $this->form->all());
+ }
+
+ public function testAddUsingNameAndType()
+ {
+ $child = $this->getBuilder('foo')->getForm();
+
+ $this->factory->expects($this->once())
+ ->method('createNamed')
+ ->with('foo', 'text', null, array('bar' => 'baz'))
+ ->will($this->returnValue($child));
+
+ $this->form->add('foo', 'text', array('bar' => 'baz'));
+
+ $this->assertTrue($this->form->has('foo'));
+ $this->assertSame($this->form, $child->getParent());
+ $this->assertSame(array('foo' => $child), $this->form->all());
+ }
+
+ public function testAddUsingNameButNoType()
+ {
+ $this->form = $this->getBuilder('name', null, '\stdClass')
+ ->setCompound(true)
+ ->setDataMapper($this->getDataMapper())
+ ->getForm();
+
+ $child = $this->getBuilder('foo')->getForm();
+
+ $this->factory->expects($this->once())
+ ->method('createForProperty')
+ ->with('\stdClass', 'foo')
+ ->will($this->returnValue($child));
+
+ $this->form->add('foo');
+
+ $this->assertTrue($this->form->has('foo'));
+ $this->assertSame($this->form, $child->getParent());
+ $this->assertSame(array('foo' => $child), $this->form->all());
+ }
+
+ public function testAddUsingNameButNoTypeAndOptions()
+ {
+ $this->form = $this->getBuilder('name', null, '\stdClass')
+ ->setCompound(true)
+ ->setDataMapper($this->getDataMapper())
+ ->getForm();
+
+ $child = $this->getBuilder('foo')->getForm();
+
+ $this->factory->expects($this->once())
+ ->method('createForProperty')
+ ->with('\stdClass', 'foo', null, array('bar' => 'baz'))
+ ->will($this->returnValue($child));
+
+ $this->form->add('foo', null, array('bar' => 'baz'));
+
+ $this->assertTrue($this->form->has('foo'));
$this->assertSame($this->form, $child->getParent());
$this->assertSame(array('foo' => $child), $this->form->all());
}
/**
- * @expectedException Symfony\Component\Form\Exception\AlreadyBoundException
+ * @expectedException \Symfony\Component\Form\Exception\AlreadyBoundException
*/
public function testAddThrowsExceptionIfAlreadyBound()
{
@@ -161,7 +220,7 @@ public function testRemove()
}
/**
- * @expectedException Symfony\Component\Form\Exception\AlreadyBoundException
+ * @expectedException \Symfony\Component\Form\Exception\AlreadyBoundException
*/
public function testRemoveThrowsExceptionIfAlreadyBound()
{
View
34 src/Symfony/Component/Form/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php
@@ -81,7 +81,7 @@ public function testPreSetDataResizesForm()
$data = array(1 => 'string', 2 => 'string');
$event = DeprecationErrorHandler::getFormEvent($this->form, $data);
- $listener = new ResizeFormListener($this->factory, 'text', array('max_length' => '10'), false, false);
+ $listener = new ResizeFormListener('text', array('max_length' => '10'), false, false);
$listener->preSetData($event);
$this->assertFalse($this->form->has('0'));
@@ -90,13 +90,13 @@ public function testPreSetDataResizesForm()
}
/**
- * @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException
+ * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException
*/
public function testPreSetDataRequiresArrayOrTraversable()
{
$data = 'no array or traversable';
$event = DeprecationErrorHandler::getFormEvent($this->form, $data);
- $listener = new ResizeFormListener($this->factory, 'text', array(), false, false);
+ $listener = new ResizeFormListener('text', array(), false, false);
$listener->preSetData($event);
}
@@ -106,7 +106,7 @@ public function testPreSetDataDealsWithNullData()
$data = null;
$event = DeprecationErrorHandler::getFormEvent($this->form, $data);
- $listener = new ResizeFormListener($this->factory, 'text', array(), false, false);
+ $listener = new ResizeFormListener('text', array(), false, false);
$listener->preSetData($event);
}
@@ -121,7 +121,7 @@ public function testPreBindResizesUpIfAllowAdd()
$data = array(0 => 'string', 1 => 'string');
$event = DeprecationErrorHandler::getFormEvent($this->form, $data);
- $listener = new ResizeFormListener($this->factory, 'text', array('max_length' => 10), true, false);
+ $listener = new ResizeFormListener('text', array('max_length' => 10), true, false);
$listener->preBind($event);
$this->assertTrue($this->form->has('0'));
@@ -135,7 +135,7 @@ public function testPreBindResizesDownIfAllowDelete()
$data = array(0 => 'string');
$event = DeprecationErrorHandler::getFormEvent($this->form, $data);
- $listener = new ResizeFormListener($this->factory, 'text', array(), false, true);
+ $listener = new ResizeFormListener('text', array(), false, true);
$listener->preBind($event);
$this->assertTrue($this->form->has('0'));
@@ -149,7 +149,7 @@ public function testPreBindRemovesZeroKeys()
$data = array();
$event = DeprecationErrorHandler::getFormEvent($this->form, $data);
- $listener = new ResizeFormListener($this->factory, 'text', array(), false, true);
+ $listener = new ResizeFormListener('text', array(), false, true);
$listener->preBind($event);
$this->assertFalse($this->form->has('0'));
@@ -162,7 +162,7 @@ public function testPreBindDoesNothingIfNotAllowAddNorAllowDelete()
$data = array(0 => 'string', 2 => 'string');
$event = DeprecationErrorHandler::getFormEvent($this->form, $data);
- $listener = new ResizeFormListener($this->factory, 'text', array(), false, false);
+ $listener = new ResizeFormListener('text', array(), false, false);
$listener->preBind($event);
$this->assertTrue($this->form->has('0'));
@@ -171,13 +171,13 @@ public function testPreBindDoesNothingIfNotAllowAddNorAllowDelete()
}
/**
- * @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException
+ * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException
*/
public function testPreBindRequiresArrayOrTraversable()
{
$data = 'no array or traversable';
$event = DeprecationErrorHandler::getFormEvent($this->form, $data);
- $listener = new ResizeFormListener($this->factory, 'text', array(), false, false);
+ $listener = new ResizeFormListener('text', array(), false, false);
$listener->preBind($event);
}
@@ -187,7 +187,7 @@ public function testPreBindDealsWithNullData()
$data = null;
$event = DeprecationErrorHandler::getFormEvent($this->form, $data);
- $listener = new ResizeFormListener($this->factory, 'text', array(), false, true);
+ $listener = new ResizeFormListener('text', array(), false, true);
$listener->preBind($event);
$this->assertFalse($this->form->has('1'));
@@ -200,7 +200,7 @@ public function testPreBindDealsWithEmptyData()
$data = '';
$event = DeprecationErrorHandler::getFormEvent($this->form, $data);
- $listener = new ResizeFormListener($this->factory, 'text', array(), false, true);
+ $listener = new ResizeFormListener('text', array(), false, true);
$listener->preBind($event);
$this->assertFalse($this->form->has('1'));
@@ -212,7 +212,7 @@ public function testOnBindNormDataRemovesEntriesMissingInTheFormIfAllowDelete()
$data = array(0 => 'first', 1 => 'second', 2 => 'third');
$event = DeprecationErrorHandler::getFormEvent($this->form, $data);
- $listener = new ResizeFormListener($this->factory, 'text', array(), false, true);
+ $listener = new ResizeFormListener('text', array(), false, true);
$listener->onBind($event);
$this->assertEquals(array(1 => 'second'), $event->getData());
@@ -224,20 +224,20 @@ public function testOnBindNormDataDoesNothingIfNotAllowDelete()
$data = array(0 => 'first', 1 => 'second', 2 => 'third');
$event = DeprecationErrorHandler::getFormEvent($this->form, $data);
- $listener = new ResizeFormListener($this->factory, 'text', array(), false, false);
+ $listener = new ResizeFormListener('text', array(), false, false);
$listener->onBind($event);
$this->assertEquals($data, $event->getData());
}
/**
- * @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException
+ * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException
*/
public function testOnBindNormDataRequiresArrayOrTraversable()
{
$data = 'no array or traversable';
$event = DeprecationErrorHandler::getFormEvent($this->form, $data);
- $listener = new ResizeFormListener($this->factory, 'text', array(), false, false);
+ $listener = new ResizeFormListener('text', array(), false, false);
$listener->onBind($event);
}
@@ -247,7 +247,7 @@ public function testOnBindNormDataDealsWithNullData()
$data = null;
$event = DeprecationErrorHandler::getFormEvent($this->form, $data);
- $listener = new ResizeFormListener($this->factory, 'text', array(), false, true);
+ $listener = new ResizeFormListener('text', array(), false, true);
$listener->onBind($event);
$this->assertEquals(array(), $event->getData());
Please sign in to comment.
Something went wrong with that request. Please try again.