feature #21919 [Form] Deprecated usage of "choices" option in sub types (HeahDude)

This PR was merged into the 3.3-dev branch.

Discussion
----------

[Form] Deprecated usage of "choices" option in sub types

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | no
| BC breaks?    | no
| Deprecations? | yes
| Tests pass?   | yes
| Fixed tickets | #... <!-- #-prefixed issue number(s), if any -->
| License       | MIT
| Doc PR        | ~

Follows #21880 and the discussion in #20771.

Commits
-------

b5b56fcbac [Form] Deprecated usage of "choices" option in sub types
This commit is contained in:
Fabien Potencier 2017-04-05 11:14:26 -07:00
commit 457174dad9
10 changed files with 179 additions and 6 deletions

View File

@ -130,6 +130,34 @@ Finder
* The `ExceptionInterface` has been deprecated and will be removed in 4.0.
Form
----
* Using the "choices" option in ``CountryType``, ``CurrencyType``, ``LanguageType``,
``LocaleType``, and ``TimezoneType`` without overriding the ``choice_loader``
option has been deprecated and will be ignored in 4.0.
Before:
```php
$builder->add('custom_locales', LocaleType::class, array(
'choices' => $availableLocales,
));
```
After:
```php
$builder->add('custom_locales', LocaleType::class, array(
'choices' => $availableLocales,
'choice_loader' => null,
));
// or
$builder->add('custom_locales', LocaleType::class, array(
'choice_loader' => new CallbackChoiceLoader(function () {
return $this->getAvailableLocales();
}),
));
```
FrameworkBundle
---------------

View File

@ -193,6 +193,31 @@ Form
}
```
* Using the "choices" option in ``CountryType``, ``CurrencyType``, ``LanguageType``,
``LocaleType``, and ``TimezoneType`` without overriding the ``choice_loader``
option is now ignored.
Before:
```php
$builder->add('custom_locales', LocaleType::class, array(
'choices' => $availableLocales,
));
```
After:
```php
$builder->add('custom_locales', LocaleType::class, array(
'choices' => $availableLocales,
'choice_loader' => null,
));
// or
$builder->add('custom_locales', LocaleType::class, array(
'choice_loader' => new CallbackChoiceLoader(function () {
return $this->getAvailableLocales();
}),
));
```
FrameworkBundle
---------------

View File

@ -4,6 +4,8 @@ CHANGELOG
3.3.0
-----
* deprecated using "choices" option in ``CountryType``, ``CurrencyType``, ``LanguageType``, ``LocaleType``, and
``TimezoneType`` when "choice_loader" is not ``null``
* added `Symfony\Component\Form\FormErrorIterator::findByCodes()`
* added `getTypedExtensions`, `getTypes`, and `getTypeGuessers` to `Symfony\Component\Form\Test\FormIntegrationTestCase`
* added `FormPass`

View File

@ -38,7 +38,13 @@ class CountryType extends AbstractType implements ChoiceLoaderInterface
{
$resolver->setDefaults(array(
'choice_loader' => function (Options $options) {
return $options['choices'] ? null : $this;
if ($options['choices']) {
@trigger_error(sprintf('Using the "choices" option in %s has been deprecated since version 3.3 and will be ignored in 4.0. Override the "choice_loader" option instead or set it to null.', __CLASS__), E_USER_DEPRECATED);
return null;
}
return $this;
},
'choice_translation_domain' => false,
));

View File

@ -38,7 +38,13 @@ class CurrencyType extends AbstractType implements ChoiceLoaderInterface
{
$resolver->setDefaults(array(
'choice_loader' => function (Options $options) {
return $options['choices'] ? null : $this;
if ($options['choices']) {
@trigger_error(sprintf('Using the "choices" option in %s has been deprecated since version 3.3 and will be ignored in 4.0. Override the "choice_loader" option instead or set it to null.', __CLASS__), E_USER_DEPRECATED);
return null;
}
return $this;
},
'choice_translation_domain' => false,
));

View File

@ -38,7 +38,13 @@ class LanguageType extends AbstractType implements ChoiceLoaderInterface
{
$resolver->setDefaults(array(
'choice_loader' => function (Options $options) {
return $options['choices'] ? null : $this;
if ($options['choices']) {
@trigger_error(sprintf('Using the "choices" option in %s has been deprecated since version 3.3 and will be ignored in 4.0. Override the "choice_loader" option instead or set it to null.', __CLASS__), E_USER_DEPRECATED);
return null;
}
return $this;
},
'choice_translation_domain' => false,
));

View File

@ -38,7 +38,13 @@ class LocaleType extends AbstractType implements ChoiceLoaderInterface
{
$resolver->setDefaults(array(
'choice_loader' => function (Options $options) {
return $options['choices'] ? null : $this;
if ($options['choices']) {
@trigger_error(sprintf('Using the "choices" option in %s has been deprecated since version 3.3 and will be ignored in 4.0. Override the "choice_loader" option instead or set it to null.', __CLASS__), E_USER_DEPRECATED);
return null;
}
return $this;
},
'choice_translation_domain' => false,
));

View File

@ -35,7 +35,13 @@ class TimezoneType extends AbstractType implements ChoiceLoaderInterface
{
$resolver->setDefaults(array(
'choice_loader' => function (Options $options) {
return $options['choices'] ? null : $this;
if ($options['choices']) {
@trigger_error(sprintf('Using the "choices" option in %s has been deprecated since version 3.3 and will be ignored in 4.0. Override the "choice_loader" option instead or set it to null.', __CLASS__), E_USER_DEPRECATED);
return null;
}
return $this;
},
'choice_translation_domain' => false,
));

View File

@ -14,13 +14,15 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\Forms;
use Symfony\Component\Form\Tests\Fixtures\ChoiceTypeExtension;
use Symfony\Component\Form\Tests\Fixtures\LazyChoiceTypeExtension;
class ExtendedChoiceTypeTest extends TestCase
{
/**
* @group legacy
* @dataProvider provideTestedTypes
*/
public function testChoicesAreOverridden($type)
public function testLegacyChoicesAreOverridden($type)
{
$factory = Forms::createFormFactoryBuilder()
->addTypeExtension(new ChoiceTypeExtension($type))
@ -36,6 +38,44 @@ class ExtendedChoiceTypeTest extends TestCase
$this->assertSame('b', $choices[1]->value);
}
/**
* @dataProvider provideTestedTypes
*/
public function testChoicesAreOverridden($type)
{
$factory = Forms::createFormFactoryBuilder()
->addTypeExtension(new ChoiceTypeExtension($type))
->getFormFactory()
;
$choices = $factory->create($type, null, array('choice_loader' => null))->createView()->vars['choices'];
$this->assertCount(2, $choices);
$this->assertSame('A', $choices[0]->label);
$this->assertSame('a', $choices[0]->value);
$this->assertSame('B', $choices[1]->label);
$this->assertSame('b', $choices[1]->value);
}
/**
* @dataProvider provideTestedTypes
*/
public function testChoiceLoaderIsOverridden($type)
{
$factory = Forms::createFormFactoryBuilder()
->addTypeExtension(new LazyChoiceTypeExtension($type))
->getFormFactory()
;
$choices = $factory->create($type)->createView()->vars['choices'];
$this->assertCount(2, $choices);
$this->assertSame('Lazy A', $choices[0]->label);
$this->assertSame('lazy_a', $choices[0]->value);
$this->assertSame('Lazy B', $choices[1]->label);
$this->assertSame('lazy_b', $choices[1]->value);
}
public function provideTestedTypes()
{
yield array(CountryTypeTest::TESTED_TYPE);

View File

@ -0,0 +1,48 @@
<?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\Fixtures;
use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\ChoiceList\Loader\CallbackChoiceLoader;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\OptionsResolver\OptionsResolver;
class LazyChoiceTypeExtension extends AbstractTypeExtension
{
private $extendedType;
public function __construct($extendedType = ChoiceType::class)
{
$this->extendedType = $extendedType;
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefault('choice_loader', new CallbackChoiceLoader(function () {
return array(
'Lazy A' => 'lazy_a',
'Lazy B' => 'lazy_b',
);
}));
}
/**
* {@inheritdoc}
*/
public function getExtendedType()
{
return $this->extendedType;
}
}