Skip to content

Commit

Permalink
feature #18332 [Form] added CallbackChoiceLoader and refactored Cho…
Browse files Browse the repository at this point in the history
…iceType's children (HeahDude)

This PR was merged into the 3.2-dev branch.

Discussion
----------

[Form] added `CallbackChoiceLoader` and refactored ChoiceType's children

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | ~
| License       | MIT
| Doc PR        | todo

Todo
====
- [ ] Address a doc PR
- [x] Update CHANGELOG

Changes
=======
 - 39e937f added `CallbackChoiceLoader` to lazy load choices with a simple callable.

 - 995dc56 refactored `CountryType`, `CurrencyType`, `LanguageType`, `LocaleType` and `TimezoneType` for better performance by implementing `ChoiceLoaderInterface` for lazy loading.

Usage
=====
```php
use Symfony\Component\Form\ChoiceList\Loader\CallbackChoiceLoader;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;

$builder->add('constants', ChoiceType::class, array(
    'choice_loader' => new CallbackChoiceLoader(function() {
            return StaticClass::getConstants();
    },
));
```

Commits
-------

8a4e164 [Form] implemented ChoiceLoaderInterface in children of ChoiceType
afd7bf8 [Form] added `CallbackChoiceLoader`
  • Loading branch information
fabpot committed Jun 13, 2016
2 parents e707760 + 8a4e164 commit 1dcc86d
Show file tree
Hide file tree
Showing 8 changed files with 511 additions and 38 deletions.
6 changes: 6 additions & 0 deletions src/Symfony/Component/Form/CHANGELOG.md
@@ -1,6 +1,12 @@
CHANGELOG
=========

3.2.0
-----

* added `CallbackChoiceLoader`
* implemented `ChoiceLoaderInterface` in children of `ChoiceType`

3.1.0
-----

Expand Down
@@ -0,0 +1,77 @@
<?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;

use Symfony\Component\Form\ChoiceList\ArrayChoiceList;

/**
* Loads an {@link ArrayChoiceList} instance from a callable returning an array of choices.
*
* @author Jules Pietri <jules@heahprod.com>
*/
class CallbackChoiceLoader implements ChoiceLoaderInterface
{
private $callback;

/**
* The loaded choice list.
*
* @var ArrayChoiceList
*/
private $choiceList;

/**
* @param callable $callback The callable returning an array of choices
*/
public function __construct(callable $callback)
{
$this->callback = $callback;
}

/**
* {@inheritdoc}
*/
public function loadChoiceList($value = null)
{
if (null !== $this->choiceList) {
return $this->choiceList;
}

return $this->choiceList = new ArrayChoiceList(call_user_func($this->callback), $value);
}

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

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

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

return $this->loadChoiceList($value)->getValuesForChoices($choices);
}
}
65 changes: 63 additions & 2 deletions src/Symfony/Component/Form/Extension/Core/Type/CountryType.php
Expand Up @@ -12,18 +12,31 @@
namespace Symfony\Component\Form\Extension\Core\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\ChoiceList\ArrayChoiceList;
use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface;
use Symfony\Component\Intl\Intl;
use Symfony\Component\OptionsResolver\OptionsResolver;

class CountryType extends AbstractType
class CountryType extends AbstractType implements ChoiceLoaderInterface
{
/**
* Country loaded choice list.
*
* The choices are lazy loaded and generated from the Intl component.
*
* {@link \Symfony\Component\Intl\Intl::getRegionBundle()}.
*
* @var ArrayChoiceList
*/
private $choiceList;

/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'choices' => array_flip(Intl::getRegionBundle()->getCountryNames()),
'choice_loader' => $this,
'choice_translation_domain' => false,
));
}
Expand All @@ -43,4 +56,52 @@ public function getBlockPrefix()
{
return 'country';
}

/**
* {@inheritdoc}
*/
public function loadChoiceList($value = null)
{
if (null !== $this->choiceList) {
return $this->choiceList;
}

return $this->choiceList = new ArrayChoiceList(array_flip(Intl::getRegionBundle()->getCountryNames()), $value);
}

/**
* {@inheritdoc}
*/
public function loadChoicesForValues(array $values, $value = null)
{
// Optimize
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
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);
}
}
65 changes: 63 additions & 2 deletions src/Symfony/Component/Form/Extension/Core/Type/CurrencyType.php
Expand Up @@ -12,18 +12,31 @@
namespace Symfony\Component\Form\Extension\Core\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\ChoiceList\ArrayChoiceList;
use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface;
use Symfony\Component\Intl\Intl;
use Symfony\Component\OptionsResolver\OptionsResolver;

class CurrencyType extends AbstractType
class CurrencyType extends AbstractType implements ChoiceLoaderInterface
{
/**
* Currency loaded choice list.
*
* The choices are lazy loaded and generated from the Intl component.
*
* {@link \Symfony\Component\Intl\Intl::getCurrencyBundle()}.
*
* @var ArrayChoiceList
*/
private $choiceList;

/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'choices' => array_flip(Intl::getCurrencyBundle()->getCurrencyNames()),
'choice_loader' => $this,
'choice_translation_domain' => false,
));
}
Expand All @@ -43,4 +56,52 @@ public function getBlockPrefix()
{
return 'currency';
}

/**
* {@inheritdoc}
*/
public function loadChoiceList($value = null)
{
if (null !== $this->choiceList) {
return $this->choiceList;
}

return $this->choiceList = new ArrayChoiceList(array_flip(Intl::getCurrencyBundle()->getCurrencyNames()), $value);
}

/**
* {@inheritdoc}
*/
public function loadChoicesForValues(array $values, $value = null)
{
// Optimize
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
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);
}
}
65 changes: 63 additions & 2 deletions src/Symfony/Component/Form/Extension/Core/Type/LanguageType.php
Expand Up @@ -12,18 +12,31 @@
namespace Symfony\Component\Form\Extension\Core\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\ChoiceList\ArrayChoiceList;
use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface;
use Symfony\Component\Intl\Intl;
use Symfony\Component\OptionsResolver\OptionsResolver;

class LanguageType extends AbstractType
class LanguageType extends AbstractType implements ChoiceLoaderInterface
{
/**
* Language loaded choice list.
*
* The choices are lazy loaded and generated from the Intl component.
*
* {@link \Symfony\Component\Intl\Intl::getLanguageBundle()}.
*
* @var ArrayChoiceList
*/
private $choiceList;

/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'choices' => array_flip(Intl::getLanguageBundle()->getLanguageNames()),
'choice_loader' => $this,
'choice_translation_domain' => false,
));
}
Expand All @@ -43,4 +56,52 @@ public function getBlockPrefix()
{
return 'language';
}

/**
* {@inheritdoc}
*/
public function loadChoiceList($value = null)
{
if (null !== $this->choiceList) {
return $this->choiceList;
}

return $this->choiceList = new ArrayChoiceList(array_flip(Intl::getLanguageBundle()->getLanguageNames()), $value);
}

/**
* {@inheritdoc}
*/
public function loadChoicesForValues(array $values, $value = null)
{
// Optimize
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
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);
}
}

0 comments on commit 1dcc86d

Please sign in to comment.