Skip to content

Commit

Permalink
feature #26825 [Form] Add choice_translation_locale option for Intl c…
Browse files Browse the repository at this point in the history
…hoice types (yceruto, fabpot)

This PR was merged into the 4.1-dev branch.

Discussion
----------

[Form] Add choice_translation_locale option for Intl choice types

| Q             | A
| ------------- | ---
| Branch?       | master (4.2)
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | yes
| Tests pass?   | yes
| Fixed tickets | #26737
| License       | MIT
| Doc PR        | symfony/symfony-docs#...

This PR adds possibility to show the list of elements for a custom locale different to the current one and proposes also deprecate the `ChoiceLoaderInterface` implementation from all of them, moving it to a separate class.

See related issue #26737 for full description and use-case.

After:
```php
$formBuilder->add('country', CountryType::class, [
    'choice_translation_locale' => 'es',
]);
```

Alternative of #23629

TODO:

- [x] Update `UPGRADE-*.md` and `src/**/CHANGELOG.md` files.
- [x] Add some tests.

Commits
-------

9592fa6 moved feature to 4.1
e250dfa Add choice_translation_locale option for Intl choice types
  • Loading branch information
fabpot committed Apr 22, 2018
2 parents 773c9df + 9592fa6 commit 2ceef59
Show file tree
Hide file tree
Showing 12 changed files with 377 additions and 4 deletions.
34 changes: 34 additions & 0 deletions UPGRADE-4.1.md
Expand Up @@ -29,6 +29,40 @@ EventDispatcher

* The `TraceableEventDispatcherInterface` has been deprecated.

Form
----

* Deprecated the `ChoiceLoaderInterface` implementation in `CountryType`,
`LanguageType`, `LocaleType` and `CurrencyType`, use the `choice_loader`
option instead.

Before:
```php
class MyCountryType extends CountryType
{
public function loadChoiceList()
{
// override the method
}
}
```

After:
```php
class MyCountryType extends AbstractType
{
public function getParent()
{
return CountryType::class;
}

public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefault('choice_loader', ...); // override the option instead
}
}
```

FrameworkBundle
---------------

Expand Down
4 changes: 4 additions & 0 deletions src/Symfony/Component/Form/CHANGELOG.md
Expand Up @@ -6,6 +6,10 @@ CHANGELOG

* added `input=datetime_immutable` to `DateType`, `TimeType`, `DateTimeType`
* added `rounding_mode` option to `MoneyType`
* added `choice_translation_locale` option to `CountryType`, `LanguageType`, `LocaleType` and `CurrencyType`
* deprecated the `ChoiceLoaderInterface` implementation in `CountryType`, `LanguageType`, `LocaleType` and `CurrencyType`
* added `input=datetime_immutable` to DateType, TimeType, DateTimeType
* added `rounding_mode` option to MoneyType

4.0.0
-----
Expand Down
@@ -0,0 +1,59 @@
<?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\ChoiceList\Loader;

/**
* Callback choice loader optimized for Intl choice types.
*
* @author Jules Pietri <jules@heahprod.com>
* @author Yonel Ceruto <yonelceruto@gmail.com>
*/
class IntlCallbackChoiceLoader extends CallbackChoiceLoader
{
/**
* {@inheritdoc}
*/
public function loadChoicesForValues(array $values, $value = null)
{
// Optimize
$values = array_filter($values);
if (empty($values)) {
return array();
}

// If no callable is set, values are the same as choices
if (null === $value) {
return $values;
}

return $this->loadChoiceList($value)->getChoicesForValues($values);
}

/**
* {@inheritdoc}
*/
public function loadValuesForChoices(array $choices, $value = null)
{
// Optimize
$choices = array_filter($choices);
if (empty($choices)) {
return array();
}

// If no callable is set, choices are the same as values
if (null === $value) {
return $choices;
}

return $this->loadChoiceList($value)->getValuesForChoices($choices);
}
}
27 changes: 26 additions & 1 deletion src/Symfony/Component/Form/Extension/Core/Type/CountryType.php
Expand Up @@ -14,7 +14,9 @@
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\ChoiceList\ArrayChoiceList;
use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface;
use Symfony\Component\Form\ChoiceList\Loader\IntlCallbackChoiceLoader;
use Symfony\Component\Intl\Intl;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;

class CountryType extends AbstractType implements ChoiceLoaderInterface
Expand All @@ -27,6 +29,8 @@ class CountryType extends AbstractType implements ChoiceLoaderInterface
* {@link \Symfony\Component\Intl\Intl::getRegionBundle()}.
*
* @var ArrayChoiceList
*
* @deprecated since Symfony 4.1
*/
private $choiceList;

Expand All @@ -36,9 +40,18 @@ class CountryType extends AbstractType implements ChoiceLoaderInterface
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'choice_loader' => $this,
'choice_loader' => function (Options $options) {
$choiceTranslationLocale = $options['choice_translation_locale'];

return new IntlCallbackChoiceLoader(function () use ($choiceTranslationLocale) {
return array_flip(Intl::getRegionBundle()->getCountryNames($choiceTranslationLocale));
});
},
'choice_translation_domain' => false,
'choice_translation_locale' => null,
));

$resolver->setAllowedTypes('choice_translation_locale', array('null', 'string'));
}

/**
Expand All @@ -59,9 +72,13 @@ public function getBlockPrefix()

/**
* {@inheritdoc}
*
* @deprecated since Symfony 4.1
*/
public function loadChoiceList($value = null)
{
@trigger_error(sprintf('Method "%s" is deprecated since Symfony 4.1, use "choice_loader" option instead.', __METHOD__), E_USER_DEPRECATED);

if (null !== $this->choiceList) {
return $this->choiceList;
}
Expand All @@ -71,9 +88,13 @@ public function loadChoiceList($value = null)

/**
* {@inheritdoc}
*
* @deprecated since Symfony 4.1
*/
public function loadChoicesForValues(array $values, $value = null)
{
@trigger_error(sprintf('Method "%s" is deprecated since Symfony 4.1, use "choice_loader" option instead.', __METHOD__), E_USER_DEPRECATED);

// Optimize
$values = array_filter($values);
if (empty($values)) {
Expand All @@ -90,9 +111,13 @@ public function loadChoicesForValues(array $values, $value = null)

/**
* {@inheritdoc}
*
* @deprecated since Symfony 4.1
*/
public function loadValuesForChoices(array $choices, $value = null)
{
@trigger_error(sprintf('Method "%s" is deprecated since Symfony 4.1, use "choice_loader" option instead.', __METHOD__), E_USER_DEPRECATED);

// Optimize
$choices = array_filter($choices);
if (empty($choices)) {
Expand Down
27 changes: 26 additions & 1 deletion src/Symfony/Component/Form/Extension/Core/Type/CurrencyType.php
Expand Up @@ -14,7 +14,9 @@
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\ChoiceList\ArrayChoiceList;
use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface;
use Symfony\Component\Form\ChoiceList\Loader\IntlCallbackChoiceLoader;
use Symfony\Component\Intl\Intl;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;

class CurrencyType extends AbstractType implements ChoiceLoaderInterface
Expand All @@ -27,6 +29,8 @@ class CurrencyType extends AbstractType implements ChoiceLoaderInterface
* {@link \Symfony\Component\Intl\Intl::getCurrencyBundle()}.
*
* @var ArrayChoiceList
*
* @deprecated since Symfony 4.1
*/
private $choiceList;

Expand All @@ -36,9 +40,18 @@ class CurrencyType extends AbstractType implements ChoiceLoaderInterface
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'choice_loader' => $this,
'choice_loader' => function (Options $options) {
$choiceTranslationLocale = $options['choice_translation_locale'];

return new IntlCallbackChoiceLoader(function () use ($choiceTranslationLocale) {
return array_flip(Intl::getCurrencyBundle()->getCurrencyNames($choiceTranslationLocale));
});
},
'choice_translation_domain' => false,
'choice_translation_locale' => null,
));

$resolver->setAllowedTypes('choice_translation_locale', array('null', 'string'));
}

/**
Expand All @@ -59,9 +72,13 @@ public function getBlockPrefix()

/**
* {@inheritdoc}
*
* @deprecated since Symfony 4.1
*/
public function loadChoiceList($value = null)
{
@trigger_error(sprintf('Method "%s" is deprecated since Symfony 4.1, use "choice_loader" option instead.', __METHOD__), E_USER_DEPRECATED);

if (null !== $this->choiceList) {
return $this->choiceList;
}
Expand All @@ -71,9 +88,13 @@ public function loadChoiceList($value = null)

/**
* {@inheritdoc}
*
* @deprecated since Symfony 4.1
*/
public function loadChoicesForValues(array $values, $value = null)
{
@trigger_error(sprintf('Method "%s" is deprecated since Symfony 4.1, use "choice_loader" option instead.', __METHOD__), E_USER_DEPRECATED);

// Optimize
$values = array_filter($values);
if (empty($values)) {
Expand All @@ -90,9 +111,13 @@ public function loadChoicesForValues(array $values, $value = null)

/**
* {@inheritdoc}
*
* @deprecated since Symfony 4.1
*/
public function loadValuesForChoices(array $choices, $value = null)
{
@trigger_error(sprintf('Method "%s" is deprecated since Symfony 4.1, use "choice_loader" option instead.', __METHOD__), E_USER_DEPRECATED);

// Optimize
$choices = array_filter($choices);
if (empty($choices)) {
Expand Down
27 changes: 26 additions & 1 deletion src/Symfony/Component/Form/Extension/Core/Type/LanguageType.php
Expand Up @@ -14,7 +14,9 @@
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\ChoiceList\ArrayChoiceList;
use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface;
use Symfony\Component\Form\ChoiceList\Loader\IntlCallbackChoiceLoader;
use Symfony\Component\Intl\Intl;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;

class LanguageType extends AbstractType implements ChoiceLoaderInterface
Expand All @@ -27,6 +29,8 @@ class LanguageType extends AbstractType implements ChoiceLoaderInterface
* {@link \Symfony\Component\Intl\Intl::getLanguageBundle()}.
*
* @var ArrayChoiceList
*
* @deprecated since Symfony 4.1
*/
private $choiceList;

Expand All @@ -36,9 +40,18 @@ class LanguageType extends AbstractType implements ChoiceLoaderInterface
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'choice_loader' => $this,
'choice_loader' => function (Options $options) {
$choiceTranslationLocale = $options['choice_translation_locale'];

return new IntlCallbackChoiceLoader(function () use ($choiceTranslationLocale) {
return array_flip(Intl::getLanguageBundle()->getLanguageNames($choiceTranslationLocale));
});
},
'choice_translation_domain' => false,
'choice_translation_locale' => null,
));

$resolver->setAllowedTypes('choice_translation_locale', array('null', 'string'));
}

/**
Expand All @@ -59,9 +72,13 @@ public function getBlockPrefix()

/**
* {@inheritdoc}
*
* @deprecated since Symfony 4.1
*/
public function loadChoiceList($value = null)
{
@trigger_error(sprintf('Method "%s" is deprecated since Symfony 4.1, use "choice_loader" option instead.', __METHOD__), E_USER_DEPRECATED);

if (null !== $this->choiceList) {
return $this->choiceList;
}
Expand All @@ -71,9 +88,13 @@ public function loadChoiceList($value = null)

/**
* {@inheritdoc}
*
* @deprecated since Symfony 4.1
*/
public function loadChoicesForValues(array $values, $value = null)
{
@trigger_error(sprintf('Method "%s" is deprecated since Symfony 4.1, use "choice_loader" option instead.', __METHOD__), E_USER_DEPRECATED);

// Optimize
$values = array_filter($values);
if (empty($values)) {
Expand All @@ -90,9 +111,13 @@ public function loadChoicesForValues(array $values, $value = null)

/**
* {@inheritdoc}
*
* @deprecated since Symfony 4.1
*/
public function loadValuesForChoices(array $choices, $value = null)
{
@trigger_error(sprintf('Method "%s" is deprecated since Symfony 4.1, use "choice_loader" option instead.', __METHOD__), E_USER_DEPRECATED);

// Optimize
$choices = array_filter($choices);
if (empty($choices)) {
Expand Down

0 comments on commit 2ceef59

Please sign in to comment.