[Form] Adapted Form to create a deterministic property path by default
This commit is contained in:
parent
03f50588c2
commit
860dd1f7d8
@ -18,18 +18,6 @@ use Symfony\Component\Form\Exception\UnexpectedTypeException;
|
||||
|
||||
class PropertyPathMapper implements DataMapperInterface
|
||||
{
|
||||
/**
|
||||
* Stores the class that the data of this form must be instances of.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $dataClass;
|
||||
|
||||
public function __construct($dataClass = null)
|
||||
{
|
||||
$this->dataClass = $dataClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@ -40,10 +28,6 @@ class PropertyPathMapper implements DataMapperInterface
|
||||
}
|
||||
|
||||
if (!empty($data)) {
|
||||
if (null !== $this->dataClass && !$data instanceof $this->dataClass) {
|
||||
throw new UnexpectedTypeException($data, $this->dataClass);
|
||||
}
|
||||
|
||||
$iterator = new VirtualFormAwareIterator($forms);
|
||||
$iterator = new \RecursiveIteratorIterator($iterator);
|
||||
|
||||
@ -59,7 +43,7 @@ class PropertyPathMapper implements DataMapperInterface
|
||||
public function mapDataToForm($data, FormInterface $form)
|
||||
{
|
||||
if (!empty($data)) {
|
||||
$propertyPath = $form->getAttribute('property_path');
|
||||
$propertyPath = $form->getPropertyPath();
|
||||
|
||||
if (null !== $propertyPath) {
|
||||
$propertyData = $propertyPath->getValue($data);
|
||||
@ -91,7 +75,7 @@ class PropertyPathMapper implements DataMapperInterface
|
||||
*/
|
||||
public function mapFormToData(FormInterface $form, &$data)
|
||||
{
|
||||
$propertyPath = $form->getAttribute('property_path');
|
||||
$propertyPath = $form->getPropertyPath();
|
||||
|
||||
if (null !== $propertyPath && $form->isSynchronized() && !$form->isDisabled()) {
|
||||
// If the data is identical to the value in $data, we are
|
||||
|
@ -31,16 +31,6 @@ class FormType extends AbstractType
|
||||
*/
|
||||
public function buildForm(FormBuilder $builder, array $options)
|
||||
{
|
||||
if (null === $options['property_path']) {
|
||||
$options['property_path'] = $builder->getName();
|
||||
}
|
||||
|
||||
if (false === $options['property_path'] || '' === $options['property_path']) {
|
||||
$options['property_path'] = null;
|
||||
} else {
|
||||
$options['property_path'] = new PropertyPath($options['property_path']);
|
||||
}
|
||||
|
||||
if (!is_array($options['attr'])) {
|
||||
throw new FormException('The "attr" option must be an "array".');
|
||||
}
|
||||
@ -54,9 +44,9 @@ class FormType extends AbstractType
|
||||
->setDisabled($options['disabled'])
|
||||
->setErrorBubbling($options['error_bubbling'])
|
||||
->setEmptyData($options['empty_data'])
|
||||
->setPropertyPath($options['property_path'])
|
||||
->setAttribute('read_only', $options['read_only'])
|
||||
->setAttribute('by_reference', $options['by_reference'])
|
||||
->setAttribute('property_path', $options['property_path'])
|
||||
->setAttribute('error_mapping', $options['error_mapping'])
|
||||
->setAttribute('max_length', $options['max_length'])
|
||||
->setAttribute('pattern', $options['pattern'])
|
||||
@ -69,7 +59,7 @@ class FormType extends AbstractType
|
||||
->setAttribute('virtual', $options['virtual'])
|
||||
->setAttribute('single_control', $options['single_control'])
|
||||
->setData($options['data'])
|
||||
->setDataMapper(new PropertyPathMapper($options['data_class']))
|
||||
->setDataMapper(new PropertyPathMapper())
|
||||
->addEventSubscriber(new ValidationListener())
|
||||
;
|
||||
|
||||
@ -112,7 +102,7 @@ class FormType extends AbstractType
|
||||
}
|
||||
|
||||
$types = array();
|
||||
foreach ($form->getTypes() as $type) {
|
||||
foreach ($form->getConfig()->getTypes() as $type) {
|
||||
$types[] = $type->getName();
|
||||
}
|
||||
|
||||
@ -229,7 +219,7 @@ class FormType extends AbstractType
|
||||
*/
|
||||
public function createBuilder($name, FormFactoryInterface $factory, array $options)
|
||||
{
|
||||
return new FormBuilder($name, $factory, new EventDispatcher(), $options['data_class']);
|
||||
return new FormBuilder($name, $options['data_class'], new EventDispatcher(), $factory);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -17,6 +17,7 @@ use Symfony\Component\Form\Exception\FormException;
|
||||
use Symfony\Component\Form\Exception\AlreadyBoundException;
|
||||
use Symfony\Component\Form\Exception\UnexpectedTypeException;
|
||||
use Symfony\Component\Form\Exception\TransformationFailedException;
|
||||
use Symfony\Component\Form\Util\PropertyPath;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
@ -162,10 +163,33 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
return $this->config->getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getPropertyPath()
|
||||
{
|
||||
if (!$this->hasParent() || null !== $this->config->getPropertyPath()) {
|
||||
return $this->config->getPropertyPath();
|
||||
}
|
||||
|
||||
if (null === $this->getName() || '' === $this->getName()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (null === $this->getParent()->getConfig()->getDataClass()) {
|
||||
return new PropertyPath('[' . $this->getName() . ']');
|
||||
}
|
||||
|
||||
return new PropertyPath($this->getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the types used by this form.
|
||||
*
|
||||
* @return array An array of FormTypeInterface
|
||||
*
|
||||
* @deprecated Deprecated since version 2.1, to be removed in 2.3. Use
|
||||
* {@link getConfig()} and {@link FormConfigInterface::getTypes()} instead.
|
||||
*/
|
||||
public function getTypes()
|
||||
{
|
||||
@ -261,9 +285,9 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
/**
|
||||
* Returns whether the form has an attribute with the given name.
|
||||
*
|
||||
* @param string $name The name of the attribute
|
||||
* @param string $name The name of the attribute.
|
||||
*
|
||||
* @return Boolean
|
||||
* @return Boolean Whether the attribute exists.
|
||||
*/
|
||||
public function hasAttribute($name)
|
||||
{
|
||||
@ -273,7 +297,9 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
/**
|
||||
* Returns the value of the attributes with the given name.
|
||||
*
|
||||
* @param string $name The name of the attribute
|
||||
* @param string $name The name of the attribute
|
||||
*
|
||||
* @return mixed The attribute value.
|
||||
*/
|
||||
public function getAttribute($name)
|
||||
{
|
||||
@ -310,6 +336,25 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
$normData = $this->appToNorm($appData);
|
||||
$clientData = $this->normToClient($normData);
|
||||
|
||||
// Validate if client data matches data class (unless empty)
|
||||
if (!empty($clientData)) {
|
||||
// TESTME
|
||||
$dataClass = $this->config->getDataClass();
|
||||
|
||||
if (null === $dataClass && is_object($clientData)) {
|
||||
// TODO clarify error message: should not be transformed to object if data class is null
|
||||
// possible solutions: set data class or change client transformers
|
||||
throw new UnexpectedTypeException($clientData, 'scalar or array');
|
||||
}
|
||||
|
||||
// TESTME
|
||||
if (null !== $dataClass && !$clientData instanceof $dataClass) {
|
||||
// TODO clarify error message: should be transformed to object if data class is set
|
||||
// possible solutions: change data class or client transformers
|
||||
throw new UnexpectedTypeException($clientData, $dataClass);
|
||||
}
|
||||
}
|
||||
|
||||
$this->appData = $appData;
|
||||
$this->normData = $normData;
|
||||
$this->clientData = $clientData;
|
||||
@ -568,6 +613,9 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
* Returns whether errors bubble up to the parent.
|
||||
*
|
||||
* @return Boolean
|
||||
*
|
||||
* @deprecated Deprecated since version 2.1, to be removed in 2.3. Use
|
||||
* {@link getConfig()} and {@link FormConfigInterface::getErrorBubbling()} instead.
|
||||
*/
|
||||
public function getErrorBubbling()
|
||||
{
|
||||
@ -693,6 +741,9 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
* Returns the DataTransformers.
|
||||
*
|
||||
* @return array An array of DataTransformerInterface
|
||||
*
|
||||
* @deprecated Deprecated since version 2.1, to be removed in 2.3. Use
|
||||
* {@link getConfig()} and {@link FormConfigInterface::getNormTransformers()} instead.
|
||||
*/
|
||||
public function getNormTransformers()
|
||||
{
|
||||
@ -703,6 +754,9 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
* Returns the DataTransformers.
|
||||
*
|
||||
* @return array An array of DataTransformerInterface
|
||||
*
|
||||
* @deprecated Deprecated since version 2.1, to be removed in 2.3. Use
|
||||
* {@link getConfig()} and {@link FormConfigInterface::getClientTransformers()} instead.
|
||||
*/
|
||||
public function getClientTransformers()
|
||||
{
|
||||
|
@ -31,11 +31,6 @@ class FormBuilder extends FormConfig
|
||||
*/
|
||||
private $factory;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $dataClass;
|
||||
|
||||
/**
|
||||
* The children of the form builder.
|
||||
*
|
||||
@ -59,19 +54,18 @@ class FormBuilder extends FormConfig
|
||||
private $parent;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* Creates a new form builder.
|
||||
*
|
||||
* @param string $name
|
||||
* @param FormFactoryInterface $factory
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
* @param string $dataClass
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
* @param FormFactoryInterface $factory
|
||||
*/
|
||||
public function __construct($name, FormFactoryInterface $factory, EventDispatcherInterface $dispatcher, $dataClass = null)
|
||||
public function __construct($name, $dataClass, EventDispatcherInterface $dispatcher, FormFactoryInterface $factory)
|
||||
{
|
||||
parent::__construct($name, $dispatcher);
|
||||
parent::__construct($name, $dataClass, $dispatcher);
|
||||
|
||||
$this->factory = $factory;
|
||||
$this->dataClass = $dataClass;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -140,7 +134,7 @@ class FormBuilder extends FormConfig
|
||||
*/
|
||||
public function create($name, $type = null, array $options = array())
|
||||
{
|
||||
if (null === $type && !$this->dataClass) {
|
||||
if (null === $type && null === $this->getDataClass()) {
|
||||
$type = 'text';
|
||||
}
|
||||
|
||||
@ -148,7 +142,7 @@ class FormBuilder extends FormConfig
|
||||
return $this->getFormFactory()->createNamedBuilder($type, $name, null, $options, $this);
|
||||
}
|
||||
|
||||
return $this->getFormFactory()->createBuilderForProperty($this->dataClass, $name, null, $options, $this);
|
||||
return $this->getFormFactory()->createBuilderForProperty($this->getDataClass(), $name, null, $options, $this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -33,6 +33,16 @@ class FormConfig implements FormConfigInterface
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* @var PropertyPath
|
||||
*/
|
||||
private $propertyPath;
|
||||
|
||||
/**
|
||||
* @var Boolean
|
||||
*/
|
||||
private $mapped;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
@ -88,19 +98,34 @@ class FormConfig implements FormConfigInterface
|
||||
*/
|
||||
private $data;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $dataClass;
|
||||
|
||||
/**
|
||||
* Creates an empty form configuration.
|
||||
*
|
||||
* @param string $name The form name.
|
||||
* @param EventDispatcherInterface $dispatcher The event dispatcher.
|
||||
* @param string $name The form name.
|
||||
* @param string $dataClass The class of the form's data.
|
||||
* @param EventDispatcherInterface $dispatcher The event dispatcher.
|
||||
*
|
||||
* @throws UnexpectedTypeException If the name is not a string.
|
||||
* @throws \InvalidArgumentException If the data class is not a valid class or if
|
||||
* the name contains invalid characters.
|
||||
*/
|
||||
public function __construct($name, EventDispatcherInterface $dispatcher)
|
||||
public function __construct($name, $dataClass, EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$name = (string) $name;
|
||||
|
||||
self::validateName($name);
|
||||
|
||||
if (null !== $dataClass && !class_exists($dataClass)) {
|
||||
throw new \InvalidArgumentException(sprintf('The data class "%s" is not a valid class.', $dataClass));
|
||||
}
|
||||
|
||||
$this->name = $name;
|
||||
$this->dataClass = $dataClass;
|
||||
$this->dispatcher = $dispatcher;
|
||||
}
|
||||
|
||||
@ -248,6 +273,22 @@ class FormConfig implements FormConfigInterface
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getPropertyPath()
|
||||
{
|
||||
return $this->propertyPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getMapped()
|
||||
{
|
||||
return $this->mapped;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@ -354,6 +395,14 @@ class FormConfig implements FormConfigInterface
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDataClass()
|
||||
{
|
||||
return $this->dataClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value for an attribute.
|
||||
*
|
||||
@ -453,6 +502,41 @@ class FormConfig implements FormConfigInterface
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the property path that the form should be mapped to.
|
||||
*
|
||||
* @param string|PropertyPath $propertyPath The property path or null if the path
|
||||
* should be set automatically based on
|
||||
* the form's name.
|
||||
*
|
||||
* @return self The configuration object.
|
||||
*/
|
||||
public function setPropertyPath($propertyPath)
|
||||
{
|
||||
if (null !== $propertyPath && !$propertyPath instanceof PropertyPath) {
|
||||
$propertyPath = new PropertyPath($propertyPath);
|
||||
}
|
||||
|
||||
$this->propertyPath = $propertyPath;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the form should be mapped to an element of its
|
||||
* parent's data.
|
||||
*
|
||||
* @param Boolean $mapped Whether the form should be mapped.
|
||||
*
|
||||
* @return self The configuration object.
|
||||
*/
|
||||
public function setMapped($mapped)
|
||||
{
|
||||
$this->mapped = $mapped;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the types.
|
||||
*
|
||||
@ -486,7 +570,7 @@ class FormConfig implements FormConfigInterface
|
||||
*
|
||||
* @param string $name The tested form name.
|
||||
*
|
||||
* @throws UnexpectedTypeException If the name is not a string.
|
||||
* @throws UnexpectedTypeException If the name is not a string.
|
||||
* @throws \InvalidArgumentException If the name contains invalid characters.
|
||||
*/
|
||||
static public function validateName($name)
|
||||
|
@ -32,6 +32,21 @@ interface FormConfigInterface
|
||||
*/
|
||||
function getName();
|
||||
|
||||
/**
|
||||
* Returns the property path that the form should be mapped to.
|
||||
*
|
||||
* @return Util\PropertyPath The property path.
|
||||
*/
|
||||
function getPropertyPath();
|
||||
|
||||
/**
|
||||
* Returns whether the form should be mapped to an element of its
|
||||
* parent's data.
|
||||
*
|
||||
* @return Boolean Whether the form is mapped.
|
||||
*/
|
||||
function getMapped();
|
||||
|
||||
/**
|
||||
* Returns the form types used to construct the form.
|
||||
*
|
||||
@ -128,4 +143,11 @@ interface FormConfigInterface
|
||||
* @return mixed The initial form data.
|
||||
*/
|
||||
function getData();
|
||||
|
||||
/**
|
||||
* Returns the class of the form data or null if the data is scalar or an array.
|
||||
*
|
||||
* @return string The data class or null.
|
||||
*/
|
||||
function getDataClass();
|
||||
}
|
||||
|
@ -151,7 +151,6 @@ class FormFactory implements FormFactoryInterface
|
||||
|
||||
$builder = null;
|
||||
$types = array();
|
||||
$optionValues = array();
|
||||
$knownOptions = array();
|
||||
$optionsResolver = new OptionsResolver();
|
||||
|
||||
|
@ -131,6 +131,13 @@ interface FormInterface extends \ArrayAccess, \Traversable, \Countable
|
||||
*/
|
||||
function getExtraData();
|
||||
|
||||
/**
|
||||
* Returns the form's configuration.
|
||||
*
|
||||
* @return FormConfigInterface The configuration.
|
||||
*/
|
||||
function getConfig();
|
||||
|
||||
/**
|
||||
* Returns whether the field is bound.
|
||||
*
|
||||
@ -138,13 +145,6 @@ interface FormInterface extends \ArrayAccess, \Traversable, \Countable
|
||||
*/
|
||||
function isBound();
|
||||
|
||||
/**
|
||||
* Returns the supported types.
|
||||
*
|
||||
* @return array An array of FormTypeInterface
|
||||
*/
|
||||
function getTypes();
|
||||
|
||||
/**
|
||||
* Returns the name by which the form is identified in forms.
|
||||
*
|
||||
@ -152,6 +152,13 @@ interface FormInterface extends \ArrayAccess, \Traversable, \Countable
|
||||
*/
|
||||
function getName();
|
||||
|
||||
/**
|
||||
* Returns the property path that the form is mapped to.
|
||||
*
|
||||
* @return Util\PropertyPath The property path.
|
||||
*/
|
||||
function getPropertyPath();
|
||||
|
||||
/**
|
||||
* Adds an error to this form.
|
||||
*
|
||||
|
@ -31,6 +31,16 @@ class ImmutableFormConfig implements FormConfigInterface
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* @var PropertyPath
|
||||
*/
|
||||
private $propertyPath;
|
||||
|
||||
/**
|
||||
* @var Boolean
|
||||
*/
|
||||
private $mapped;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
@ -86,6 +96,11 @@ class ImmutableFormConfig implements FormConfigInterface
|
||||
*/
|
||||
private $data;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $dataClass;
|
||||
|
||||
/**
|
||||
* Creates an immutable copy of a given configuration.
|
||||
*
|
||||
@ -95,6 +110,8 @@ class ImmutableFormConfig implements FormConfigInterface
|
||||
{
|
||||
$this->dispatcher = $config->getEventDispatcher();
|
||||
$this->name = $config->getName();
|
||||
$this->propertyPath = $config->getPropertyPath();
|
||||
$this->mapped = $config->getMapped();
|
||||
$this->types = $config->getTypes();
|
||||
$this->clientTransformers = $config->getClientTransformers();
|
||||
$this->normTransformers = $config->getNormTransformers();
|
||||
@ -104,8 +121,9 @@ class ImmutableFormConfig implements FormConfigInterface
|
||||
$this->disabled = $config->getDisabled();
|
||||
$this->errorBubbling = $config->getErrorBubbling();
|
||||
$this->emptyData = $config->getEmptyData();
|
||||
$this->data = $config->getData();
|
||||
$this->attributes = $config->getAttributes();
|
||||
$this->data = $config->getData();
|
||||
$this->dataClass = $config->getDataClass();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -124,6 +142,22 @@ class ImmutableFormConfig implements FormConfigInterface
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getPropertyPath()
|
||||
{
|
||||
return $this->propertyPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getMapped()
|
||||
{
|
||||
return $this->mapped;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@ -229,4 +263,12 @@ class ImmutableFormConfig implements FormConfigInterface
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDataClass()
|
||||
{
|
||||
return $this->dataClass;
|
||||
}
|
||||
}
|
||||
|
@ -74,9 +74,12 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase
|
||||
->setMethods(array('foo'))
|
||||
->getMockForAbstractClass();
|
||||
|
||||
$form->setAttribute('property_path', $propertyPath);
|
||||
$form->setAttribute('by_reference', $byReference);
|
||||
|
||||
$form->expects($this->any())
|
||||
->method('getPropertyPath')
|
||||
->will($this->returnValue($propertyPath));
|
||||
|
||||
$form->expects($this->any())
|
||||
->method('isSynchronized')
|
||||
->will($this->returnValue($synchronized));
|
||||
|
@ -11,10 +11,17 @@
|
||||
|
||||
namespace Symfony\Component\Form\Tests\Extension\Core\EventListener;
|
||||
|
||||
use Symfony\Component\Form\FormBuilder;
|
||||
|
||||
class MergeCollectionListenerArrayObjectTest extends MergeCollectionListenerTest
|
||||
{
|
||||
protected function getData(array $data)
|
||||
{
|
||||
return new \ArrayObject($data);
|
||||
}
|
||||
|
||||
protected function getBuilder($name = 'name')
|
||||
{
|
||||
return new FormBuilder($name, '\ArrayObject', $this->dispatcher, $this->factory);
|
||||
}
|
||||
}
|
||||
|
@ -11,10 +11,17 @@
|
||||
|
||||
namespace Symfony\Component\Form\Tests\Extension\Core\EventListener;
|
||||
|
||||
use Symfony\Component\Form\FormBuilder;
|
||||
|
||||
class MergeCollectionListenerArrayTest extends MergeCollectionListenerTest
|
||||
{
|
||||
protected function getData(array $data)
|
||||
{
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected function getBuilder($name = 'name')
|
||||
{
|
||||
return new FormBuilder($name, null, $this->dispatcher, $this->factory);
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
namespace Symfony\Component\Form\Tests\Extension\Core\EventListener;
|
||||
|
||||
use Symfony\Component\Form\Tests\Fixtures\CustomArrayObject;
|
||||
use Symfony\Component\Form\FormBuilder;
|
||||
|
||||
class MergeCollectionListenerCustomArrayObjectTest extends MergeCollectionListenerTest
|
||||
{
|
||||
@ -19,4 +20,9 @@ class MergeCollectionListenerCustomArrayObjectTest extends MergeCollectionListen
|
||||
{
|
||||
return new CustomArrayObject($data);
|
||||
}
|
||||
|
||||
protected function getBuilder($name = 'name')
|
||||
{
|
||||
return new FormBuilder($name, 'Symfony\Component\Form\Tests\Fixtures\CustomArrayObject', $this->dispatcher, $this->factory);
|
||||
}
|
||||
}
|
||||
|
@ -17,9 +17,9 @@ use Symfony\Component\Form\FormBuilder;
|
||||
|
||||
abstract class MergeCollectionListenerTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
private $dispatcher;
|
||||
private $factory;
|
||||
private $form;
|
||||
protected $dispatcher;
|
||||
protected $factory;
|
||||
protected $form;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
@ -39,10 +39,7 @@ abstract class MergeCollectionListenerTest extends \PHPUnit_Framework_TestCase
|
||||
$this->form = null;
|
||||
}
|
||||
|
||||
protected function getBuilder($name = 'name')
|
||||
{
|
||||
return new FormBuilder($name, $this->factory, $this->dispatcher);
|
||||
}
|
||||
abstract protected function getBuilder($name = 'name');
|
||||
|
||||
protected function getForm($name = 'name', $propertyPath = null)
|
||||
{
|
||||
|
@ -42,7 +42,7 @@ class ResizeFormListenerTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
protected function getBuilder($name = 'name')
|
||||
{
|
||||
return new FormBuilder($name, $this->factory, $this->dispatcher);
|
||||
return new FormBuilder($name, null, $this->dispatcher, $this->factory);
|
||||
}
|
||||
|
||||
protected function getForm($name = 'name')
|
||||
|
@ -51,41 +51,6 @@ class FormTest_AuthorWithoutRefSetter
|
||||
|
||||
class FormTypeTest extends TypeTestCase
|
||||
{
|
||||
public function testGetPropertyPathDefaultPath()
|
||||
{
|
||||
$form = $this->factory->createNamed('form', 'title');
|
||||
|
||||
$this->assertEquals(new PropertyPath('title'), $form->getAttribute('property_path'));
|
||||
}
|
||||
|
||||
public function testGetPropertyPathPathIsZero()
|
||||
{
|
||||
$form = $this->factory->create('form', null, array('property_path' => '0'));
|
||||
|
||||
$this->assertEquals(new PropertyPath('0'), $form->getAttribute('property_path'));
|
||||
}
|
||||
|
||||
public function testGetPropertyPathPathIsEmpty()
|
||||
{
|
||||
$form = $this->factory->create('form', null, array('property_path' => ''));
|
||||
|
||||
$this->assertNull($form->getAttribute('property_path'));
|
||||
}
|
||||
|
||||
public function testGetPropertyPathPathIsFalse()
|
||||
{
|
||||
$form = $this->factory->create('form', null, array('property_path' => false));
|
||||
|
||||
$this->assertNull($form->getAttribute('property_path'));
|
||||
}
|
||||
|
||||
public function testGetPropertyPathPathIsNull()
|
||||
{
|
||||
$form = $this->factory->createNamed('form', 'title', null, array('property_path' => null));
|
||||
|
||||
$this->assertEquals(new PropertyPath('title'), $form->getAttribute('property_path'));
|
||||
}
|
||||
|
||||
public function testPassRequiredAsOption()
|
||||
{
|
||||
$form = $this->factory->create('form', null, array('required' => false));
|
||||
@ -285,10 +250,9 @@ class FormTypeTest extends TypeTestCase
|
||||
$this->assertEquals($author, $form->getData());
|
||||
}
|
||||
|
||||
public function testBindWithEmptyDataDoesNotCreateObjectIfDataClassIsNull()
|
||||
public function testBindWithEmptyDataCreatesArrayIfDataClassIsNull()
|
||||
{
|
||||
$form = $this->factory->create('form', null, array(
|
||||
'data' => new Author(),
|
||||
'data_class' => null,
|
||||
'required' => false,
|
||||
));
|
||||
@ -365,6 +329,7 @@ class FormTypeTest extends TypeTestCase
|
||||
$author = new Author();
|
||||
|
||||
$form = $this->factory->create('form', null, array(
|
||||
'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author',
|
||||
'empty_data' => $author,
|
||||
));
|
||||
$form->add($this->factory->createNamed('form', 'firstName'));
|
||||
@ -430,10 +395,11 @@ class FormTypeTest extends TypeTestCase
|
||||
{
|
||||
$author = new FormTest_AuthorWithoutRefSetter(new Author());
|
||||
|
||||
$builder = $this->factory->createBuilder('form');
|
||||
$builder->add('reference', 'form');
|
||||
$builder = $this->factory->createBuilder('form', $author);
|
||||
$builder->add('reference', 'form', array(
|
||||
'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author',
|
||||
));
|
||||
$builder->get('reference')->add('firstName', 'form');
|
||||
$builder->setData($author);
|
||||
$form = $builder->getForm();
|
||||
|
||||
$form->bind(array(
|
||||
@ -452,10 +418,11 @@ class FormTypeTest extends TypeTestCase
|
||||
$author = new FormTest_AuthorWithoutRefSetter(null);
|
||||
$newReference = new Author();
|
||||
|
||||
$builder = $this->factory->createBuilder('form');
|
||||
$builder->add('referenceCopy', 'form');
|
||||
$builder = $this->factory->createBuilder('form', $author);
|
||||
$builder->add('referenceCopy', 'form', array(
|
||||
'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author',
|
||||
));
|
||||
$builder->get('referenceCopy')->add('firstName', 'form');
|
||||
$builder->setData($author);
|
||||
$form = $builder->getForm();
|
||||
|
||||
$form['referenceCopy']->setData($newReference); // new author object
|
||||
@ -474,17 +441,19 @@ class FormTypeTest extends TypeTestCase
|
||||
{
|
||||
$author = new FormTest_AuthorWithoutRefSetter(new Author());
|
||||
|
||||
$builder = $this->factory->createBuilder('form');
|
||||
$builder->add('referenceCopy', 'form', array('by_reference' => false));
|
||||
$builder = $this->factory->createBuilder('form', $author);
|
||||
$builder->add('referenceCopy', 'form', array(
|
||||
'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author',
|
||||
'by_reference' => false
|
||||
));
|
||||
$builder->get('referenceCopy')->add('firstName', 'form');
|
||||
$builder->setData($author);
|
||||
$form = $builder->getForm();
|
||||
|
||||
$form->bind(array(
|
||||
// referenceCopy has a getter that returns a copy
|
||||
// referenceCopy has a getter that returns a copy
|
||||
'referenceCopy' => array(
|
||||
'firstName' => 'Foo',
|
||||
)
|
||||
)
|
||||
));
|
||||
|
||||
// firstName can only be updated if setReferenceCopy() was called
|
||||
@ -495,16 +464,14 @@ class FormTypeTest extends TypeTestCase
|
||||
{
|
||||
$author = new FormTest_AuthorWithoutRefSetter('scalar');
|
||||
|
||||
$builder = $this->factory->createBuilder('form');
|
||||
$builder = $this->factory->createBuilder('form', $author);
|
||||
$builder->add('referenceCopy', 'form');
|
||||
$builder->get('referenceCopy')->appendClientTransformer(new CallbackTransformer(
|
||||
function () {},
|
||||
function ($value) { // reverseTransform
|
||||
|
||||
return 'foobar';
|
||||
}
|
||||
function () {},
|
||||
function ($value) { // reverseTransform
|
||||
return 'foobar';
|
||||
}
|
||||
));
|
||||
$builder->setData($author);
|
||||
$form = $builder->getForm();
|
||||
|
||||
$form->bind(array(
|
||||
@ -525,11 +492,10 @@ class FormTypeTest extends TypeTestCase
|
||||
$builder->setData($author);
|
||||
$builder->add('referenceCopy', 'form');
|
||||
$builder->get('referenceCopy')->appendClientTransformer(new CallbackTransformer(
|
||||
function () {},
|
||||
function ($value) use ($ref2) { // reverseTransform
|
||||
|
||||
return $ref2;
|
||||
}
|
||||
function () {},
|
||||
function ($value) use ($ref2) { // reverseTransform
|
||||
return $ref2;
|
||||
}
|
||||
));
|
||||
$form = $builder->getForm();
|
||||
|
||||
|
@ -18,10 +18,19 @@ use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||
|
||||
abstract class TypeTestCase extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @var FormFactory
|
||||
*/
|
||||
protected $factory;
|
||||
|
||||
/**
|
||||
* @var FormBuilder
|
||||
*/
|
||||
protected $builder;
|
||||
|
||||
/**
|
||||
* @var EventDispatcher
|
||||
*/
|
||||
protected $dispatcher;
|
||||
|
||||
protected function setUp()
|
||||
@ -32,7 +41,7 @@ abstract class TypeTestCase extends \PHPUnit_Framework_TestCase
|
||||
|
||||
$this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
|
||||
$this->factory = new FormFactory($this->getExtensions());
|
||||
$this->builder = new FormBuilder(null, $this->factory, $this->dispatcher);
|
||||
$this->builder = new FormBuilder(null, null, $this->dispatcher, $this->factory);
|
||||
}
|
||||
|
||||
protected function tearDown()
|
||||
|
@ -88,9 +88,9 @@ class DelegatingValidationListenerTest extends \PHPUnit_Framework_TestCase
|
||||
return new FormError($this->message, $this->params);
|
||||
}
|
||||
|
||||
protected function getBuilder($name = 'name', $propertyPath = null)
|
||||
protected function getBuilder($name = 'name', $propertyPath = null, $dataClass = null)
|
||||
{
|
||||
$builder = new FormBuilder($name, $this->factory, $this->dispatcher);
|
||||
$builder = new FormBuilder($name, $dataClass, $this->dispatcher, $this->factory);
|
||||
$builder->setAttribute('property_path', new PropertyPath($propertyPath ?: $name));
|
||||
$builder->setAttribute('error_mapping', array());
|
||||
$builder->setErrorBubbling(false);
|
||||
@ -98,9 +98,9 @@ class DelegatingValidationListenerTest extends \PHPUnit_Framework_TestCase
|
||||
return $builder;
|
||||
}
|
||||
|
||||
protected function getForm($name = 'name', $propertyPath = null)
|
||||
protected function getForm($name = 'name', $propertyPath = null, $dataClass = null)
|
||||
{
|
||||
return $this->getBuilder($name, $propertyPath)->getForm();
|
||||
return $this->getBuilder($name, $propertyPath, $dataClass)->getForm();
|
||||
}
|
||||
|
||||
protected function getMockForm()
|
||||
@ -608,7 +608,7 @@ class DelegatingValidationListenerTest extends \PHPUnit_Framework_TestCase
|
||||
$context = $this->getExecutionContext();
|
||||
$graphWalker = $context->getGraphWalker();
|
||||
$object = $this->getMock('\stdClass');
|
||||
$form = $this->getBuilder()
|
||||
$form = $this->getBuilder('name', null, '\stdClass')
|
||||
->setAttribute('validation_groups', array('group1', 'group2'))
|
||||
->getForm();
|
||||
|
||||
@ -629,7 +629,7 @@ class DelegatingValidationListenerTest extends \PHPUnit_Framework_TestCase
|
||||
$context = $this->getExecutionContext();
|
||||
$graphWalker = $context->getGraphWalker();
|
||||
$object = $this->getMock('\stdClass');
|
||||
$form = $this->getBuilder()
|
||||
$form = $this->getBuilder('name', null, '\stdClass')
|
||||
->setAttribute('validation_groups', array($this, 'getValidationGroups'))
|
||||
->getForm();
|
||||
|
||||
@ -650,7 +650,7 @@ class DelegatingValidationListenerTest extends \PHPUnit_Framework_TestCase
|
||||
$context = $this->getExecutionContext();
|
||||
$graphWalker = $context->getGraphWalker();
|
||||
$object = $this->getMock('\stdClass');
|
||||
$form = $this->getBuilder()
|
||||
$form = $this->getBuilder('name', null, '\stdClass')
|
||||
->setAttribute('validation_groups', function(FormInterface $form){
|
||||
return array('group1', 'group2');
|
||||
})
|
||||
@ -677,7 +677,7 @@ class DelegatingValidationListenerTest extends \PHPUnit_Framework_TestCase
|
||||
$parent = $this->getBuilder()
|
||||
->setAttribute('validation_groups', 'group')
|
||||
->getForm();
|
||||
$child = $this->getBuilder()
|
||||
$child = $this->getBuilder('name', null, '\stdClass')
|
||||
->setAttribute('validation_groups', null)
|
||||
->getForm();
|
||||
$parent->add($child);
|
||||
@ -700,7 +700,7 @@ class DelegatingValidationListenerTest extends \PHPUnit_Framework_TestCase
|
||||
$parent = $this->getBuilder()
|
||||
->setAttribute('validation_groups', array($this, 'getValidationGroups'))
|
||||
->getForm();
|
||||
$child = $this->getBuilder()
|
||||
$child = $this->getBuilder('name', null, '\stdClass')
|
||||
->setAttribute('validation_groups', null)
|
||||
->getForm();
|
||||
$parent->add($child);
|
||||
@ -728,7 +728,7 @@ class DelegatingValidationListenerTest extends \PHPUnit_Framework_TestCase
|
||||
return array('group1', 'group2');
|
||||
})
|
||||
->getForm();
|
||||
$child = $this->getBuilder()
|
||||
$child = $this->getBuilder('name', null, '\stdClass')
|
||||
->setAttribute('validation_groups', null)
|
||||
->getForm();
|
||||
$parent->add($child);
|
||||
@ -750,7 +750,7 @@ class DelegatingValidationListenerTest extends \PHPUnit_Framework_TestCase
|
||||
$context = $this->getExecutionContext('foo.bar');
|
||||
$graphWalker = $context->getGraphWalker();
|
||||
$object = $this->getMock('\stdClass');
|
||||
$form = $this->getForm();
|
||||
$form = $this->getForm('name', null, '\stdClass');
|
||||
|
||||
$graphWalker->expects($this->once())
|
||||
->method('walkReference')
|
||||
|
@ -31,7 +31,7 @@ class FooType extends AbstractType
|
||||
|
||||
public function createBuilder($name, FormFactoryInterface $factory, array $options)
|
||||
{
|
||||
return new FormBuilder($name, $factory, new EventDispatcher());
|
||||
return new FormBuilder($name, null, new EventDispatcher(), $factory);
|
||||
}
|
||||
|
||||
public function getDefaultOptions()
|
||||
|
@ -25,7 +25,7 @@ class FormBuilderTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
$this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
|
||||
$this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface');
|
||||
$this->builder = new FormBuilder('name', $this->factory, $this->dispatcher);
|
||||
$this->builder = new FormBuilder('name', null, $this->dispatcher, $this->factory);
|
||||
}
|
||||
|
||||
protected function tearDown()
|
||||
@ -60,7 +60,7 @@ class FormBuilderTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
public function testAddWithGuessFluent()
|
||||
{
|
||||
$this->builder = new FormBuilder('name', $this->factory, $this->dispatcher, 'stdClass');
|
||||
$this->builder = new FormBuilder('name', 'stdClass', $this->dispatcher, $this->factory);
|
||||
$builder = $this->builder->add('foo');
|
||||
$this->assertSame($builder, $this->builder);
|
||||
}
|
||||
@ -83,7 +83,7 @@ class FormBuilderTest extends \PHPUnit_Framework_TestCase
|
||||
$this->factory->expects($this->once())
|
||||
->method('createNamedBuilder')
|
||||
->with('text', 'foo')
|
||||
->will($this->returnValue(new FormBuilder('foo', $this->factory, $this->dispatcher)));
|
||||
->will($this->returnValue(new FormBuilder('foo', null, $this->dispatcher, $this->factory)));
|
||||
|
||||
$this->assertCount(0, $this->builder->all());
|
||||
$this->assertFalse($this->builder->has('foo'));
|
||||
@ -159,7 +159,7 @@ class FormBuilderTest extends \PHPUnit_Framework_TestCase
|
||||
->with('stdClass', $expectedName, null, $expectedOptions)
|
||||
->will($this->returnValue($this->getFormBuilder()));
|
||||
|
||||
$this->builder = new FormBuilder('name', $this->factory, $this->dispatcher, 'stdClass');
|
||||
$this->builder = new FormBuilder('name', 'stdClass', $this->dispatcher, $this->factory);
|
||||
$this->builder->add($expectedName, null, $expectedOptions);
|
||||
$builder = $this->builder->get($expectedName);
|
||||
|
||||
@ -173,14 +173,14 @@ class FormBuilderTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
public function testGetParentForAddedBuilder()
|
||||
{
|
||||
$builder = new FormBuilder('name', $this->factory, $this->dispatcher);
|
||||
$builder = new FormBuilder('name', null, $this->dispatcher, $this->factory);
|
||||
$this->builder->add($builder);
|
||||
$this->assertSame($this->builder, $builder->getParent());
|
||||
}
|
||||
|
||||
public function testGetParentForRemovedBuilder()
|
||||
{
|
||||
$builder = new FormBuilder('name', $this->factory, $this->dispatcher);
|
||||
$builder = new FormBuilder('name', null, $this->dispatcher, $this->factory);
|
||||
$this->builder->add($builder);
|
||||
$this->builder->remove('name');
|
||||
$this->assertNull($builder->getParent());
|
||||
@ -188,7 +188,7 @@ class FormBuilderTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
public function testGetParentForCreatedBuilder()
|
||||
{
|
||||
$this->builder = new FormBuilder('name', $this->factory, $this->dispatcher, 'stdClass');
|
||||
$this->builder = new FormBuilder('name', 'stdClass', $this->dispatcher, $this->factory);
|
||||
$this->factory
|
||||
->expects($this->once())
|
||||
->method('createNamedBuilder')
|
||||
|
@ -64,7 +64,7 @@ class FormConfigTest extends \PHPUnit_Framework_TestCase
|
||||
$dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
|
||||
|
||||
try {
|
||||
new FormConfig($name, $dispatcher);
|
||||
new FormConfig($name, null, $dispatcher);
|
||||
if (!$accepted) {
|
||||
$this->fail(sprintf('The value "%s" should not be accepted', $name));
|
||||
}
|
||||
|
@ -598,7 +598,7 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase
|
||||
$this->extension1->addType($type);
|
||||
|
||||
$parentBuilder = $this->getMockBuilder('Symfony\Component\Form\FormBuilder')
|
||||
->setConstructorArgs(array('name', $this->factory, $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface')))
|
||||
->setConstructorArgs(array('name', null, $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'), $this->factory))
|
||||
->getMock()
|
||||
;
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
namespace Symfony\Component\Form\Tests;
|
||||
|
||||
use Symfony\Component\Form\Form;
|
||||
use Symfony\Component\Form\Util\PropertyPath;
|
||||
use Symfony\Component\Form\FormConfig;
|
||||
use Symfony\Component\Form\FormView;
|
||||
use Symfony\Component\Form\FormBuilder;
|
||||
@ -61,7 +62,7 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
||||
'foo' => 'bar',
|
||||
));
|
||||
|
||||
$config = new FormConfig('name', $this->dispatcher);
|
||||
$config = new FormConfig('name', null, $this->dispatcher);
|
||||
$config->appendClientTransformer($client);
|
||||
$config->appendNormTransformer($norm);
|
||||
$form = new Form($config);
|
||||
@ -1201,14 +1202,41 @@ class FormTest extends \PHPUnit_Framework_TestCase
|
||||
*/
|
||||
public function testFormCannotHaveEmptyNameNotInRootLevel()
|
||||
{
|
||||
$parent = $this->getBuilder()
|
||||
$this->getBuilder()
|
||||
->add($this->getBuilder(''))
|
||||
->getForm();
|
||||
}
|
||||
|
||||
protected function getBuilder($name = 'name', EventDispatcherInterface $dispatcher = null)
|
||||
public function testGetPropertyPathReturnsConfiguredPath()
|
||||
{
|
||||
return new FormBuilder($name, $this->factory, $dispatcher ?: $this->dispatcher);
|
||||
$form = $this->getBuilder()->setPropertyPath('address.street')->getForm();
|
||||
|
||||
$this->assertEquals(new PropertyPath('address.street'), $form->getPropertyPath());
|
||||
}
|
||||
|
||||
// see https://github.com/symfony/symfony/issues/3903
|
||||
public function testGetPropertyPathDefaultsToNameIfParentHasDataClass()
|
||||
{
|
||||
$parent = $this->getBuilder(null, null, 'stdClass')->getForm();
|
||||
$form = $this->getBuilder('name')->getForm();
|
||||
$parent->add($form);
|
||||
|
||||
$this->assertEquals(new PropertyPath('name'), $form->getPropertyPath());
|
||||
}
|
||||
|
||||
// see https://github.com/symfony/symfony/issues/3903
|
||||
public function testGetPropertyPathDefaultsToIndexedNameIfParentDataClassIsNull()
|
||||
{
|
||||
$parent = $this->getBuilder()->getForm();
|
||||
$form = $this->getBuilder('name')->getForm();
|
||||
$parent->add($form);
|
||||
|
||||
$this->assertEquals(new PropertyPath('[name]'), $form->getPropertyPath());
|
||||
}
|
||||
|
||||
protected function getBuilder($name = 'name', EventDispatcherInterface $dispatcher = null, $dataClass = null)
|
||||
{
|
||||
return new FormBuilder($name, $dataClass, $dispatcher ?: $this->dispatcher, $this->factory);
|
||||
}
|
||||
|
||||
protected function getMockForm($name = 'name')
|
||||
|
Reference in New Issue
Block a user