Added new option "input" to NumberType
This commit is contained in:
parent
fb2b37a8f3
commit
3f25734647
@ -1,6 +1,11 @@
|
|||||||
CHANGELOG
|
CHANGELOG
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
4.3.0
|
||||||
|
-----
|
||||||
|
|
||||||
|
* changed guessing of DECIMAL to set the `input` option of `NumberType` to string
|
||||||
|
|
||||||
4.2.0
|
4.2.0
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
@ -1,91 +0,0 @@
|
|||||||
<?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\Bridge\Doctrine\Form\DataTransformer;
|
|
||||||
|
|
||||||
use Symfony\Component\Form\DataTransformerInterface;
|
|
||||||
use Symfony\Component\Form\Exception\TransformationFailedException;
|
|
||||||
|
|
||||||
class NumberToStringTransformer implements DataTransformerInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var bool
|
|
||||||
*/
|
|
||||||
private $forceFullScale;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var int|null
|
|
||||||
*/
|
|
||||||
private $scale;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param bool $forceFullScale
|
|
||||||
* @param int|null $scale
|
|
||||||
*/
|
|
||||||
public function __construct($forceFullScale = false, $scale = null)
|
|
||||||
{
|
|
||||||
$this->forceFullScale = $forceFullScale;
|
|
||||||
$this->scale = $scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param mixed $value
|
|
||||||
*
|
|
||||||
* @return string|null
|
|
||||||
*/
|
|
||||||
public function transform($value)
|
|
||||||
{
|
|
||||||
if (null === $value) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_string($value)) {
|
|
||||||
throw new TransformationFailedException('Expected a string.');
|
|
||||||
}
|
|
||||||
|
|
||||||
return $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param mixed $value
|
|
||||||
*
|
|
||||||
* @return string|null
|
|
||||||
*/
|
|
||||||
public function reverseTransform($value)
|
|
||||||
{
|
|
||||||
if (null === $value) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_string($value)) {
|
|
||||||
return $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
$valueIsInt = is_int($value);
|
|
||||||
if (!$valueIsInt && !is_float($value)) {
|
|
||||||
throw new TransformationFailedException('Expected an int or a float.');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->forceFullScale && is_int($this->scale)) {
|
|
||||||
if ($valueIsInt) {
|
|
||||||
$value = floatval($value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return number_format($value, $this->scale, '.', '');
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
return (string) $value;
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
throw new TransformationFailedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -17,7 +17,6 @@ use Doctrine\Common\Persistence\Proxy;
|
|||||||
use Doctrine\DBAL\Types\Type;
|
use Doctrine\DBAL\Types\Type;
|
||||||
use Doctrine\ORM\Mapping\ClassMetadataInfo;
|
use Doctrine\ORM\Mapping\ClassMetadataInfo;
|
||||||
use Doctrine\ORM\Mapping\MappingException as LegacyMappingException;
|
use Doctrine\ORM\Mapping\MappingException as LegacyMappingException;
|
||||||
use Symfony\Bridge\Doctrine\Form\Type\DecimalType;
|
|
||||||
use Symfony\Component\Form\FormTypeGuesserInterface;
|
use Symfony\Component\Form\FormTypeGuesserInterface;
|
||||||
use Symfony\Component\Form\Guess\Guess;
|
use Symfony\Component\Form\Guess\Guess;
|
||||||
use Symfony\Component\Form\Guess\TypeGuess;
|
use Symfony\Component\Form\Guess\TypeGuess;
|
||||||
@ -76,7 +75,7 @@ class DoctrineOrmTypeGuesser implements FormTypeGuesserInterface
|
|||||||
case 'time_immutable':
|
case 'time_immutable':
|
||||||
return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TimeType', ['input' => 'datetime_immutable'], Guess::HIGH_CONFIDENCE);
|
return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TimeType', ['input' => 'datetime_immutable'], Guess::HIGH_CONFIDENCE);
|
||||||
case Type::DECIMAL:
|
case Type::DECIMAL:
|
||||||
return new TypeGuess(DecimalType::class, array(), Guess::HIGH_CONFIDENCE);
|
return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\NumberType', ['input' => 'string'], Guess::MEDIUM_CONFIDENCE);
|
||||||
case Type::FLOAT:
|
case Type::FLOAT:
|
||||||
return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\NumberType', [], Guess::MEDIUM_CONFIDENCE);
|
return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\NumberType', [], Guess::MEDIUM_CONFIDENCE);
|
||||||
case Type::INTEGER:
|
case Type::INTEGER:
|
||||||
|
@ -1,50 +0,0 @@
|
|||||||
<?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\Bridge\Doctrine\Form\Type;
|
|
||||||
|
|
||||||
use Symfony\Bridge\Doctrine\Form\DataTransformer\NumberToStringTransformer;
|
|
||||||
use Symfony\Component\Form\AbstractType;
|
|
||||||
use Symfony\Component\Form\Extension\Core\Type\NumberType;
|
|
||||||
use Symfony\Component\Form\FormBuilderInterface;
|
|
||||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
|
||||||
|
|
||||||
class DecimalType extends AbstractType
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
|
||||||
{
|
|
||||||
$builder->addModelTransformer(new NumberToStringTransformer($options['force_full_scale'], $options['scale']));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function configureOptions(OptionsResolver $resolver)
|
|
||||||
{
|
|
||||||
$resolver->setDefaults(array(
|
|
||||||
'force_full_scale' => false
|
|
||||||
));
|
|
||||||
$resolver->setAllowedTypes('force_full_scale', array(
|
|
||||||
'boolean'
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function getParent()
|
|
||||||
{
|
|
||||||
return NumberType::class;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
<?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\Bridge\Doctrine\Tests\Fixtures;
|
|
||||||
|
|
||||||
use Doctrine\ORM\Mapping\Entity;
|
|
||||||
use Doctrine\ORM\Mapping\Id;
|
|
||||||
use Doctrine\ORM\Mapping\Column;
|
|
||||||
|
|
||||||
/** @Entity */
|
|
||||||
class Price
|
|
||||||
{
|
|
||||||
/** @Id @Column(type="integer") */
|
|
||||||
public $id;
|
|
||||||
|
|
||||||
/** @Column(type="decimal", scale=2) */
|
|
||||||
public $doesNotPreserveFullScaleValue;
|
|
||||||
|
|
||||||
/** @Column(type="string") */
|
|
||||||
public $preserveFullScaleValueSimulation;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $id
|
|
||||||
* @param float $value
|
|
||||||
*/
|
|
||||||
public function __construct(int $id, float $value)
|
|
||||||
{
|
|
||||||
$this->id = $id;
|
|
||||||
$this->doesNotPreserveFullScaleValue = $value;
|
|
||||||
$this->preserveFullScaleValueSimulation = number_format($value, 2, '.', '');
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,177 +0,0 @@
|
|||||||
<?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\Bridge\Doctrine\Tests\Form\Type;
|
|
||||||
|
|
||||||
use Doctrine\ORM\EntityManager;
|
|
||||||
use Doctrine\ORM\Tools\SchemaTool;
|
|
||||||
use Symfony\Bridge\Doctrine\Form\Type\DecimalType;
|
|
||||||
use Symfony\Bridge\Doctrine\Test\DoctrineTestHelper;
|
|
||||||
use Symfony\Bridge\Doctrine\Tests\Fixtures\Price;
|
|
||||||
use Symfony\Component\Form\Extension\Core\Type\FormType;
|
|
||||||
use Symfony\Component\Form\Tests\Extension\Core\Type\BaseTypeTest;
|
|
||||||
|
|
||||||
class DecimalTypeTest extends BaseTypeTest
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
const TESTED_TYPE = DecimalType::class;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var EntityManager
|
|
||||||
*/
|
|
||||||
private $em;
|
|
||||||
|
|
||||||
protected function setUp()
|
|
||||||
{
|
|
||||||
$this->em = DoctrineTestHelper::createTestEntityManager();
|
|
||||||
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
$schemaTool = new SchemaTool($this->em);
|
|
||||||
$classes = array(
|
|
||||||
$this->em->getClassMetadata(Price::class)
|
|
||||||
);
|
|
||||||
|
|
||||||
try {
|
|
||||||
$schemaTool->dropSchema($classes);
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
$schemaTool->createSchema($classes);
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function tearDown()
|
|
||||||
{
|
|
||||||
parent::tearDown();
|
|
||||||
|
|
||||||
$this->em = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// On some platforms, fetched decimal values are rounded (the full scale is not preserved)
|
|
||||||
// eg : on SQLite, inserted float value 4.50 will be fetched as string value "4.5"
|
|
||||||
public function testSubmitWithSameStringValueOnAPlatformThatDoesNotPreserveFullScaleValueWithoutForceFullScale()
|
|
||||||
{
|
|
||||||
$fullScalePrice = new Price(1, 1.23);
|
|
||||||
$nonFullScalePrice = new Price(2, 4.50);
|
|
||||||
$this->em->persist($fullScalePrice);
|
|
||||||
$this->em->persist($nonFullScalePrice);
|
|
||||||
$this->em->flush();
|
|
||||||
|
|
||||||
$this->em->refresh($fullScalePrice);
|
|
||||||
$this->em->refresh($nonFullScalePrice);
|
|
||||||
|
|
||||||
$this->assertInternalType('string', $fullScalePrice->doesNotPreserveFullScaleValue);
|
|
||||||
$fullScalePriceStringValue = $fullScalePrice->doesNotPreserveFullScaleValue;
|
|
||||||
|
|
||||||
$formBuilder = $this->factory->createBuilder(FormType::class, $fullScalePrice, array(
|
|
||||||
'data_class' => Price::class
|
|
||||||
));
|
|
||||||
$formBuilder->add('doesNotPreserveFullScaleValue', static::TESTED_TYPE, array(
|
|
||||||
'force_full_scale' => false
|
|
||||||
));
|
|
||||||
|
|
||||||
$form = $formBuilder->getForm();
|
|
||||||
$form->submit(array(
|
|
||||||
'doesNotPreserveFullScaleValue' => $fullScalePriceStringValue
|
|
||||||
));
|
|
||||||
|
|
||||||
$this->assertSame($fullScalePriceStringValue, $fullScalePrice->doesNotPreserveFullScaleValue);
|
|
||||||
|
|
||||||
$this->assertInternalType('string', $nonFullScalePrice->doesNotPreserveFullScaleValue);
|
|
||||||
$nonFullScalePriceStringValue = $nonFullScalePrice->doesNotPreserveFullScaleValue;
|
|
||||||
|
|
||||||
$formBuilder = $this->factory->createBuilder(FormType::class, $nonFullScalePrice, array(
|
|
||||||
'data_class' => Price::class
|
|
||||||
));
|
|
||||||
$formBuilder->add('doesNotPreserveFullScaleValue', static::TESTED_TYPE, array(
|
|
||||||
'force_full_scale' => false
|
|
||||||
));
|
|
||||||
|
|
||||||
$form = $formBuilder->getForm();
|
|
||||||
$form->submit(array(
|
|
||||||
'doesNotPreserveFullScaleValue' => $nonFullScalePriceStringValue
|
|
||||||
));
|
|
||||||
|
|
||||||
$this->assertSame($nonFullScalePriceStringValue, $nonFullScalePrice->doesNotPreserveFullScaleValue);
|
|
||||||
|
|
||||||
$unitOfWork = $this->em->getUnitOfWork();
|
|
||||||
$unitOfWork->computeChangeSets();
|
|
||||||
|
|
||||||
$this->assertSame(array(), $unitOfWork->getEntityChangeSet($fullScalePrice));
|
|
||||||
$this->assertSame(array(), $unitOfWork->getEntityChangeSet($nonFullScalePrice));
|
|
||||||
}
|
|
||||||
|
|
||||||
// On some platforms, fetched decimal values are not rounded at all (the full scale is preserved)
|
|
||||||
// eg : on PostgreSQL, inserted float value 4.50 will be fetched as string value "4.50"
|
|
||||||
public function testSubmitWithSameStringValueOnAPlatformThatPreserveFullScaleValueWithForceFullScale()
|
|
||||||
{
|
|
||||||
$fullScalePrice = new Price(1, 1.23);
|
|
||||||
$nonFullScalePrice = new Price(2, 4.50);
|
|
||||||
$this->em->persist($fullScalePrice);
|
|
||||||
$this->em->persist($nonFullScalePrice);
|
|
||||||
$this->em->flush();
|
|
||||||
|
|
||||||
$this->em->refresh($fullScalePrice);
|
|
||||||
$this->em->refresh($nonFullScalePrice);
|
|
||||||
|
|
||||||
$this->assertInternalType('string', $fullScalePrice->preserveFullScaleValueSimulation);
|
|
||||||
$fullScalePriceStringValue = $fullScalePrice->preserveFullScaleValueSimulation;
|
|
||||||
|
|
||||||
$formBuilder = $this->factory->createBuilder(FormType::class, $fullScalePrice, array(
|
|
||||||
'data_class' => Price::class
|
|
||||||
));
|
|
||||||
$formBuilder->add('preserveFullScaleValueSimulation', static::TESTED_TYPE, array(
|
|
||||||
'force_full_scale' => true,
|
|
||||||
'scale' => 2
|
|
||||||
));
|
|
||||||
|
|
||||||
$form = $formBuilder->getForm();
|
|
||||||
$form->submit(array(
|
|
||||||
'preserveFullScaleValueSimulation' => $fullScalePriceStringValue
|
|
||||||
));
|
|
||||||
|
|
||||||
$this->assertSame($fullScalePriceStringValue, $fullScalePrice->preserveFullScaleValueSimulation);
|
|
||||||
|
|
||||||
$this->assertInternalType('string', $nonFullScalePrice->preserveFullScaleValueSimulation);
|
|
||||||
$nonFullScalePriceStringValue = $nonFullScalePrice->preserveFullScaleValueSimulation;
|
|
||||||
|
|
||||||
$formBuilder = $this->factory->createBuilder(FormType::class, $nonFullScalePrice, array(
|
|
||||||
'data_class' => Price::class
|
|
||||||
));
|
|
||||||
$formBuilder->add('preserveFullScaleValueSimulation', static::TESTED_TYPE, array(
|
|
||||||
'force_full_scale' => true,
|
|
||||||
'scale' => 2
|
|
||||||
));
|
|
||||||
|
|
||||||
$form = $formBuilder->getForm();
|
|
||||||
$form->submit(array(
|
|
||||||
'preserveFullScaleValueSimulation' => $nonFullScalePriceStringValue
|
|
||||||
));
|
|
||||||
|
|
||||||
$this->assertSame($nonFullScalePriceStringValue, $nonFullScalePrice->preserveFullScaleValueSimulation);
|
|
||||||
|
|
||||||
$unitOfWork = $this->em->getUnitOfWork();
|
|
||||||
$unitOfWork->computeChangeSets();
|
|
||||||
|
|
||||||
$this->assertSame(array(), $unitOfWork->getEntityChangeSet($fullScalePrice));
|
|
||||||
$this->assertSame(array(), $unitOfWork->getEntityChangeSet($nonFullScalePrice));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testSubmitNull($expected = null, $norm = null, $view = null)
|
|
||||||
{
|
|
||||||
parent::testSubmitNull($expected, $norm, '');
|
|
||||||
}
|
|
||||||
}
|
|
@ -47,6 +47,7 @@ CHANGELOG
|
|||||||
* dispatch `PostSubmitEvent` on `form.post_submit`
|
* dispatch `PostSubmitEvent` on `form.post_submit`
|
||||||
* dispatch `PreSetDataEvent` on `form.pre_set_data`
|
* dispatch `PreSetDataEvent` on `form.pre_set_data`
|
||||||
* dispatch `PostSetDataEvent` on `form.post_set_data`
|
* dispatch `PostSetDataEvent` on `form.post_set_data`
|
||||||
|
* added an `input` option to `NumberType`
|
||||||
|
|
||||||
4.2.0
|
4.2.0
|
||||||
-----
|
-----
|
||||||
|
@ -0,0 +1,65 @@
|
|||||||
|
<?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\DataTransformer;
|
||||||
|
|
||||||
|
use Symfony\Component\Form\DataTransformerInterface;
|
||||||
|
use Symfony\Component\Form\Exception\TransformationFailedException;
|
||||||
|
|
||||||
|
class StringToFloatTransformer implements DataTransformerInterface
|
||||||
|
{
|
||||||
|
private $scale;
|
||||||
|
|
||||||
|
public function __construct(int $scale = null)
|
||||||
|
{
|
||||||
|
$this->scale = $scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mixed $value
|
||||||
|
*
|
||||||
|
* @return float|null
|
||||||
|
*/
|
||||||
|
public function transform($value)
|
||||||
|
{
|
||||||
|
if (null === $value) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!\is_string($value) || !is_numeric($value)) {
|
||||||
|
throw new TransformationFailedException('Expected a numeric string.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return (float) $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mixed $value
|
||||||
|
*
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public function reverseTransform($value)
|
||||||
|
{
|
||||||
|
if (null === $value) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!\is_int($value) && !\is_float($value)) {
|
||||||
|
throw new TransformationFailedException('Expected a numeric.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->scale > 0) {
|
||||||
|
return number_format((float) $value, $this->scale, '.', '');
|
||||||
|
}
|
||||||
|
|
||||||
|
return (string) $value;
|
||||||
|
}
|
||||||
|
}
|
@ -14,6 +14,7 @@ namespace Symfony\Component\Form\Extension\Core\Type;
|
|||||||
use Symfony\Component\Form\AbstractType;
|
use Symfony\Component\Form\AbstractType;
|
||||||
use Symfony\Component\Form\Exception\LogicException;
|
use Symfony\Component\Form\Exception\LogicException;
|
||||||
use Symfony\Component\Form\Extension\Core\DataTransformer\NumberToLocalizedStringTransformer;
|
use Symfony\Component\Form\Extension\Core\DataTransformer\NumberToLocalizedStringTransformer;
|
||||||
|
use Symfony\Component\Form\Extension\Core\DataTransformer\StringToFloatTransformer;
|
||||||
use Symfony\Component\Form\FormBuilderInterface;
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
use Symfony\Component\Form\FormInterface;
|
use Symfony\Component\Form\FormInterface;
|
||||||
use Symfony\Component\Form\FormView;
|
use Symfony\Component\Form\FormView;
|
||||||
@ -33,6 +34,10 @@ class NumberType extends AbstractType
|
|||||||
$options['rounding_mode'],
|
$options['rounding_mode'],
|
||||||
$options['html5'] ? 'en' : null
|
$options['html5'] ? 'en' : null
|
||||||
));
|
));
|
||||||
|
|
||||||
|
if ('string' === $options['input']) {
|
||||||
|
$builder->addModelTransformer(new StringToFloatTransformer($options['scale']));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -56,6 +61,7 @@ class NumberType extends AbstractType
|
|||||||
'grouping' => false,
|
'grouping' => false,
|
||||||
'rounding_mode' => NumberToLocalizedStringTransformer::ROUND_HALF_UP,
|
'rounding_mode' => NumberToLocalizedStringTransformer::ROUND_HALF_UP,
|
||||||
'compound' => false,
|
'compound' => false,
|
||||||
|
'input' => 'number',
|
||||||
'html5' => false,
|
'html5' => false,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -68,7 +74,7 @@ class NumberType extends AbstractType
|
|||||||
NumberToLocalizedStringTransformer::ROUND_UP,
|
NumberToLocalizedStringTransformer::ROUND_UP,
|
||||||
NumberToLocalizedStringTransformer::ROUND_CEILING,
|
NumberToLocalizedStringTransformer::ROUND_CEILING,
|
||||||
]);
|
]);
|
||||||
|
$resolver->setAllowedValues('input', ['number', 'string']);
|
||||||
$resolver->setAllowedTypes('scale', ['null', 'int']);
|
$resolver->setAllowedTypes('scale', ['null', 'int']);
|
||||||
$resolver->setAllowedTypes('html5', 'bool');
|
$resolver->setAllowedTypes('html5', 'bool');
|
||||||
|
|
||||||
|
@ -0,0 +1,104 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the symfony/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\DataTransformer;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Symfony\Component\Form\Extension\Core\DataTransformer\StringToFloatTransformer;
|
||||||
|
|
||||||
|
class StringToFloatTransformerTest extends TestCase
|
||||||
|
{
|
||||||
|
private $transformer;
|
||||||
|
|
||||||
|
protected function setUp()
|
||||||
|
{
|
||||||
|
$this->transformer = new StringToFloatTransformer();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function tearDown()
|
||||||
|
{
|
||||||
|
$this->transformer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function provideTransformations(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[null, null],
|
||||||
|
['1', 1.],
|
||||||
|
['1.', 1.],
|
||||||
|
['1.0', 1.],
|
||||||
|
['1.23', 1.23],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider provideTransformations
|
||||||
|
*/
|
||||||
|
public function testTransform($from, $to): void
|
||||||
|
{
|
||||||
|
$transformer = new StringToFloatTransformer();
|
||||||
|
|
||||||
|
$this->assertSame($to, $transformer->transform($from));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
|
||||||
|
*/
|
||||||
|
public function testFailIfTransformingANonString(): void
|
||||||
|
{
|
||||||
|
$transformer = new StringToFloatTransformer();
|
||||||
|
$transformer->transform(1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
|
||||||
|
*/
|
||||||
|
public function testFailIfTransformingANonNumericString(): void
|
||||||
|
{
|
||||||
|
$transformer = new StringToFloatTransformer();
|
||||||
|
$transformer->transform('foobar');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function provideReverseTransformations(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[null, null],
|
||||||
|
[1, '1'],
|
||||||
|
[1., '1'],
|
||||||
|
[1.0, '1'],
|
||||||
|
[1.23, '1.23'],
|
||||||
|
[1, '1.000', 3],
|
||||||
|
[1.0, '1.000', 3],
|
||||||
|
[1.23, '1.230', 3],
|
||||||
|
[1.2344, '1.234', 3],
|
||||||
|
[1.2345, '1.235', 3],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider provideReverseTransformations
|
||||||
|
*/
|
||||||
|
public function testReverseTransform($from, $to, int $scale = null): void
|
||||||
|
{
|
||||||
|
$transformer = new StringToFloatTransformer($scale);
|
||||||
|
|
||||||
|
$this->assertSame($to, $transformer->reverseTransform($from));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
|
||||||
|
*/
|
||||||
|
public function testFailIfReverseTransformingANonNumeric(): void
|
||||||
|
{
|
||||||
|
$transformer = new StringToFloatTransformer();
|
||||||
|
$transformer->reverseTransform('foobar');
|
||||||
|
}
|
||||||
|
}
|
@ -27,7 +27,7 @@ class NumberTypeTest extends BaseTypeTest
|
|||||||
\Locale::setDefault('de_DE');
|
\Locale::setDefault('de_DE');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testDefaultFormatting()
|
public function testDefaultFormatting(): void
|
||||||
{
|
{
|
||||||
$form = $this->factory->create(static::TESTED_TYPE);
|
$form = $this->factory->create(static::TESTED_TYPE);
|
||||||
$form->setData('12345.67890');
|
$form->setData('12345.67890');
|
||||||
@ -35,7 +35,7 @@ class NumberTypeTest extends BaseTypeTest
|
|||||||
$this->assertSame('12345,679', $form->createView()->vars['value']);
|
$this->assertSame('12345,679', $form->createView()->vars['value']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testDefaultFormattingWithGrouping()
|
public function testDefaultFormattingWithGrouping(): void
|
||||||
{
|
{
|
||||||
$form = $this->factory->create(static::TESTED_TYPE, null, ['grouping' => true]);
|
$form = $this->factory->create(static::TESTED_TYPE, null, ['grouping' => true]);
|
||||||
$form->setData('12345.67890');
|
$form->setData('12345.67890');
|
||||||
@ -43,7 +43,7 @@ class NumberTypeTest extends BaseTypeTest
|
|||||||
$this->assertSame('12.345,679', $form->createView()->vars['value']);
|
$this->assertSame('12.345,679', $form->createView()->vars['value']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testDefaultFormattingWithScale()
|
public function testDefaultFormattingWithScale(): void
|
||||||
{
|
{
|
||||||
$form = $this->factory->create(static::TESTED_TYPE, null, ['scale' => 2]);
|
$form = $this->factory->create(static::TESTED_TYPE, null, ['scale' => 2]);
|
||||||
$form->setData('12345.67890');
|
$form->setData('12345.67890');
|
||||||
@ -51,7 +51,23 @@ class NumberTypeTest extends BaseTypeTest
|
|||||||
$this->assertSame('12345,68', $form->createView()->vars['value']);
|
$this->assertSame('12345,68', $form->createView()->vars['value']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testDefaultFormattingWithRounding()
|
public function testDefaultFormattingWithScaleFloat(): void
|
||||||
|
{
|
||||||
|
$form = $this->factory->create(static::TESTED_TYPE, null, ['scale' => 2]);
|
||||||
|
$form->setData(12345.67890);
|
||||||
|
|
||||||
|
$this->assertSame('12345,68', $form->createView()->vars['value']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDefaultFormattingWithScaleAndStringInput(): void
|
||||||
|
{
|
||||||
|
$form = $this->factory->create(static::TESTED_TYPE, null, ['scale' => 2, 'input' => 'string']);
|
||||||
|
$form->setData('12345.67890');
|
||||||
|
|
||||||
|
$this->assertSame('12345,68', $form->createView()->vars['value']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDefaultFormattingWithRounding(): void
|
||||||
{
|
{
|
||||||
$form = $this->factory->create(static::TESTED_TYPE, null, ['scale' => 0, 'rounding_mode' => \NumberFormatter::ROUND_UP]);
|
$form = $this->factory->create(static::TESTED_TYPE, null, ['scale' => 0, 'rounding_mode' => \NumberFormatter::ROUND_UP]);
|
||||||
$form->setData('12345.54321');
|
$form->setData('12345.54321');
|
||||||
@ -76,6 +92,46 @@ class NumberTypeTest extends BaseTypeTest
|
|||||||
$this->assertSame($expectedData, $form->getData());
|
$this->assertSame($expectedData, $form->getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testSubmitNumericInput(): void
|
||||||
|
{
|
||||||
|
$form = $this->factory->create(static::TESTED_TYPE, null, ['input' => 'number']);
|
||||||
|
$form->submit('1,234');
|
||||||
|
|
||||||
|
$this->assertSame(1.234, $form->getData());
|
||||||
|
$this->assertSame(1.234, $form->getNormData());
|
||||||
|
$this->assertSame('1,234', $form->getViewData());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSubmitNumericInputWithScale(): void
|
||||||
|
{
|
||||||
|
$form = $this->factory->create(static::TESTED_TYPE, null, ['input' => 'number', 'scale' => 2]);
|
||||||
|
$form->submit('1,234');
|
||||||
|
|
||||||
|
$this->assertSame(1.23, $form->getData());
|
||||||
|
$this->assertSame(1.23, $form->getNormData());
|
||||||
|
$this->assertSame('1,23', $form->getViewData());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSubmitStringInput(): void
|
||||||
|
{
|
||||||
|
$form = $this->factory->create(static::TESTED_TYPE, null, ['input' => 'string']);
|
||||||
|
$form->submit('1,234');
|
||||||
|
|
||||||
|
$this->assertSame('1.234', $form->getData());
|
||||||
|
$this->assertSame(1.234, $form->getNormData());
|
||||||
|
$this->assertSame('1,234', $form->getViewData());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSubmitStringInputWithScale(): void
|
||||||
|
{
|
||||||
|
$form = $this->factory->create(static::TESTED_TYPE, null, ['input' => 'string', 'scale' => 2]);
|
||||||
|
$form->submit('1,234');
|
||||||
|
|
||||||
|
$this->assertSame('1.23', $form->getData());
|
||||||
|
$this->assertSame(1.23, $form->getNormData());
|
||||||
|
$this->assertSame('1,23', $form->getViewData());
|
||||||
|
}
|
||||||
|
|
||||||
public function testIgnoresDefaultLocaleToRenderHtml5NumberWidgets()
|
public function testIgnoresDefaultLocaleToRenderHtml5NumberWidgets()
|
||||||
{
|
{
|
||||||
$form = $this->factory->create(static::TESTED_TYPE, null, [
|
$form = $this->factory->create(static::TESTED_TYPE, null, [
|
||||||
|
Reference in New Issue
Block a user