[Form] Support \DateTimeImmutable

This commit is contained in:
Valentin 2017-12-22 17:02:25 +03:00 committed by Fabien Potencier
parent 32cc2e06a3
commit 034f8b2f23
9 changed files with 255 additions and 3 deletions

View File

@ -1,6 +1,11 @@
CHANGELOG
=========
4.1.0
-----
* added `input=datetime_immutable` to DateType, TimeType, DateTimeType
4.0.0
-----

View File

@ -0,0 +1,67 @@
<?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;
/**
* Transforms between a DateTimeImmutable object and a DateTime object.
*
* @author Valentin Udaltsov <udaltsov.valentin@gmail.com>
*/
final class DateTimeImmutableToDateTimeTransformer implements DataTransformerInterface
{
/**
* Transforms a DateTimeImmutable into a DateTime object.
*
* @param \DateTimeImmutable|null $value A DateTimeImmutable object
*
* @return \DateTime|null A \DateTime object
*
* @throws TransformationFailedException If the given value is not a \DateTimeImmutable
*/
public function transform($value)
{
if (null === $value) {
return null;
}
if (!$value instanceof \DateTimeImmutable) {
throw new TransformationFailedException('Expected a \DateTimeImmutable.');
}
return \DateTime::createFromFormat(\DateTime::RFC3339, $value->format(\DateTime::RFC3339));
}
/**
* Transforms a DateTime object into a DateTimeImmutable object.
*
* @param \DateTime|null $value A DateTime object
*
* @return \DateTimeImmutable|null A DateTimeImmutable object
*
* @throws TransformationFailedException If the given value is not a \DateTime
*/
public function reverseTransform($value)
{
if (null === $value) {
return null;
}
if (!$value instanceof \DateTime) {
throw new TransformationFailedException('Expected a \DateTime.');
}
return \DateTimeImmutable::createFromMutable($value);
}
}

View File

@ -18,6 +18,7 @@ use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\ReversedTransformer;
use Symfony\Component\Form\Extension\Core\DataTransformer\DataTransformerChain;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeImmutableToDateTimeTransformer;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToArrayTransformer;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToLocalizedStringTransformer;
@ -165,7 +166,9 @@ class DateTimeType extends AbstractType
;
}
if ('string' === $options['input']) {
if ('datetime_immutable' === $options['input']) {
$builder->addModelTransformer(new DateTimeImmutableToDateTimeTransformer());
} elseif ('string' === $options['input']) {
$builder->addModelTransformer(new ReversedTransformer(
new DateTimeToStringTransformer($options['model_timezone'], $options['model_timezone'])
));
@ -254,6 +257,7 @@ class DateTimeType extends AbstractType
$resolver->setAllowedValues('input', array(
'datetime',
'datetime_immutable',
'string',
'timestamp',
'array',

View File

@ -15,6 +15,7 @@ use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeImmutableToDateTimeTransformer;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToLocalizedStringTransformer;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToArrayTransformer;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer;
@ -123,7 +124,9 @@ class DateType extends AbstractType
;
}
if ('string' === $options['input']) {
if ('datetime_immutable' === $options['input']) {
$builder->addModelTransformer(new DateTimeImmutableToDateTimeTransformer());
} elseif ('string' === $options['input']) {
$builder->addModelTransformer(new ReversedTransformer(
new DateTimeToStringTransformer($options['model_timezone'], $options['model_timezone'], 'Y-m-d')
));
@ -258,6 +261,7 @@ class DateType extends AbstractType
$resolver->setAllowedValues('input', array(
'datetime',
'datetime_immutable',
'string',
'timestamp',
'array',

View File

@ -18,6 +18,7 @@ use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\ReversedTransformer;
use Symfony\Component\Form\Exception\InvalidConfigurationException;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeImmutableToDateTimeTransformer;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToArrayTransformer;
@ -133,7 +134,9 @@ class TimeType extends AbstractType
$builder->addViewTransformer(new DateTimeToArrayTransformer($options['model_timezone'], $options['view_timezone'], $parts, 'text' === $options['widget']));
}
if ('string' === $options['input']) {
if ('datetime_immutable' === $options['input']) {
$builder->addModelTransformer(new DateTimeImmutableToDateTimeTransformer());
} elseif ('string' === $options['input']) {
$builder->addModelTransformer(new ReversedTransformer(
new DateTimeToStringTransformer($options['model_timezone'], $options['model_timezone'], 'H:i:s')
));
@ -252,6 +255,7 @@ class TimeType extends AbstractType
$resolver->setAllowedValues('input', array(
'datetime',
'datetime_immutable',
'string',
'timestamp',
'array',

View File

@ -0,0 +1,76 @@
<?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\DataTransformer;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeImmutableToDateTimeTransformer;
class DateTimeImmutableToDateTimeTransformerTest extends TestCase
{
public function testTransform()
{
$transformer = new DateTimeImmutableToDateTimeTransformer();
$input = new \DateTimeImmutable('2010-02-03 04:05:06 UTC');
$expectedOutput = new \DateTime('2010-02-03 04:05:06 UTC');
$actualOutput = $transformer->transform($input);
$this->assertInstanceOf(\DateTime::class, $actualOutput);
$this->assertEquals($expectedOutput, $actualOutput);
}
public function testTransformEmpty()
{
$transformer = new DateTimeImmutableToDateTimeTransformer();
$this->assertNull($transformer->transform(null));
}
/**
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
* @expectedExceptionMessage Expected a \DateTimeImmutable.
*/
public function testTransformFail()
{
$transformer = new DateTimeImmutableToDateTimeTransformer();
$transformer->transform(new \DateTime());
}
public function testReverseTransform()
{
$transformer = new DateTimeImmutableToDateTimeTransformer();
$input = new \DateTime('2010-02-03 04:05:06 UTC');
$expectedOutput = new \DateTimeImmutable('2010-02-03 04:05:06 UTC');
$actualOutput = $transformer->reverseTransform($input);
$this->assertInstanceOf(\DateTimeImmutable::class, $actualOutput);
$this->assertEquals($expectedOutput, $actualOutput);
}
public function testReverseTransformEmpty()
{
$transformer = new DateTimeImmutableToDateTimeTransformer();
$this->assertNull($transformer->reverseTransform(null));
}
/**
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
* @expectedExceptionMessage Expected a \DateTime.
*/
public function testReverseTransformFail()
{
$transformer = new DateTimeImmutableToDateTimeTransformer();
$transformer->reverseTransform(new \DateTimeImmutable());
}
}

View File

@ -52,6 +52,34 @@ class DateTimeTypeTest extends BaseTypeTest
$this->assertEquals($dateTime, $form->getData());
}
public function testSubmitDateTimeImmutable()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'model_timezone' => 'UTC',
'view_timezone' => 'UTC',
'date_widget' => 'choice',
'years' => array(2010),
'time_widget' => 'choice',
'input' => 'datetime_immutable',
));
$form->submit(array(
'date' => array(
'day' => '2',
'month' => '6',
'year' => '2010',
),
'time' => array(
'hour' => '3',
'minute' => '4',
),
));
$dateTime = new \DateTimeImmutable('2010-06-02 03:04:00 UTC');
$this->assertEquals($dateTime, $form->getData());
}
public function testSubmitString()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
@ -219,6 +247,26 @@ class DateTimeTypeTest extends BaseTypeTest
$this->assertEquals('2010-06-02T03:04:00-10:00', $form->getViewData());
}
public function testSubmitDifferentTimezonesDateTimeImmutable()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'model_timezone' => 'America/New_York',
'view_timezone' => 'Pacific/Tahiti',
'widget' => 'single_text',
'input' => 'datetime_immutable',
));
$outputTime = new \DateTimeImmutable('2010-06-02 03:04:00 Pacific/Tahiti');
$form->submit('2010-06-02T03:04:00-10:00');
$outputTime = $outputTime->setTimezone(new \DateTimeZone('America/New_York'));
$this->assertInstanceOf(\DateTimeImmutable::class, $form->getData());
$this->assertEquals($outputTime, $form->getData());
$this->assertEquals('2010-06-02T03:04:00-10:00', $form->getViewData());
}
public function testSubmitStringSingleText()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(

View File

@ -105,6 +105,28 @@ class DateTypeTest extends BaseTypeTest
$this->assertEquals('02.06.2010', $form->getViewData());
}
public function testSubmitFromSingleTextDateTimeImmutable()
{
// we test against "de_DE", so we need the full implementation
IntlTestHelper::requireFullIntl($this, false);
\Locale::setDefault('de_DE');
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'format' => \IntlDateFormatter::MEDIUM,
'model_timezone' => 'UTC',
'view_timezone' => 'UTC',
'widget' => 'single_text',
'input' => 'datetime_immutable',
));
$form->submit('2.6.2010');
$this->assertInstanceOf(\DateTimeImmutable::class, $form->getData());
$this->assertEquals(new \DateTimeImmutable('2010-06-02 UTC'), $form->getData());
$this->assertEquals('02.06.2010', $form->getViewData());
}
public function testSubmitFromSingleTextString()
{
// we test against "de_DE", so we need the full implementation

View File

@ -39,6 +39,28 @@ class TimeTypeTest extends BaseTypeTest
$this->assertEquals($input, $form->getViewData());
}
public function testSubmitDateTimeImmutable()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(
'model_timezone' => 'UTC',
'view_timezone' => 'UTC',
'input' => 'datetime_immutable',
));
$input = array(
'hour' => '3',
'minute' => '4',
);
$form->submit($input);
$dateTime = new \DateTimeImmutable('1970-01-01 03:04:00 UTC');
$this->assertInstanceOf(\DateTimeImmutable::class, $form->getData());
$this->assertEquals($dateTime, $form->getData());
$this->assertEquals($input, $form->getViewData());
}
public function testSubmitString()
{
$form = $this->factory->create(static::TESTED_TYPE, null, array(