[Form] Add input + regions options to TimezoneType
This commit is contained in:
parent
40a3466268
commit
183307b741
@ -74,6 +74,38 @@ Finder
|
||||
deprecated and will be removed in 4.0 as it used to fix a bug which existed
|
||||
before version 5.5.23/5.6.7.
|
||||
|
||||
Form
|
||||
----
|
||||
|
||||
* Deprecated `ChoiceLoaderInterface` implementation in `TimezoneType`. Use the "choice_loader" option instead.
|
||||
|
||||
Before:
|
||||
```php
|
||||
class MyTimezoneType extends TimezoneType
|
||||
{
|
||||
public function loadChoices()
|
||||
{
|
||||
// override the method
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
After:
|
||||
```php
|
||||
class MyTimezoneType extends AbstractType
|
||||
{
|
||||
public function. getParent()
|
||||
{
|
||||
return TimezoneType::class;
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setDefault('choice_loader', ...); // override the option instead
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
FrameworkBundle
|
||||
---------------
|
||||
|
||||
|
@ -282,6 +282,35 @@ Form
|
||||
));
|
||||
```
|
||||
|
||||
* Removed `ChoiceLoaderInterface` implementation in `TimezoneType`. Use the "choice_loader" option instead.
|
||||
|
||||
Before:
|
||||
```php
|
||||
class MyTimezoneType extends TimezoneType
|
||||
{
|
||||
public function loadChoices()
|
||||
{
|
||||
// override the method
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
After:
|
||||
```php
|
||||
class MyTimezoneType extends AbstractType
|
||||
{
|
||||
public function. getParent()
|
||||
{
|
||||
return TimezoneType::class;
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setDefault('choice_loader', ...); // override the option instead
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
FrameworkBundle
|
||||
---------------
|
||||
|
||||
|
@ -5,6 +5,8 @@ CHANGELOG
|
||||
-----
|
||||
|
||||
* added `DebugCommand`
|
||||
* deprecated `ChoiceLoaderInterface` implementation in `TimezoneType`
|
||||
* added options "input" and "regions" to `TimezoneType`
|
||||
|
||||
3.3.0
|
||||
-----
|
||||
|
@ -0,0 +1,82 @@
|
||||
<?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 timezone identifier string and a DateTimeZone object.
|
||||
*
|
||||
* @author Roland Franssen <franssen.roland@gmai.com>
|
||||
*/
|
||||
class DateTimeZoneToStringTransformer implements DataTransformerInterface
|
||||
{
|
||||
private $multiple;
|
||||
|
||||
public function __construct($multiple = false)
|
||||
{
|
||||
$this->multiple = $multiple;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function transform($dateTimeZone)
|
||||
{
|
||||
if (null === $dateTimeZone) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->multiple) {
|
||||
if (!is_array($dateTimeZone)) {
|
||||
throw new TransformationFailedException('Expected an array.');
|
||||
}
|
||||
|
||||
return array_map(array(new self(), 'transform'), $dateTimeZone);
|
||||
}
|
||||
|
||||
if (!$dateTimeZone instanceof \DateTimeZone) {
|
||||
throw new TransformationFailedException('Expected a \DateTimeZone.');
|
||||
}
|
||||
|
||||
return $dateTimeZone->getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function reverseTransform($value)
|
||||
{
|
||||
if (null === $value) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->multiple) {
|
||||
if (!is_array($value)) {
|
||||
throw new TransformationFailedException('Expected an array.');
|
||||
}
|
||||
|
||||
return array_map(array(new self(), 'reverseTransform'), $value);
|
||||
}
|
||||
|
||||
if (!is_string($value)) {
|
||||
throw new TransformationFailedException('Expected a string.');
|
||||
}
|
||||
|
||||
try {
|
||||
return new \DateTimeZone($value);
|
||||
} catch (\Exception $e) {
|
||||
throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
|
||||
}
|
||||
}
|
||||
}
|
@ -13,7 +13,10 @@ namespace Symfony\Component\Form\Extension\Core\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\ChoiceList\ArrayChoiceList;
|
||||
use Symfony\Component\Form\ChoiceList\Loader\CallbackChoiceLoader;
|
||||
use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface;
|
||||
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeZoneToStringTransformer;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\Options;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
@ -25,9 +28,21 @@ class TimezoneType extends AbstractType implements ChoiceLoaderInterface
|
||||
* The choices are generated from the ICU function \DateTimeZone::listIdentifiers().
|
||||
*
|
||||
* @var ArrayChoiceList
|
||||
*
|
||||
* @deprecated since version 3.4, to be removed in 4.0
|
||||
*/
|
||||
private $choiceList;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
if ('datetimezone' === $options['input']) {
|
||||
$builder->addModelTransformer(new DateTimeZoneToStringTransformer($options['multiple']));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@ -41,10 +56,20 @@ class TimezoneType extends AbstractType implements ChoiceLoaderInterface
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this;
|
||||
$regions = $options['regions'];
|
||||
|
||||
return new CallbackChoiceLoader(function () use ($regions) {
|
||||
return self::getTimezones($regions);
|
||||
});
|
||||
},
|
||||
'choice_translation_domain' => false,
|
||||
'input' => 'string',
|
||||
'regions' => \DateTimeZone::ALL,
|
||||
));
|
||||
|
||||
$resolver->setAllowedValues('input', array('string', 'datetimezone'));
|
||||
|
||||
$resolver->setAllowedTypes('regions', 'int');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -65,21 +90,29 @@ class TimezoneType extends AbstractType implements ChoiceLoaderInterface
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @deprecated since version 3.4, to be removed in 4.0
|
||||
*/
|
||||
public function loadChoiceList($value = null)
|
||||
{
|
||||
@trigger_error(sprintf('Method "%s" is deprecated since version 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
if (null !== $this->choiceList) {
|
||||
return $this->choiceList;
|
||||
}
|
||||
|
||||
return $this->choiceList = new ArrayChoiceList(self::getTimezones(), $value);
|
||||
return $this->choiceList = new ArrayChoiceList(self::getTimezones(\DateTimeZone::ALL), $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @deprecated since version 3.4, to be removed in 4.0
|
||||
*/
|
||||
public function loadChoicesForValues(array $values, $value = null)
|
||||
{
|
||||
@trigger_error(sprintf('Method "%s" is deprecated since version 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
// Optimize
|
||||
$values = array_filter($values);
|
||||
if (empty($values)) {
|
||||
@ -96,9 +129,13 @@ class TimezoneType extends AbstractType implements ChoiceLoaderInterface
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @deprecated since version 3.4, to be removed in 4.0
|
||||
*/
|
||||
public function loadValuesForChoices(array $choices, $value = null)
|
||||
{
|
||||
@trigger_error(sprintf('Method "%s" is deprecated since version 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
// Optimize
|
||||
$choices = array_filter($choices);
|
||||
if (empty($choices)) {
|
||||
@ -116,13 +153,15 @@ class TimezoneType extends AbstractType implements ChoiceLoaderInterface
|
||||
/**
|
||||
* Returns a normalized array of timezone choices.
|
||||
*
|
||||
* @param int $regions
|
||||
*
|
||||
* @return array The timezone choices
|
||||
*/
|
||||
private static function getTimezones()
|
||||
private static function getTimezones($regions)
|
||||
{
|
||||
$timezones = array();
|
||||
|
||||
foreach (\DateTimeZone::listIdentifiers() as $timezone) {
|
||||
foreach (\DateTimeZone::listIdentifiers($regions) as $timezone) {
|
||||
$parts = explode('/', $timezone);
|
||||
|
||||
if (count($parts) > 2) {
|
||||
@ -139,6 +178,6 @@ class TimezoneType extends AbstractType implements ChoiceLoaderInterface
|
||||
$timezones[$region][str_replace('_', ' ', $name)] = $timezone;
|
||||
}
|
||||
|
||||
return $timezones;
|
||||
return 1 === count($timezones) ? reset($timezones) : $timezones;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,56 @@
|
||||
<?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 Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeZoneToStringTransformer;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class DateTimeZoneToStringTransformerTest extends TestCase
|
||||
{
|
||||
public function testSingle()
|
||||
{
|
||||
$transformer = new DateTimeZoneToStringTransformer();
|
||||
|
||||
$this->assertNull($transformer->transform(null));
|
||||
$this->assertNull($transformer->reverseTransform(null));
|
||||
|
||||
$this->assertSame('Europe/Amsterdam', $transformer->transform(new \DateTimeZone('Europe/Amsterdam')));
|
||||
$this->assertEquals(new \DateTimeZone('Europe/Amsterdam'), $transformer->reverseTransform('Europe/Amsterdam'));
|
||||
}
|
||||
|
||||
public function testMultiple()
|
||||
{
|
||||
$transformer = new DateTimeZoneToStringTransformer(true);
|
||||
|
||||
$this->assertNull($transformer->transform(null));
|
||||
$this->assertNull($transformer->reverseTransform(null));
|
||||
|
||||
$this->assertSame(array('Europe/Amsterdam'), $transformer->transform(array(new \DateTimeZone('Europe/Amsterdam'))));
|
||||
$this->assertEquals(array(new \DateTimeZone('Europe/Amsterdam')), $transformer->reverseTransform(array('Europe/Amsterdam')));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
|
||||
*/
|
||||
public function testInvalidTimezone()
|
||||
{
|
||||
(new DateTimeZoneToStringTransformer())->transform(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
|
||||
*/
|
||||
public function testUnknownTimezone()
|
||||
{
|
||||
(new DateTimeZoneToStringTransformer(true))->reverseTransform(array('Foo/Bar'));
|
||||
}
|
||||
}
|
@ -33,4 +33,31 @@ class TimezoneTypeTest extends BaseTypeTest
|
||||
{
|
||||
parent::testSubmitNull($expected, $norm, '');
|
||||
}
|
||||
|
||||
public function testDateTimeZoneInput()
|
||||
{
|
||||
$form = $this->factory->create(static::TESTED_TYPE, new \DateTimeZone('America/New_York'), array('input' => 'datetimezone'));
|
||||
|
||||
$this->assertSame('America/New_York', $form->createView()->vars['value']);
|
||||
|
||||
$form->submit('Europe/Amsterdam');
|
||||
|
||||
$this->assertEquals(new \DateTimeZone('Europe/Amsterdam'), $form->getData());
|
||||
|
||||
$form = $this->factory->create(static::TESTED_TYPE, array(new \DateTimeZone('America/New_York')), array('input' => 'datetimezone', 'multiple' => true));
|
||||
|
||||
$this->assertSame(array('America/New_York'), $form->createView()->vars['value']);
|
||||
|
||||
$form->submit(array('Europe/Amsterdam', 'Europe/Paris'));
|
||||
|
||||
$this->assertEquals(array(new \DateTimeZone('Europe/Amsterdam'), new \DateTimeZone('Europe/Paris')), $form->getData());
|
||||
}
|
||||
|
||||
public function testFilterByRegions()
|
||||
{
|
||||
$choices = $this->factory->create(static::TESTED_TYPE, null, array('regions' => \DateTimeZone::EUROPE))
|
||||
->createView()->vars['choices'];
|
||||
|
||||
$this->assertContains(new ChoiceView('Europe/Amsterdam', 'Europe/Amsterdam', 'Amsterdam'), $choices, '', false, false);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user