add new way of mapping data using callback functions
This commit is contained in:
parent
845c232dd5
commit
878effaf47
@ -16,6 +16,28 @@ FrameworkBundle
|
|||||||
used to be added by default to the seed, which is not the case anymore. This allows sharing caches between
|
used to be added by default to the seed, which is not the case anymore. This allows sharing caches between
|
||||||
apps or different environments.
|
apps or different environments.
|
||||||
|
|
||||||
|
Form
|
||||||
|
----
|
||||||
|
|
||||||
|
* Deprecated `PropertyPathMapper` in favor of `DataMapper` and `PropertyPathAccessor`.
|
||||||
|
|
||||||
|
Before:
|
||||||
|
|
||||||
|
```php
|
||||||
|
use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper;
|
||||||
|
|
||||||
|
$builder->setDataMapper(new PropertyPathMapper());
|
||||||
|
```
|
||||||
|
|
||||||
|
After:
|
||||||
|
|
||||||
|
```php
|
||||||
|
use Symfony\Component\Form\Extension\Core\DataAccessor\PropertyPathAccessor;
|
||||||
|
use Symfony\Component\Form\Extension\Core\DataMapper\DataMapper;
|
||||||
|
|
||||||
|
$builder->setDataMapper(new DataMapper(new PropertyPathAccessor()));
|
||||||
|
```
|
||||||
|
|
||||||
Lock
|
Lock
|
||||||
----
|
----
|
||||||
|
|
||||||
|
@ -48,6 +48,7 @@ Form
|
|||||||
* Added argument `callable|null $filter` to `ChoiceListFactoryInterface::createListFromChoices()` and `createListFromLoader()`.
|
* Added argument `callable|null $filter` to `ChoiceListFactoryInterface::createListFromChoices()` and `createListFromLoader()`.
|
||||||
* The `Symfony\Component\Form\Extension\Validator\Util\ServerParams` class has been removed, use its parent `Symfony\Component\Form\Util\ServerParams` instead.
|
* The `Symfony\Component\Form\Extension\Validator\Util\ServerParams` class has been removed, use its parent `Symfony\Component\Form\Util\ServerParams` instead.
|
||||||
* The `NumberToLocalizedStringTransformer::ROUND_*` constants have been removed, use `\NumberFormatter::ROUND_*` instead.
|
* The `NumberToLocalizedStringTransformer::ROUND_*` constants have been removed, use `\NumberFormatter::ROUND_*` instead.
|
||||||
|
* Removed `PropertyPathMapper` in favor of `DataMapper` and `PropertyPathAccessor`.
|
||||||
|
|
||||||
FrameworkBundle
|
FrameworkBundle
|
||||||
---------------
|
---------------
|
||||||
|
@ -5,6 +5,8 @@ CHANGELOG
|
|||||||
-----
|
-----
|
||||||
|
|
||||||
* Added support for using the `{{ label }}` placeholder in constraint messages, which is replaced in the `ViolationMapper` by the corresponding field form label.
|
* Added support for using the `{{ label }}` placeholder in constraint messages, which is replaced in the `ViolationMapper` by the corresponding field form label.
|
||||||
|
* Added `DataMapper`, `ChainAccessor`, `PropertyPathAccessor` and `CallbackAccessor` with new callable `getter` and `setter` options for each form type
|
||||||
|
* Deprecated `PropertyPathMapper` in favor of `DataMapper` and `PropertyPathAccessor`
|
||||||
|
|
||||||
5.1.0
|
5.1.0
|
||||||
-----
|
-----
|
||||||
|
69
src/Symfony/Component/Form/DataAccessorInterface.php
Normal file
69
src/Symfony/Component/Form/DataAccessorInterface.php
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
<?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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes and reads values to/from an object or array bound to a form.
|
||||||
|
*
|
||||||
|
* @author Yonel Ceruto <yonelceruto@gmail.com>
|
||||||
|
*/
|
||||||
|
interface DataAccessorInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns the value at the end of the property of the object graph.
|
||||||
|
*
|
||||||
|
* @param object|array $viewData The view data of the compound form
|
||||||
|
* @param FormInterface $form The {@link FormInterface()} instance to check
|
||||||
|
*
|
||||||
|
* @return mixed The value at the end of the property
|
||||||
|
*
|
||||||
|
* @throws Exception\AccessException If unable to read from the given form data
|
||||||
|
*/
|
||||||
|
public function getValue($viewData, FormInterface $form);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the value at the end of the property of the object graph.
|
||||||
|
*
|
||||||
|
* @param object|array $viewData The view data of the compound form
|
||||||
|
* @param mixed $value The value to set at the end of the object graph
|
||||||
|
* @param FormInterface $form The {@link FormInterface()} instance to check
|
||||||
|
*
|
||||||
|
* @throws Exception\AccessException If unable to write the given value
|
||||||
|
*/
|
||||||
|
public function setValue(&$viewData, $value, FormInterface $form): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether a value can be read from an object graph.
|
||||||
|
*
|
||||||
|
* Whenever this method returns true, {@link getValue()} is guaranteed not
|
||||||
|
* to throw an exception when called with the same arguments.
|
||||||
|
*
|
||||||
|
* @param object|array $viewData The view data of the compound form
|
||||||
|
* @param FormInterface $form The {@link FormInterface()} instance to check
|
||||||
|
*
|
||||||
|
* @return bool Whether the value can be read
|
||||||
|
*/
|
||||||
|
public function isReadable($viewData, FormInterface $form): bool;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether a value can be written at a given object graph.
|
||||||
|
*
|
||||||
|
* Whenever this method returns true, {@link setValue()} is guaranteed not
|
||||||
|
* to throw an exception when called with the same arguments.
|
||||||
|
*
|
||||||
|
* @param object|array $viewData The view data of the compound form
|
||||||
|
* @param FormInterface $form The {@link FormInterface()} instance to check
|
||||||
|
*
|
||||||
|
* @return bool Whether the value can be set
|
||||||
|
*/
|
||||||
|
public function isWritable($viewData, FormInterface $form): bool;
|
||||||
|
}
|
16
src/Symfony/Component/Form/Exception/AccessException.php
Normal file
16
src/Symfony/Component/Form/Exception/AccessException.php
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?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\Exception;
|
||||||
|
|
||||||
|
class AccessException extends RuntimeException
|
||||||
|
{
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
<?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\Extension\Core\DataAccessor;
|
||||||
|
|
||||||
|
use Symfony\Component\Form\DataAccessorInterface;
|
||||||
|
use Symfony\Component\Form\Exception\AccessException;
|
||||||
|
use Symfony\Component\Form\FormInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes and reads values to/from an object or array using callback functions.
|
||||||
|
*
|
||||||
|
* @author Yonel Ceruto <yonelceruto@gmail.com>
|
||||||
|
*/
|
||||||
|
class CallbackAccessor implements DataAccessorInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getValue($data, FormInterface $form)
|
||||||
|
{
|
||||||
|
if (null === $getter = $form->getConfig()->getOption('getter')) {
|
||||||
|
throw new AccessException('Unable to read from the given form data as no getter is defined.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return ($getter)($data, $form);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function setValue(&$data, $value, FormInterface $form): void
|
||||||
|
{
|
||||||
|
if (null === $setter = $form->getConfig()->getOption('setter')) {
|
||||||
|
throw new AccessException('Unable to write the given value as no setter is defined.');
|
||||||
|
}
|
||||||
|
|
||||||
|
($setter)($data, $form->getData(), $form);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function isReadable($data, FormInterface $form): bool
|
||||||
|
{
|
||||||
|
return null !== $form->getConfig()->getOption('getter');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function isWritable($data, FormInterface $form): bool
|
||||||
|
{
|
||||||
|
return null !== $form->getConfig()->getOption('setter');
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,90 @@
|
|||||||
|
<?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\Extension\Core\DataAccessor;
|
||||||
|
|
||||||
|
use Symfony\Component\Form\DataAccessorInterface;
|
||||||
|
use Symfony\Component\Form\Exception\AccessException;
|
||||||
|
use Symfony\Component\Form\FormInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Yonel Ceruto <yonelceruto@gmail.com>
|
||||||
|
*/
|
||||||
|
class ChainAccessor implements DataAccessorInterface
|
||||||
|
{
|
||||||
|
private $accessors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param DataAccessorInterface[]|iterable $accessors
|
||||||
|
*/
|
||||||
|
public function __construct(iterable $accessors)
|
||||||
|
{
|
||||||
|
$this->accessors = $accessors;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getValue($data, FormInterface $form)
|
||||||
|
{
|
||||||
|
foreach ($this->accessors as $accessor) {
|
||||||
|
if ($accessor->isReadable($data, $form)) {
|
||||||
|
return $accessor->getValue($data, $form);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new AccessException('Unable to read from the given form data as no accessor in the chain is able to read the data.');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function setValue(&$data, $value, FormInterface $form): void
|
||||||
|
{
|
||||||
|
foreach ($this->accessors as $accessor) {
|
||||||
|
if ($accessor->isWritable($data, $form)) {
|
||||||
|
$accessor->setValue($data, $value, $form);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new AccessException('Unable to write the given value as no accessor in the chain is able to set the data.');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function isReadable($data, FormInterface $form): bool
|
||||||
|
{
|
||||||
|
foreach ($this->accessors as $accessor) {
|
||||||
|
if ($accessor->isReadable($data, $form)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function isWritable($data, FormInterface $form): bool
|
||||||
|
{
|
||||||
|
foreach ($this->accessors as $accessor) {
|
||||||
|
if ($accessor->isWritable($data, $form)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,102 @@
|
|||||||
|
<?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\Extension\Core\DataAccessor;
|
||||||
|
|
||||||
|
use Symfony\Component\Form\DataAccessorInterface;
|
||||||
|
use Symfony\Component\Form\Exception\AccessException;
|
||||||
|
use Symfony\Component\Form\FormInterface;
|
||||||
|
use Symfony\Component\PropertyAccess\Exception\AccessException as PropertyAccessException;
|
||||||
|
use Symfony\Component\PropertyAccess\Exception\UninitializedPropertyException;
|
||||||
|
use Symfony\Component\PropertyAccess\PropertyAccess;
|
||||||
|
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes and reads values to/from an object or array using property path.
|
||||||
|
*
|
||||||
|
* @author Yonel Ceruto <yonelceruto@gmail.com>
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
class PropertyPathAccessor implements DataAccessorInterface
|
||||||
|
{
|
||||||
|
private $propertyAccessor;
|
||||||
|
|
||||||
|
public function __construct(PropertyAccessorInterface $propertyAccessor = null)
|
||||||
|
{
|
||||||
|
$this->propertyAccessor = $propertyAccessor ?? PropertyAccess::createPropertyAccessor();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getValue($data, FormInterface $form)
|
||||||
|
{
|
||||||
|
if (null === $propertyPath = $form->getPropertyPath()) {
|
||||||
|
throw new AccessException('Unable to read from the given form data as no property path is defined.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->getPropertyValue($data, $propertyPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function setValue(&$data, $propertyValue, FormInterface $form): void
|
||||||
|
{
|
||||||
|
if (null === $propertyPath = $form->getPropertyPath()) {
|
||||||
|
throw new AccessException('Unable to write the given value as no property path is defined.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the field is of type DateTimeInterface and the data is the same skip the update to
|
||||||
|
// keep the original object hash
|
||||||
|
if ($propertyValue instanceof \DateTimeInterface && $propertyValue == $this->getPropertyValue($data, $propertyPath)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the data is identical to the value in $data, we are
|
||||||
|
// dealing with a reference
|
||||||
|
if (!\is_object($data) || !$form->getConfig()->getByReference() || $propertyValue !== $this->getPropertyValue($data, $propertyPath)) {
|
||||||
|
$this->propertyAccessor->setValue($data, $propertyPath, $propertyValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function isReadable($data, FormInterface $form): bool
|
||||||
|
{
|
||||||
|
return null !== $form->getPropertyPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function isWritable($data, FormInterface $form): bool
|
||||||
|
{
|
||||||
|
return null !== $form->getPropertyPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getPropertyValue($data, $propertyPath)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return $this->propertyAccessor->getValue($data, $propertyPath);
|
||||||
|
} catch (PropertyAccessException $e) {
|
||||||
|
if (!$e instanceof UninitializedPropertyException
|
||||||
|
// For versions without UninitializedPropertyException check the exception message
|
||||||
|
&& (class_exists(UninitializedPropertyException::class) || false === strpos($e->getMessage(), 'You should initialize it'))
|
||||||
|
) {
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,83 @@
|
|||||||
|
<?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\Extension\Core\DataMapper;
|
||||||
|
|
||||||
|
use Symfony\Component\Form\DataAccessorInterface;
|
||||||
|
use Symfony\Component\Form\DataMapperInterface;
|
||||||
|
use Symfony\Component\Form\Exception\UnexpectedTypeException;
|
||||||
|
use Symfony\Component\Form\Extension\Core\DataAccessor\CallbackAccessor;
|
||||||
|
use Symfony\Component\Form\Extension\Core\DataAccessor\ChainAccessor;
|
||||||
|
use Symfony\Component\Form\Extension\Core\DataAccessor\PropertyPathAccessor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps arrays/objects to/from forms using data accessors.
|
||||||
|
*
|
||||||
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*/
|
||||||
|
class DataMapper implements DataMapperInterface
|
||||||
|
{
|
||||||
|
private $dataAccessor;
|
||||||
|
|
||||||
|
public function __construct(DataAccessorInterface $dataAccessor = null)
|
||||||
|
{
|
||||||
|
$this->dataAccessor = $dataAccessor ?? new ChainAccessor([
|
||||||
|
new CallbackAccessor(),
|
||||||
|
new PropertyPathAccessor(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function mapDataToForms($data, iterable $forms): void
|
||||||
|
{
|
||||||
|
$empty = null === $data || [] === $data;
|
||||||
|
|
||||||
|
if (!$empty && !\is_array($data) && !\is_object($data)) {
|
||||||
|
throw new UnexpectedTypeException($data, 'object, array or empty');
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($forms as $form) {
|
||||||
|
$config = $form->getConfig();
|
||||||
|
|
||||||
|
if (!$empty && $config->getMapped() && $this->dataAccessor->isReadable($data, $form)) {
|
||||||
|
$form->setData($this->dataAccessor->getValue($data, $form));
|
||||||
|
} else {
|
||||||
|
$form->setData($config->getData());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function mapFormsToData(iterable $forms, &$data): void
|
||||||
|
{
|
||||||
|
if (null === $data) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!\is_array($data) && !\is_object($data)) {
|
||||||
|
throw new UnexpectedTypeException($data, 'object, array or empty');
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($forms as $form) {
|
||||||
|
$config = $form->getConfig();
|
||||||
|
|
||||||
|
// Write-back is disabled if the form is not synchronized (transformation failed),
|
||||||
|
// if the form was not submitted and if the form is disabled (modification not allowed)
|
||||||
|
if ($config->getMapped() && $form->isSubmitted() && $form->isSynchronized() && !$form->isDisabled() && $this->dataAccessor->isWritable($data, $form)) {
|
||||||
|
$this->dataAccessor->setValue($data, $form->getData(), $form);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -18,10 +18,14 @@ use Symfony\Component\PropertyAccess\Exception\UninitializedPropertyException;
|
|||||||
use Symfony\Component\PropertyAccess\PropertyAccess;
|
use Symfony\Component\PropertyAccess\PropertyAccess;
|
||||||
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
|
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
|
||||||
|
|
||||||
|
trigger_deprecation('symfony/form', '5.2', 'The "%s" class is deprecated. Use "%s" instead.', PropertyPathMapper::class, DataMapper::class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps arrays/objects to/from forms using property paths.
|
* Maps arrays/objects to/from forms using property paths.
|
||||||
*
|
*
|
||||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
|
*
|
||||||
|
* @deprecated since symfony/form 5.2. Use {@see DataMapper} instead.
|
||||||
*/
|
*/
|
||||||
class PropertyPathMapper implements DataMapperInterface
|
class PropertyPathMapper implements DataMapperInterface
|
||||||
{
|
{
|
||||||
|
@ -12,7 +12,10 @@
|
|||||||
namespace Symfony\Component\Form\Extension\Core\Type;
|
namespace Symfony\Component\Form\Extension\Core\Type;
|
||||||
|
|
||||||
use Symfony\Component\Form\Exception\LogicException;
|
use Symfony\Component\Form\Exception\LogicException;
|
||||||
use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper;
|
use Symfony\Component\Form\Extension\Core\DataAccessor\CallbackAccessor;
|
||||||
|
use Symfony\Component\Form\Extension\Core\DataAccessor\ChainAccessor;
|
||||||
|
use Symfony\Component\Form\Extension\Core\DataAccessor\PropertyPathAccessor;
|
||||||
|
use Symfony\Component\Form\Extension\Core\DataMapper\DataMapper;
|
||||||
use Symfony\Component\Form\Extension\Core\EventListener\TrimListener;
|
use Symfony\Component\Form\Extension\Core\EventListener\TrimListener;
|
||||||
use Symfony\Component\Form\FormBuilderInterface;
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
use Symfony\Component\Form\FormConfigBuilderInterface;
|
use Symfony\Component\Form\FormConfigBuilderInterface;
|
||||||
@ -25,11 +28,14 @@ use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
|
|||||||
|
|
||||||
class FormType extends BaseType
|
class FormType extends BaseType
|
||||||
{
|
{
|
||||||
private $propertyAccessor;
|
private $dataMapper;
|
||||||
|
|
||||||
public function __construct(PropertyAccessorInterface $propertyAccessor = null)
|
public function __construct(PropertyAccessorInterface $propertyAccessor = null)
|
||||||
{
|
{
|
||||||
$this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor();
|
$this->dataMapper = new DataMapper(new ChainAccessor([
|
||||||
|
new CallbackAccessor(),
|
||||||
|
new PropertyPathAccessor($propertyAccessor ?? PropertyAccess::createPropertyAccessor()),
|
||||||
|
]));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -52,7 +58,7 @@ class FormType extends BaseType
|
|||||||
->setCompound($options['compound'])
|
->setCompound($options['compound'])
|
||||||
->setData($isDataOptionSet ? $options['data'] : null)
|
->setData($isDataOptionSet ? $options['data'] : null)
|
||||||
->setDataLocked($isDataOptionSet)
|
->setDataLocked($isDataOptionSet)
|
||||||
->setDataMapper($options['compound'] ? new PropertyPathMapper($this->propertyAccessor) : null)
|
->setDataMapper($options['compound'] ? $this->dataMapper : null)
|
||||||
->setMethod($options['method'])
|
->setMethod($options['method'])
|
||||||
->setAction($options['action']);
|
->setAction($options['action']);
|
||||||
|
|
||||||
@ -202,6 +208,8 @@ class FormType extends BaseType
|
|||||||
'invalid_message' => 'This value is not valid.',
|
'invalid_message' => 'This value is not valid.',
|
||||||
'invalid_message_parameters' => [],
|
'invalid_message_parameters' => [],
|
||||||
'is_empty_callback' => null,
|
'is_empty_callback' => null,
|
||||||
|
'getter' => null,
|
||||||
|
'setter' => null,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$resolver->setAllowedTypes('label_attr', 'array');
|
$resolver->setAllowedTypes('label_attr', 'array');
|
||||||
@ -211,6 +219,11 @@ class FormType extends BaseType
|
|||||||
$resolver->setAllowedTypes('help_attr', 'array');
|
$resolver->setAllowedTypes('help_attr', 'array');
|
||||||
$resolver->setAllowedTypes('help_html', 'bool');
|
$resolver->setAllowedTypes('help_html', 'bool');
|
||||||
$resolver->setAllowedTypes('is_empty_callback', ['null', 'callable']);
|
$resolver->setAllowedTypes('is_empty_callback', ['null', 'callable']);
|
||||||
|
$resolver->setAllowedTypes('getter', ['null', 'callable']);
|
||||||
|
$resolver->setAllowedTypes('setter', ['null', 'callable']);
|
||||||
|
|
||||||
|
$resolver->setInfo('getter', 'A callable that accepts two arguments (the view data and the current form field) and must return a value.');
|
||||||
|
$resolver->setInfo('setter', 'A callable that accepts three arguments (a reference to the view data, the submitted value and the current form field).');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -13,7 +13,7 @@ namespace Symfony\Component\Form\Tests;
|
|||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||||
use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper;
|
use Symfony\Component\Form\Extension\Core\DataMapper\DataMapper;
|
||||||
use Symfony\Component\Form\Form;
|
use Symfony\Component\Form\Form;
|
||||||
use Symfony\Component\Form\FormBuilder;
|
use Symfony\Component\Form\FormBuilder;
|
||||||
use Symfony\Component\Form\FormError;
|
use Symfony\Component\Form\FormError;
|
||||||
@ -409,7 +409,7 @@ abstract class AbstractRequestHandlerTest extends TestCase
|
|||||||
$builder->setCompound($compound);
|
$builder->setCompound($compound);
|
||||||
|
|
||||||
if ($compound) {
|
if ($compound) {
|
||||||
$builder->setDataMapper(new PropertyPathMapper());
|
$builder->setDataMapper(new DataMapper());
|
||||||
}
|
}
|
||||||
|
|
||||||
return $builder;
|
return $builder;
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
namespace Symfony\Component\Form\Tests;
|
namespace Symfony\Component\Form\Tests;
|
||||||
|
|
||||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||||
use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper;
|
use Symfony\Component\Form\Extension\Core\DataMapper\DataMapper;
|
||||||
use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler;
|
use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler;
|
||||||
use Symfony\Component\Form\FormError;
|
use Symfony\Component\Form\FormError;
|
||||||
use Symfony\Component\Form\FormEvent;
|
use Symfony\Component\Form\FormEvent;
|
||||||
@ -394,17 +394,17 @@ class CompoundFormTest extends AbstractFormTest
|
|||||||
{
|
{
|
||||||
$form = $this->getBuilder()
|
$form = $this->getBuilder()
|
||||||
->setCompound(true)
|
->setCompound(true)
|
||||||
// We test using PropertyPathMapper on purpose. The traversal logic
|
// We test using DataMapper on purpose. The traversal logic
|
||||||
// is currently contained in InheritDataAwareIterator, but even
|
// is currently contained in InheritDataAwareIterator, but even
|
||||||
// if that changes, this test should still function.
|
// if that changes, this test should still function.
|
||||||
->setDataMapper(new PropertyPathMapper())
|
->setDataMapper(new DataMapper())
|
||||||
->getForm();
|
->getForm();
|
||||||
|
|
||||||
$childToBeRemoved = $this->createForm('removed', false);
|
$childToBeRemoved = $this->createForm('removed', false);
|
||||||
$childToBeAdded = $this->createForm('added', false);
|
$childToBeAdded = $this->createForm('added', false);
|
||||||
$child = $this->getBuilder('child', new EventDispatcher())
|
$child = $this->getBuilder('child', new EventDispatcher())
|
||||||
->setCompound(true)
|
->setCompound(true)
|
||||||
->setDataMapper(new PropertyPathMapper())
|
->setDataMapper(new DataMapper())
|
||||||
->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($form, $childToBeAdded) {
|
->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($form, $childToBeAdded) {
|
||||||
$form->remove('removed');
|
$form->remove('removed');
|
||||||
$form->add($childToBeAdded);
|
$form->add($childToBeAdded);
|
||||||
@ -449,7 +449,7 @@ class CompoundFormTest extends AbstractFormTest
|
|||||||
|
|
||||||
public function testSetDataDoesNotMapViewDataToChildrenWithLockedSetData()
|
public function testSetDataDoesNotMapViewDataToChildrenWithLockedSetData()
|
||||||
{
|
{
|
||||||
$mapper = new PropertyPathMapper();
|
$mapper = new DataMapper();
|
||||||
$viewData = [
|
$viewData = [
|
||||||
'firstName' => 'Fabien',
|
'firstName' => 'Fabien',
|
||||||
'lastName' => 'Pot',
|
'lastName' => 'Pot',
|
||||||
|
@ -0,0 +1,427 @@
|
|||||||
|
<?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\Extension\Core\DataMapper;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||||
|
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||||
|
use Symfony\Component\Form\Extension\Core\DataMapper\DataMapper;
|
||||||
|
use Symfony\Component\Form\Form;
|
||||||
|
use Symfony\Component\Form\FormConfigBuilder;
|
||||||
|
use Symfony\Component\Form\Tests\Fixtures\TypehintedPropertiesCar;
|
||||||
|
use Symfony\Component\PropertyAccess\PropertyPath;
|
||||||
|
|
||||||
|
class DataMapperTest extends TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var DataMapper
|
||||||
|
*/
|
||||||
|
private $mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var EventDispatcherInterface
|
||||||
|
*/
|
||||||
|
private $dispatcher;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
$this->mapper = new DataMapper();
|
||||||
|
$this->dispatcher = new EventDispatcher();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMapDataToFormsPassesObjectRefIfByReference()
|
||||||
|
{
|
||||||
|
$car = new \stdClass();
|
||||||
|
$engine = new \stdClass();
|
||||||
|
$car->engine = $engine;
|
||||||
|
$propertyPath = new PropertyPath('engine');
|
||||||
|
|
||||||
|
$config = new FormConfigBuilder('name', \stdClass::class, $this->dispatcher);
|
||||||
|
$config->setByReference(true);
|
||||||
|
$config->setPropertyPath($propertyPath);
|
||||||
|
$form = new Form($config);
|
||||||
|
|
||||||
|
$this->mapper->mapDataToForms($car, [$form]);
|
||||||
|
|
||||||
|
self::assertSame($engine, $form->getData());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMapDataToFormsPassesObjectCloneIfNotByReference()
|
||||||
|
{
|
||||||
|
$car = new \stdClass();
|
||||||
|
$engine = new \stdClass();
|
||||||
|
$engine->brand = 'Rolls-Royce';
|
||||||
|
$car->engine = $engine;
|
||||||
|
$propertyPath = new PropertyPath('engine');
|
||||||
|
|
||||||
|
$config = new FormConfigBuilder('name', \stdClass::class, $this->dispatcher);
|
||||||
|
$config->setByReference(false);
|
||||||
|
$config->setPropertyPath($propertyPath);
|
||||||
|
$form = new Form($config);
|
||||||
|
|
||||||
|
$this->mapper->mapDataToForms($car, [$form]);
|
||||||
|
|
||||||
|
self::assertNotSame($engine, $form->getData());
|
||||||
|
self::assertEquals($engine, $form->getData());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMapDataToFormsIgnoresEmptyPropertyPath()
|
||||||
|
{
|
||||||
|
$car = new \stdClass();
|
||||||
|
|
||||||
|
$config = new FormConfigBuilder(null, \stdClass::class, $this->dispatcher);
|
||||||
|
$config->setByReference(true);
|
||||||
|
$form = new Form($config);
|
||||||
|
|
||||||
|
self::assertNull($form->getPropertyPath());
|
||||||
|
|
||||||
|
$this->mapper->mapDataToForms($car, [$form]);
|
||||||
|
|
||||||
|
self::assertNull($form->getData());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMapDataToFormsIgnoresUnmapped()
|
||||||
|
{
|
||||||
|
$car = new \stdClass();
|
||||||
|
$car->engine = new \stdClass();
|
||||||
|
$propertyPath = new PropertyPath('engine');
|
||||||
|
|
||||||
|
$config = new FormConfigBuilder('name', \stdClass::class, $this->dispatcher);
|
||||||
|
$config->setByReference(true);
|
||||||
|
$config->setMapped(false);
|
||||||
|
$config->setPropertyPath($propertyPath);
|
||||||
|
$form = new Form($config);
|
||||||
|
|
||||||
|
$this->mapper->mapDataToForms($car, [$form]);
|
||||||
|
|
||||||
|
self::assertNull($form->getData());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @requires PHP 7.4
|
||||||
|
*/
|
||||||
|
public function testMapDataToFormsIgnoresUninitializedProperties()
|
||||||
|
{
|
||||||
|
$engineForm = new Form(new FormConfigBuilder('engine', null, $this->dispatcher));
|
||||||
|
$colorForm = new Form(new FormConfigBuilder('color', null, $this->dispatcher));
|
||||||
|
|
||||||
|
$car = new TypehintedPropertiesCar();
|
||||||
|
$car->engine = 'BMW';
|
||||||
|
|
||||||
|
$this->mapper->mapDataToForms($car, [$engineForm, $colorForm]);
|
||||||
|
|
||||||
|
self::assertSame($car->engine, $engineForm->getData());
|
||||||
|
self::assertNull($colorForm->getData());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMapDataToFormsSetsDefaultDataIfPassedDataIsNull()
|
||||||
|
{
|
||||||
|
$default = new \stdClass();
|
||||||
|
$propertyPath = new PropertyPath('engine');
|
||||||
|
|
||||||
|
$config = new FormConfigBuilder('name', \stdClass::class, $this->dispatcher);
|
||||||
|
$config->setByReference(true);
|
||||||
|
$config->setPropertyPath($propertyPath);
|
||||||
|
$config->setData($default);
|
||||||
|
|
||||||
|
$form = new Form($config);
|
||||||
|
|
||||||
|
$this->mapper->mapDataToForms(null, [$form]);
|
||||||
|
|
||||||
|
self::assertSame($default, $form->getData());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMapDataToFormsSetsDefaultDataIfPassedDataIsEmptyArray()
|
||||||
|
{
|
||||||
|
$default = new \stdClass();
|
||||||
|
$propertyPath = new PropertyPath('engine');
|
||||||
|
|
||||||
|
$config = new FormConfigBuilder('name', \stdClass::class, $this->dispatcher);
|
||||||
|
$config->setByReference(true);
|
||||||
|
$config->setPropertyPath($propertyPath);
|
||||||
|
$config->setData($default);
|
||||||
|
|
||||||
|
$form = new Form($config);
|
||||||
|
|
||||||
|
$this->mapper->mapDataToForms([], [$form]);
|
||||||
|
|
||||||
|
self::assertSame($default, $form->getData());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMapFormsToDataWritesBackIfNotByReference()
|
||||||
|
{
|
||||||
|
$car = new \stdClass();
|
||||||
|
$car->engine = new \stdClass();
|
||||||
|
$engine = new \stdClass();
|
||||||
|
$engine->brand = 'Rolls-Royce';
|
||||||
|
$propertyPath = new PropertyPath('engine');
|
||||||
|
|
||||||
|
$config = new FormConfigBuilder('name', \stdClass::class, $this->dispatcher);
|
||||||
|
$config->setByReference(false);
|
||||||
|
$config->setPropertyPath($propertyPath);
|
||||||
|
$config->setData($engine);
|
||||||
|
$form = new SubmittedForm($config);
|
||||||
|
|
||||||
|
$this->mapper->mapFormsToData([$form], $car);
|
||||||
|
|
||||||
|
self::assertEquals($engine, $car->engine);
|
||||||
|
self::assertNotSame($engine, $car->engine);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMapFormsToDataWritesBackIfByReferenceButNoReference()
|
||||||
|
{
|
||||||
|
$car = new \stdClass();
|
||||||
|
$car->engine = new \stdClass();
|
||||||
|
$engine = new \stdClass();
|
||||||
|
$propertyPath = new PropertyPath('engine');
|
||||||
|
|
||||||
|
$config = new FormConfigBuilder('name', \stdClass::class, $this->dispatcher);
|
||||||
|
$config->setByReference(true);
|
||||||
|
$config->setPropertyPath($propertyPath);
|
||||||
|
$config->setData($engine);
|
||||||
|
$form = new SubmittedForm($config);
|
||||||
|
|
||||||
|
$this->mapper->mapFormsToData([$form], $car);
|
||||||
|
|
||||||
|
self::assertSame($engine, $car->engine);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMapFormsToDataWritesBackIfByReferenceAndReference()
|
||||||
|
{
|
||||||
|
$car = new \stdClass();
|
||||||
|
$car->engine = 'BMW';
|
||||||
|
$propertyPath = new PropertyPath('engine');
|
||||||
|
|
||||||
|
$config = new FormConfigBuilder('engine', null, $this->dispatcher);
|
||||||
|
$config->setByReference(true);
|
||||||
|
$config->setPropertyPath($propertyPath);
|
||||||
|
$config->setData('Rolls-Royce');
|
||||||
|
$form = new SubmittedForm($config);
|
||||||
|
|
||||||
|
$car->engine = 'Rolls-Royce';
|
||||||
|
|
||||||
|
$this->mapper->mapFormsToData([$form], $car);
|
||||||
|
|
||||||
|
self::assertSame('Rolls-Royce', $car->engine);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMapFormsToDataIgnoresUnmapped()
|
||||||
|
{
|
||||||
|
$initialEngine = new \stdClass();
|
||||||
|
$car = new \stdClass();
|
||||||
|
$car->engine = $initialEngine;
|
||||||
|
$engine = new \stdClass();
|
||||||
|
$propertyPath = new PropertyPath('engine');
|
||||||
|
|
||||||
|
$config = new FormConfigBuilder('name', \stdClass::class, $this->dispatcher);
|
||||||
|
$config->setByReference(true);
|
||||||
|
$config->setPropertyPath($propertyPath);
|
||||||
|
$config->setData($engine);
|
||||||
|
$config->setMapped(false);
|
||||||
|
$form = new SubmittedForm($config);
|
||||||
|
|
||||||
|
$this->mapper->mapFormsToData([$form], $car);
|
||||||
|
|
||||||
|
self::assertSame($initialEngine, $car->engine);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMapFormsToDataIgnoresUnsubmittedForms()
|
||||||
|
{
|
||||||
|
$initialEngine = new \stdClass();
|
||||||
|
$car = new \stdClass();
|
||||||
|
$car->engine = $initialEngine;
|
||||||
|
$engine = new \stdClass();
|
||||||
|
$propertyPath = new PropertyPath('engine');
|
||||||
|
|
||||||
|
$config = new FormConfigBuilder('name', \stdClass::class, $this->dispatcher);
|
||||||
|
$config->setByReference(true);
|
||||||
|
$config->setPropertyPath($propertyPath);
|
||||||
|
$config->setData($engine);
|
||||||
|
$form = new Form($config);
|
||||||
|
|
||||||
|
$this->mapper->mapFormsToData([$form], $car);
|
||||||
|
|
||||||
|
self::assertSame($initialEngine, $car->engine);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMapFormsToDataIgnoresEmptyData()
|
||||||
|
{
|
||||||
|
$initialEngine = new \stdClass();
|
||||||
|
$car = new \stdClass();
|
||||||
|
$car->engine = $initialEngine;
|
||||||
|
$propertyPath = new PropertyPath('engine');
|
||||||
|
|
||||||
|
$config = new FormConfigBuilder('name', \stdClass::class, $this->dispatcher);
|
||||||
|
$config->setByReference(true);
|
||||||
|
$config->setPropertyPath($propertyPath);
|
||||||
|
$config->setData(null);
|
||||||
|
$form = new Form($config);
|
||||||
|
|
||||||
|
$this->mapper->mapFormsToData([$form], $car);
|
||||||
|
|
||||||
|
self::assertSame($initialEngine, $car->engine);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMapFormsToDataIgnoresUnsynchronized()
|
||||||
|
{
|
||||||
|
$initialEngine = new \stdClass();
|
||||||
|
$car = new \stdClass();
|
||||||
|
$car->engine = $initialEngine;
|
||||||
|
$engine = new \stdClass();
|
||||||
|
$propertyPath = new PropertyPath('engine');
|
||||||
|
|
||||||
|
$config = new FormConfigBuilder('name', \stdClass::class, $this->dispatcher);
|
||||||
|
$config->setByReference(true);
|
||||||
|
$config->setPropertyPath($propertyPath);
|
||||||
|
$config->setData($engine);
|
||||||
|
$form = new NotSynchronizedForm($config);
|
||||||
|
|
||||||
|
$this->mapper->mapFormsToData([$form], $car);
|
||||||
|
|
||||||
|
self::assertSame($initialEngine, $car->engine);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMapFormsToDataIgnoresDisabled()
|
||||||
|
{
|
||||||
|
$initialEngine = new \stdClass();
|
||||||
|
$car = new \stdClass();
|
||||||
|
$car->engine = $initialEngine;
|
||||||
|
$engine = new \stdClass();
|
||||||
|
$propertyPath = new PropertyPath('engine');
|
||||||
|
|
||||||
|
$config = new FormConfigBuilder('name', \stdClass::class, $this->dispatcher);
|
||||||
|
$config->setByReference(true);
|
||||||
|
$config->setPropertyPath($propertyPath);
|
||||||
|
$config->setData($engine);
|
||||||
|
$config->setDisabled(true);
|
||||||
|
$form = new SubmittedForm($config);
|
||||||
|
|
||||||
|
$this->mapper->mapFormsToData([$form], $car);
|
||||||
|
|
||||||
|
self::assertSame($initialEngine, $car->engine);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @requires PHP 7.4
|
||||||
|
*/
|
||||||
|
public function testMapFormsToUninitializedProperties()
|
||||||
|
{
|
||||||
|
$car = new TypehintedPropertiesCar();
|
||||||
|
$config = new FormConfigBuilder('engine', null, $this->dispatcher);
|
||||||
|
$config->setData('BMW');
|
||||||
|
$form = new SubmittedForm($config);
|
||||||
|
|
||||||
|
$this->mapper->mapFormsToData([$form], $car);
|
||||||
|
|
||||||
|
self::assertSame('BMW', $car->engine);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider provideDate
|
||||||
|
*/
|
||||||
|
public function testMapFormsToDataDoesNotChangeEqualDateTimeInstance($date)
|
||||||
|
{
|
||||||
|
$article = [];
|
||||||
|
$publishedAt = $date;
|
||||||
|
$publishedAtValue = clone $publishedAt;
|
||||||
|
$article['publishedAt'] = $publishedAtValue;
|
||||||
|
$propertyPath = new PropertyPath('[publishedAt]');
|
||||||
|
|
||||||
|
$config = new FormConfigBuilder('publishedAt', \get_class($publishedAt), $this->dispatcher);
|
||||||
|
$config->setByReference(false);
|
||||||
|
$config->setPropertyPath($propertyPath);
|
||||||
|
$config->setData($publishedAt);
|
||||||
|
$form = new SubmittedForm($config);
|
||||||
|
|
||||||
|
$this->mapper->mapFormsToData([$form], $article);
|
||||||
|
|
||||||
|
self::assertSame($publishedAtValue, $article['publishedAt']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function provideDate(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[new \DateTime()],
|
||||||
|
[new \DateTimeImmutable()],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMapDataToFormsUsingGetCallbackOption()
|
||||||
|
{
|
||||||
|
$initialName = 'John Doe';
|
||||||
|
$person = new DummyPerson($initialName);
|
||||||
|
|
||||||
|
$config = new FormConfigBuilder('name', null, $this->dispatcher, [
|
||||||
|
'getter' => static function (DummyPerson $person) {
|
||||||
|
return $person->myName();
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
$form = new Form($config);
|
||||||
|
|
||||||
|
$this->mapper->mapDataToForms($person, [$form]);
|
||||||
|
|
||||||
|
self::assertSame($initialName, $form->getData());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMapFormsToDataUsingSetCallbackOption()
|
||||||
|
{
|
||||||
|
$person = new DummyPerson('John Doe');
|
||||||
|
|
||||||
|
$config = new FormConfigBuilder('name', null, $this->dispatcher, [
|
||||||
|
'setter' => static function (DummyPerson $person, $name) {
|
||||||
|
$person->rename($name);
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
$config->setData('Jane Doe');
|
||||||
|
$form = new SubmittedForm($config);
|
||||||
|
|
||||||
|
$this->mapper->mapFormsToData([$form], $person);
|
||||||
|
|
||||||
|
self::assertSame('Jane Doe', $person->myName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SubmittedForm extends Form
|
||||||
|
{
|
||||||
|
public function isSubmitted(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class NotSynchronizedForm extends SubmittedForm
|
||||||
|
{
|
||||||
|
public function isSynchronized(): bool
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DummyPerson
|
||||||
|
{
|
||||||
|
private $name;
|
||||||
|
|
||||||
|
public function __construct(string $name)
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function myName(): string
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rename($name): void
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
}
|
||||||
|
}
|
@ -22,6 +22,9 @@ use Symfony\Component\PropertyAccess\PropertyAccess;
|
|||||||
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
|
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
|
||||||
use Symfony\Component\PropertyAccess\PropertyPath;
|
use Symfony\Component\PropertyAccess\PropertyPath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group legacy
|
||||||
|
*/
|
||||||
class PropertyPathMapperTest extends TestCase
|
class PropertyPathMapperTest extends TestCase
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
@ -363,19 +366,3 @@ class PropertyPathMapperTest extends TestCase
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SubmittedForm extends Form
|
|
||||||
{
|
|
||||||
public function isSubmitted(): bool
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class NotSynchronizedForm extends SubmittedForm
|
|
||||||
{
|
|
||||||
public function isSynchronized(): bool
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -14,7 +14,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\EventListener;
|
|||||||
use Doctrine\Common\Collections\ArrayCollection;
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||||
use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper;
|
use Symfony\Component\Form\Extension\Core\DataMapper\DataMapper;
|
||||||
use Symfony\Component\Form\Extension\Core\EventListener\ResizeFormListener;
|
use Symfony\Component\Form\Extension\Core\EventListener\ResizeFormListener;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||||
use Symfony\Component\Form\FormBuilder;
|
use Symfony\Component\Form\FormBuilder;
|
||||||
@ -31,7 +31,7 @@ class ResizeFormListenerTest extends TestCase
|
|||||||
$this->factory = (new FormFactoryBuilder())->getFormFactory();
|
$this->factory = (new FormFactoryBuilder())->getFormFactory();
|
||||||
$this->form = $this->getBuilder()
|
$this->form = $this->getBuilder()
|
||||||
->setCompound(true)
|
->setCompound(true)
|
||||||
->setDataMapper(new PropertyPathMapper())
|
->setDataMapper(new DataMapper())
|
||||||
->getForm();
|
->getForm();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,12 +268,12 @@ class ResizeFormListenerTest extends TestCase
|
|||||||
$this->form->setData(['0' => ['name' => 'John'], '1' => ['name' => 'Jane']]);
|
$this->form->setData(['0' => ['name' => 'John'], '1' => ['name' => 'Jane']]);
|
||||||
$form1 = $this->getBuilder('0')
|
$form1 = $this->getBuilder('0')
|
||||||
->setCompound(true)
|
->setCompound(true)
|
||||||
->setDataMapper(new PropertyPathMapper())
|
->setDataMapper(new DataMapper())
|
||||||
->getForm();
|
->getForm();
|
||||||
$form1->add($this->getForm('name'));
|
$form1->add($this->getForm('name'));
|
||||||
$form2 = $this->getBuilder('1')
|
$form2 = $this->getBuilder('1')
|
||||||
->setCompound(true)
|
->setCompound(true)
|
||||||
->setDataMapper(new PropertyPathMapper())
|
->setDataMapper(new DataMapper())
|
||||||
->getForm();
|
->getForm();
|
||||||
$form2->add($this->getForm('name'));
|
$form2->add($this->getForm('name'));
|
||||||
$this->form->add($form1);
|
$this->form->add($form1);
|
||||||
|
@ -13,7 +13,7 @@ namespace Symfony\Component\Form\Tests\Extension\Csrf\EventListener;
|
|||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||||
use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper;
|
use Symfony\Component\Form\Extension\Core\DataMapper\DataMapper;
|
||||||
use Symfony\Component\Form\Extension\Csrf\EventListener\CsrfValidationListener;
|
use Symfony\Component\Form\Extension\Csrf\EventListener\CsrfValidationListener;
|
||||||
use Symfony\Component\Form\FormBuilder;
|
use Symfony\Component\Form\FormBuilder;
|
||||||
use Symfony\Component\Form\FormEvent;
|
use Symfony\Component\Form\FormEvent;
|
||||||
@ -33,7 +33,7 @@ class CsrfValidationListenerTest extends TestCase
|
|||||||
$this->factory = (new FormFactoryBuilder())->getFormFactory();
|
$this->factory = (new FormFactoryBuilder())->getFormFactory();
|
||||||
$this->tokenManager = new CsrfTokenManager();
|
$this->tokenManager = new CsrfTokenManager();
|
||||||
$this->form = $this->getBuilder()
|
$this->form = $this->getBuilder()
|
||||||
->setDataMapper(new PropertyPathMapper())
|
->setDataMapper(new DataMapper())
|
||||||
->getForm();
|
->getForm();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ use PHPUnit\Framework\MockObject\MockObject;
|
|||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||||
use Symfony\Component\Form\Extension\Core\CoreExtension;
|
use Symfony\Component\Form\Extension\Core\CoreExtension;
|
||||||
use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper;
|
use Symfony\Component\Form\Extension\Core\DataMapper\DataMapper;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
|
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\FormType;
|
use Symfony\Component\Form\Extension\Core\Type\FormType;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||||
@ -81,7 +81,7 @@ class FormDataCollectorTest extends TestCase
|
|||||||
$this->dataCollector = new FormDataCollector($this->dataExtractor);
|
$this->dataCollector = new FormDataCollector($this->dataExtractor);
|
||||||
$this->dispatcher = new EventDispatcher();
|
$this->dispatcher = new EventDispatcher();
|
||||||
$this->factory = new FormFactory(new FormRegistry([new CoreExtension()], new ResolvedFormTypeFactory()));
|
$this->factory = new FormFactory(new FormRegistry([new CoreExtension()], new ResolvedFormTypeFactory()));
|
||||||
$this->dataMapper = new PropertyPathMapper();
|
$this->dataMapper = new DataMapper();
|
||||||
$this->form = $this->createForm('name');
|
$this->form = $this->createForm('name');
|
||||||
$this->childForm = $this->createForm('child');
|
$this->childForm = $this->createForm('child');
|
||||||
$this->view = new FormView();
|
$this->view = new FormView();
|
||||||
|
@ -15,7 +15,7 @@ use Symfony\Component\EventDispatcher\EventDispatcher;
|
|||||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||||
use Symfony\Component\Form\CallbackTransformer;
|
use Symfony\Component\Form\CallbackTransformer;
|
||||||
use Symfony\Component\Form\Exception\TransformationFailedException;
|
use Symfony\Component\Form\Exception\TransformationFailedException;
|
||||||
use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper;
|
use Symfony\Component\Form\Extension\Core\DataMapper\DataMapper;
|
||||||
use Symfony\Component\Form\Extension\Validator\Constraints\Form;
|
use Symfony\Component\Form\Extension\Validator\Constraints\Form;
|
||||||
use Symfony\Component\Form\Extension\Validator\Constraints\FormValidator;
|
use Symfony\Component\Form\Extension\Validator\Constraints\FormValidator;
|
||||||
use Symfony\Component\Form\Extension\Validator\ValidatorExtension;
|
use Symfony\Component\Form\Extension\Validator\ValidatorExtension;
|
||||||
@ -107,7 +107,7 @@ class FormValidatorTest extends ConstraintValidatorTestCase
|
|||||||
|
|
||||||
$parent = $this->getBuilder('parent')
|
$parent = $this->getBuilder('parent')
|
||||||
->setCompound(true)
|
->setCompound(true)
|
||||||
->setDataMapper(new PropertyPathMapper())
|
->setDataMapper(new DataMapper())
|
||||||
->getForm();
|
->getForm();
|
||||||
$options = [
|
$options = [
|
||||||
'validation_groups' => ['group1', 'group2'],
|
'validation_groups' => ['group1', 'group2'],
|
||||||
@ -130,7 +130,7 @@ class FormValidatorTest extends ConstraintValidatorTestCase
|
|||||||
|
|
||||||
$parent = $this->getBuilder('parent', null)
|
$parent = $this->getBuilder('parent', null)
|
||||||
->setCompound(true)
|
->setCompound(true)
|
||||||
->setDataMapper(new PropertyPathMapper())
|
->setDataMapper(new DataMapper())
|
||||||
->getForm();
|
->getForm();
|
||||||
$options = ['validation_groups' => ['group1', 'group2']];
|
$options = ['validation_groups' => ['group1', 'group2']];
|
||||||
$form = $this->getBuilder('name', '\stdClass', $options)->getForm();
|
$form = $this->getBuilder('name', '\stdClass', $options)->getForm();
|
||||||
@ -169,7 +169,7 @@ class FormValidatorTest extends ConstraintValidatorTestCase
|
|||||||
|
|
||||||
$parent = $this->getBuilder('parent', null)
|
$parent = $this->getBuilder('parent', null)
|
||||||
->setCompound(true)
|
->setCompound(true)
|
||||||
->setDataMapper(new PropertyPathMapper())
|
->setDataMapper(new DataMapper())
|
||||||
->getForm();
|
->getForm();
|
||||||
$options = [
|
$options = [
|
||||||
'validation_groups' => ['group1', 'group2'],
|
'validation_groups' => ['group1', 'group2'],
|
||||||
@ -196,7 +196,7 @@ class FormValidatorTest extends ConstraintValidatorTestCase
|
|||||||
])
|
])
|
||||||
->setData($object)
|
->setData($object)
|
||||||
->setCompound(true)
|
->setCompound(true)
|
||||||
->setDataMapper(new PropertyPathMapper())
|
->setDataMapper(new DataMapper())
|
||||||
->getForm();
|
->getForm();
|
||||||
|
|
||||||
$form->setData($object);
|
$form->setData($object);
|
||||||
@ -243,7 +243,7 @@ class FormValidatorTest extends ConstraintValidatorTestCase
|
|||||||
];
|
];
|
||||||
$form = $this->getBuilder('name', null, $formOptions)
|
$form = $this->getBuilder('name', null, $formOptions)
|
||||||
->setCompound(true)
|
->setCompound(true)
|
||||||
->setDataMapper(new PropertyPathMapper())
|
->setDataMapper(new DataMapper())
|
||||||
->getForm();
|
->getForm();
|
||||||
$childOptions = ['constraints' => [new NotBlank()]];
|
$childOptions = ['constraints' => [new NotBlank()]];
|
||||||
$child = $this->getCompoundForm(new \stdClass(), $childOptions);
|
$child = $this->getCompoundForm(new \stdClass(), $childOptions);
|
||||||
@ -470,7 +470,7 @@ class FormValidatorTest extends ConstraintValidatorTestCase
|
|||||||
|
|
||||||
$parent = $this->getBuilder('parent')
|
$parent = $this->getBuilder('parent')
|
||||||
->setCompound(true)
|
->setCompound(true)
|
||||||
->setDataMapper(new PropertyPathMapper())
|
->setDataMapper(new DataMapper())
|
||||||
->getForm();
|
->getForm();
|
||||||
$form = $this->getForm('name', '\stdClass', [
|
$form = $this->getForm('name', '\stdClass', [
|
||||||
'validation_groups' => 'form_group',
|
'validation_groups' => 'form_group',
|
||||||
@ -497,7 +497,7 @@ class FormValidatorTest extends ConstraintValidatorTestCase
|
|||||||
|
|
||||||
$parent = $this->getBuilder('parent')
|
$parent = $this->getBuilder('parent')
|
||||||
->setCompound(true)
|
->setCompound(true)
|
||||||
->setDataMapper(new PropertyPathMapper())
|
->setDataMapper(new DataMapper())
|
||||||
->getForm();
|
->getForm();
|
||||||
$form = $this->getCompoundForm($object, [
|
$form = $this->getCompoundForm($object, [
|
||||||
'validation_groups' => 'form_group',
|
'validation_groups' => 'form_group',
|
||||||
@ -525,7 +525,7 @@ class FormValidatorTest extends ConstraintValidatorTestCase
|
|||||||
$parentOptions = ['validation_groups' => 'group'];
|
$parentOptions = ['validation_groups' => 'group'];
|
||||||
$parent = $this->getBuilder('parent', null, $parentOptions)
|
$parent = $this->getBuilder('parent', null, $parentOptions)
|
||||||
->setCompound(true)
|
->setCompound(true)
|
||||||
->setDataMapper(new PropertyPathMapper())
|
->setDataMapper(new DataMapper())
|
||||||
->getForm();
|
->getForm();
|
||||||
$formOptions = ['constraints' => [new Valid()]];
|
$formOptions = ['constraints' => [new Valid()]];
|
||||||
$form = $this->getCompoundForm($object, $formOptions);
|
$form = $this->getCompoundForm($object, $formOptions);
|
||||||
@ -546,7 +546,7 @@ class FormValidatorTest extends ConstraintValidatorTestCase
|
|||||||
$parentOptions = ['validation_groups' => [$this, 'getValidationGroups']];
|
$parentOptions = ['validation_groups' => [$this, 'getValidationGroups']];
|
||||||
$parent = $this->getBuilder('parent', null, $parentOptions)
|
$parent = $this->getBuilder('parent', null, $parentOptions)
|
||||||
->setCompound(true)
|
->setCompound(true)
|
||||||
->setDataMapper(new PropertyPathMapper())
|
->setDataMapper(new DataMapper())
|
||||||
->getForm();
|
->getForm();
|
||||||
$formOptions = ['constraints' => [new Valid()]];
|
$formOptions = ['constraints' => [new Valid()]];
|
||||||
$form = $this->getCompoundForm($object, $formOptions);
|
$form = $this->getCompoundForm($object, $formOptions);
|
||||||
@ -571,7 +571,7 @@ class FormValidatorTest extends ConstraintValidatorTestCase
|
|||||||
];
|
];
|
||||||
$parent = $this->getBuilder('parent', null, $parentOptions)
|
$parent = $this->getBuilder('parent', null, $parentOptions)
|
||||||
->setCompound(true)
|
->setCompound(true)
|
||||||
->setDataMapper(new PropertyPathMapper())
|
->setDataMapper(new DataMapper())
|
||||||
->getForm();
|
->getForm();
|
||||||
$formOptions = ['constraints' => [new Valid()]];
|
$formOptions = ['constraints' => [new Valid()]];
|
||||||
$form = $this->getCompoundForm($object, $formOptions);
|
$form = $this->getCompoundForm($object, $formOptions);
|
||||||
@ -618,7 +618,7 @@ class FormValidatorTest extends ConstraintValidatorTestCase
|
|||||||
{
|
{
|
||||||
$form = $this->getBuilder('parent', null, ['extra_fields_message' => 'Extra!|Extras!'])
|
$form = $this->getBuilder('parent', null, ['extra_fields_message' => 'Extra!|Extras!'])
|
||||||
->setCompound(true)
|
->setCompound(true)
|
||||||
->setDataMapper(new PropertyPathMapper())
|
->setDataMapper(new DataMapper())
|
||||||
->add($this->getBuilder('child'))
|
->add($this->getBuilder('child'))
|
||||||
->getForm();
|
->getForm();
|
||||||
|
|
||||||
@ -643,7 +643,7 @@ class FormValidatorTest extends ConstraintValidatorTestCase
|
|||||||
{
|
{
|
||||||
$form = $this->getBuilder('parent', null, ['extra_fields_message' => 'Extra!|Extras!!'])
|
$form = $this->getBuilder('parent', null, ['extra_fields_message' => 'Extra!|Extras!!'])
|
||||||
->setCompound(true)
|
->setCompound(true)
|
||||||
->setDataMapper(new PropertyPathMapper())
|
->setDataMapper(new DataMapper())
|
||||||
->add($this->getBuilder('child'))
|
->add($this->getBuilder('child'))
|
||||||
->getForm();
|
->getForm();
|
||||||
|
|
||||||
@ -669,7 +669,7 @@ class FormValidatorTest extends ConstraintValidatorTestCase
|
|||||||
$form = $this
|
$form = $this
|
||||||
->getBuilder('parent', null, ['allow_extra_fields' => true])
|
->getBuilder('parent', null, ['allow_extra_fields' => true])
|
||||||
->setCompound(true)
|
->setCompound(true)
|
||||||
->setDataMapper(new PropertyPathMapper())
|
->setDataMapper(new DataMapper())
|
||||||
->add($this->getBuilder('child'))
|
->add($this->getBuilder('child'))
|
||||||
->getForm();
|
->getForm();
|
||||||
|
|
||||||
@ -698,7 +698,7 @@ class FormValidatorTest extends ConstraintValidatorTestCase
|
|||||||
$form = $this
|
$form = $this
|
||||||
->getBuilder('form', null, ['constraints' => [new NotBlank(['groups' => ['foo']])]])
|
->getBuilder('form', null, ['constraints' => [new NotBlank(['groups' => ['foo']])]])
|
||||||
->setCompound(true)
|
->setCompound(true)
|
||||||
->setDataMapper(new PropertyPathMapper())
|
->setDataMapper(new DataMapper())
|
||||||
->getForm();
|
->getForm();
|
||||||
$form->submit([
|
$form->submit([
|
||||||
'extra_data' => 'foo',
|
'extra_data' => 'foo',
|
||||||
@ -739,7 +739,7 @@ class FormValidatorTest extends ConstraintValidatorTestCase
|
|||||||
return $this->getBuilder('name', \is_object($data) ? \get_class($data) : null, $options)
|
return $this->getBuilder('name', \is_object($data) ? \get_class($data) : null, $options)
|
||||||
->setData($data)
|
->setData($data)
|
||||||
->setCompound(true)
|
->setCompound(true)
|
||||||
->setDataMapper(new PropertyPathMapper())
|
->setDataMapper(new DataMapper())
|
||||||
->getForm();
|
->getForm();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ namespace Symfony\Component\Form\Tests\Extension\Validator\EventListener;
|
|||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||||
use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper;
|
use Symfony\Component\Form\Extension\Core\DataMapper\DataMapper;
|
||||||
use Symfony\Component\Form\Extension\Validator\Constraints\Form as FormConstraint;
|
use Symfony\Component\Form\Extension\Validator\Constraints\Form as FormConstraint;
|
||||||
use Symfony\Component\Form\Extension\Validator\EventListener\ValidationListener;
|
use Symfony\Component\Form\Extension\Validator\EventListener\ValidationListener;
|
||||||
use Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationMapper;
|
use Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationMapper;
|
||||||
@ -79,7 +79,7 @@ class ValidationListenerTest extends TestCase
|
|||||||
$config->setCompound($compound);
|
$config->setCompound($compound);
|
||||||
|
|
||||||
if ($compound) {
|
if ($compound) {
|
||||||
$config->setDataMapper(new PropertyPathMapper());
|
$config->setDataMapper(new DataMapper());
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Form($config);
|
return new Form($config);
|
||||||
|
@ -16,7 +16,7 @@ use Symfony\Component\EventDispatcher\EventDispatcher;
|
|||||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||||
use Symfony\Component\Form\CallbackTransformer;
|
use Symfony\Component\Form\CallbackTransformer;
|
||||||
use Symfony\Component\Form\Exception\TransformationFailedException;
|
use Symfony\Component\Form\Exception\TransformationFailedException;
|
||||||
use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper;
|
use Symfony\Component\Form\Extension\Core\DataMapper\DataMapper;
|
||||||
use Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationMapper;
|
use Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationMapper;
|
||||||
use Symfony\Component\Form\Form;
|
use Symfony\Component\Form\Form;
|
||||||
use Symfony\Component\Form\FormConfigBuilder;
|
use Symfony\Component\Form\FormConfigBuilder;
|
||||||
@ -82,7 +82,7 @@ class ViolationMapperTest extends TestCase
|
|||||||
$config->setInheritData($inheritData);
|
$config->setInheritData($inheritData);
|
||||||
$config->setPropertyPath($propertyPath);
|
$config->setPropertyPath($propertyPath);
|
||||||
$config->setCompound(true);
|
$config->setCompound(true);
|
||||||
$config->setDataMapper(new PropertyPathMapper());
|
$config->setDataMapper(new DataMapper());
|
||||||
|
|
||||||
if (!$synchronized) {
|
if (!$synchronized) {
|
||||||
$config->addViewTransformer(new CallbackTransformer(
|
$config->addViewTransformer(new CallbackTransformer(
|
||||||
@ -1643,7 +1643,7 @@ class ViolationMapperTest extends TestCase
|
|||||||
$config->setInheritData(false);
|
$config->setInheritData(false);
|
||||||
$config->setPropertyPath('name');
|
$config->setPropertyPath('name');
|
||||||
$config->setCompound(true);
|
$config->setCompound(true);
|
||||||
$config->setDataMapper(new PropertyPathMapper());
|
$config->setDataMapper(new DataMapper());
|
||||||
|
|
||||||
$child = new Form($config);
|
$child = new Form($config);
|
||||||
$parent->add($child);
|
$parent->add($child);
|
||||||
@ -1681,7 +1681,7 @@ class ViolationMapperTest extends TestCase
|
|||||||
$config->setInheritData(false);
|
$config->setInheritData(false);
|
||||||
$config->setPropertyPath('custom');
|
$config->setPropertyPath('custom');
|
||||||
$config->setCompound(true);
|
$config->setCompound(true);
|
||||||
$config->setDataMapper(new PropertyPathMapper());
|
$config->setDataMapper(new DataMapper());
|
||||||
|
|
||||||
$child = new Form($config);
|
$child = new Form($config);
|
||||||
$parent->add($child);
|
$parent->add($child);
|
||||||
@ -1719,7 +1719,7 @@ class ViolationMapperTest extends TestCase
|
|||||||
$config->setInheritData(false);
|
$config->setInheritData(false);
|
||||||
$config->setPropertyPath('custom-id');
|
$config->setPropertyPath('custom-id');
|
||||||
$config->setCompound(true);
|
$config->setCompound(true);
|
||||||
$config->setDataMapper(new PropertyPathMapper());
|
$config->setDataMapper(new DataMapper());
|
||||||
|
|
||||||
$child = new Form($config);
|
$child = new Form($config);
|
||||||
$parent->add($child);
|
$parent->add($child);
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
"by_reference",
|
"by_reference",
|
||||||
"data",
|
"data",
|
||||||
"disabled",
|
"disabled",
|
||||||
|
"getter",
|
||||||
"help",
|
"help",
|
||||||
"help_attr",
|
"help_attr",
|
||||||
"help_html",
|
"help_html",
|
||||||
@ -57,6 +58,7 @@
|
|||||||
"property_path",
|
"property_path",
|
||||||
"required",
|
"required",
|
||||||
"row_attr",
|
"row_attr",
|
||||||
|
"setter",
|
||||||
"translation_domain",
|
"translation_domain",
|
||||||
"upload_max_size_message"
|
"upload_max_size_message"
|
||||||
]
|
]
|
||||||
|
@ -17,7 +17,8 @@ Symfony\Component\Form\Extension\Core\Type\ChoiceType (Block prefix: "choice")
|
|||||||
group_by by_reference
|
group_by by_reference
|
||||||
multiple data
|
multiple data
|
||||||
placeholder disabled
|
placeholder disabled
|
||||||
preferred_choices help
|
preferred_choices getter
|
||||||
|
help
|
||||||
help_attr
|
help_attr
|
||||||
help_html
|
help_html
|
||||||
help_translation_parameters
|
help_translation_parameters
|
||||||
@ -35,6 +36,7 @@ Symfony\Component\Form\Extension\Core\Type\ChoiceType (Block prefix: "choice")
|
|||||||
property_path
|
property_path
|
||||||
required
|
required
|
||||||
row_attr
|
row_attr
|
||||||
|
setter
|
||||||
translation_domain
|
translation_domain
|
||||||
upload_max_size_message
|
upload_max_size_message
|
||||||
--------------------------- -------------------- ------------------------------ -----------------------
|
--------------------------- -------------------- ------------------------------ -----------------------
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
"disabled",
|
"disabled",
|
||||||
"empty_data",
|
"empty_data",
|
||||||
"error_bubbling",
|
"error_bubbling",
|
||||||
|
"getter",
|
||||||
"help",
|
"help",
|
||||||
"help_attr",
|
"help_attr",
|
||||||
"help_html",
|
"help_html",
|
||||||
@ -36,6 +37,7 @@
|
|||||||
"property_path",
|
"property_path",
|
||||||
"required",
|
"required",
|
||||||
"row_attr",
|
"row_attr",
|
||||||
|
"setter",
|
||||||
"translation_domain",
|
"translation_domain",
|
||||||
"trim",
|
"trim",
|
||||||
"upload_max_size_message"
|
"upload_max_size_message"
|
||||||
|
@ -19,6 +19,7 @@ Symfony\Component\Form\Extension\Core\Type\FormType (Block prefix: "form")
|
|||||||
disabled
|
disabled
|
||||||
empty_data
|
empty_data
|
||||||
error_bubbling
|
error_bubbling
|
||||||
|
getter
|
||||||
help
|
help
|
||||||
help_attr
|
help_attr
|
||||||
help_html
|
help_html
|
||||||
@ -38,6 +39,7 @@ Symfony\Component\Form\Extension\Core\Type\FormType (Block prefix: "form")
|
|||||||
property_path
|
property_path
|
||||||
required
|
required
|
||||||
row_attr
|
row_attr
|
||||||
|
setter
|
||||||
translation_domain
|
translation_domain
|
||||||
trim
|
trim
|
||||||
upload_max_size_message
|
upload_max_size_message
|
||||||
|
Reference in New Issue
Block a user