Skip to content

Commit

Permalink
[Form] Add "choice_translation_parameters" option
Browse files Browse the repository at this point in the history
  • Loading branch information
VincentLanglet authored and fabpot committed Dec 10, 2020
1 parent 9d40bd8 commit 1ce5b03
Show file tree
Hide file tree
Showing 15 changed files with 322 additions and 81 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@
{{- block('choice_widget_options') -}}
</optgroup>
{%- else -%}
<option value="{{ choice.value }}"{% if choice.attr %}{% with { attr: choice.attr } %}{{ block('attributes') }}{% endwith %}{% endif %}{% if not render_preferred_choices|default(false) and choice is selectedchoice(value) %} selected="selected"{% endif %}>{{ choice_translation_domain is same as(false) ? choice.label : choice.label|trans({}, choice_translation_domain) }}</option>
<option value="{{ choice.value }}"{% if choice.attr %}{% with { attr: choice.attr } %}{{ block('attributes') }}{% endwith %}{% endif %}{% if not render_preferred_choices|default(false) and choice is selectedchoice(value) %} selected="selected"{% endif %}>{{ choice_translation_domain is same as(false) ? choice.label : choice.label|trans(choice.labelTranslationParameters, choice_translation_domain) }}</option>
{%- endif -%}
{% endfor %}
{%- endblock choice_widget_options -%}
Expand Down
4 changes: 2 additions & 2 deletions src/Symfony/Bridge/Twig/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"symfony/asset": "^4.4|^5.0",
"symfony/dependency-injection": "^4.4|^5.0",
"symfony/finder": "^4.4|^5.0",
"symfony/form": "^5.1.9",
"symfony/form": "^5.3",
"symfony/http-foundation": "^4.4|^5.0",
"symfony/http-kernel": "^4.4|^5.0",
"symfony/mime": "^5.2",
Expand All @@ -52,7 +52,7 @@
},
"conflict": {
"symfony/console": "<4.4",
"symfony/form": "<5.1",
"symfony/form": "<5.3",
"symfony/http-foundation": "<4.4",
"symfony/http-kernel": "<4.4",
"symfony/translation": "<5.2",
Expand Down
1 change: 1 addition & 0 deletions src/Symfony/Component/Form/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ CHANGELOG
* Deprecated passing an array as the first argument of the `CheckboxListMapper::mapFormsToData()` method, pass `\Traversable` instead.
* Deprecated passing an array as the second argument of the `RadioListMapper::mapDataToForms()` method, pass `\Traversable` instead.
* Deprecated passing an array as the first argument of the `RadioListMapper::mapFormsToData()` method, pass `\Traversable` instead.
* Added a `choice_translation_parameters` option to `ChoiceType`

5.2.0
-----
Expand Down
13 changes: 13 additions & 0 deletions src/Symfony/Component/Form/ChoiceList/ChoiceList.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use Symfony\Component\Form\ChoiceList\Factory\Cache\ChoiceFilter;
use Symfony\Component\Form\ChoiceList\Factory\Cache\ChoiceLabel;
use Symfony\Component\Form\ChoiceList\Factory\Cache\ChoiceLoader;
use Symfony\Component\Form\ChoiceList\Factory\Cache\ChoiceTranslationParameters;
use Symfony\Component\Form\ChoiceList\Factory\Cache\ChoiceValue;
use Symfony\Component\Form\ChoiceList\Factory\Cache\GroupBy;
use Symfony\Component\Form\ChoiceList\Factory\Cache\PreferredChoice;
Expand Down Expand Up @@ -113,6 +114,18 @@ public static function attr($formType, $attr, $vary = null): ChoiceAttr
return new ChoiceAttr($formType, $attr, $vary);
}

/**
* Decorates a "choice_translation_parameters" option to make it cacheable.
*
* @param FormTypeInterface|FormTypeExtensionInterface $formType A form type or type extension configuring a cacheable choice list
* @param callable|array $translationParameters Any pseudo callable or array to create translation parameters from a choice
* @param mixed|null $vary Dynamic data used to compute a unique hash when caching the option
*/
public static function translationParameters($formType, $translationParameters, $vary = null): ChoiceTranslationParameters
{
return new ChoiceTranslationParameters($formType, $translationParameters, $vary);
}

/**
* Decorates a "group_by" callback to make it cacheable.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?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\Factory\Cache;

use Symfony\Component\Form\FormTypeExtensionInterface;
use Symfony\Component\Form\FormTypeInterface;

/**
* A cacheable wrapper for any {@see FormTypeInterface} or {@see FormTypeExtensionInterface}
* which configures a "choice_translation_parameters" option.
*
* @internal
*
* @author Vincent Langlet <vincentlanglet@users.noreply.github.com>
*/
final class ChoiceTranslationParameters extends AbstractStaticOption
{
}
Original file line number Diff line number Diff line change
Expand Up @@ -174,14 +174,16 @@ public function createListFromLoader(ChoiceLoaderInterface $loader, $value = nul
/**
* {@inheritdoc}
*
* @param array|callable|Cache\PreferredChoice|null $preferredChoices The preferred choices
* @param callable|false|Cache\ChoiceLabel|null $label The option or static option generating the choice labels
* @param callable|Cache\ChoiceFieldName|null $index The option or static option generating the view indices
* @param callable|Cache\GroupBy|null $groupBy The option or static option generating the group names
* @param array|callable|Cache\ChoiceAttr|null $attr The option or static option generating the HTML attributes
* @param array|callable|Cache\PreferredChoice|null $preferredChoices The preferred choices
* @param callable|false|Cache\ChoiceLabel|null $label The option or static option generating the choice labels
* @param callable|Cache\ChoiceFieldName|null $index The option or static option generating the view indices
* @param callable|Cache\GroupBy|null $groupBy The option or static option generating the group names
* @param array|callable|Cache\ChoiceAttr|null $attr The option or static option generating the HTML attributes
* @param array|callable|Cache\ChoiceTranslationParameters $labelTranslationParameters The parameters used to translate the choice labels
*/
public function createView(ChoiceListInterface $list, $preferredChoices = null, $label = null, $index = null, $groupBy = null, $attr = null)
public function createView(ChoiceListInterface $list, $preferredChoices = null, $label = null, $index = null, $groupBy = null, $attr = null/*, $labelTranslationParameters = []*/)
{
$labelTranslationParameters = \func_num_args() > 6 ? func_get_arg(6) : [];
$cache = true;

if ($preferredChoices instanceof Cache\PreferredChoice) {
Expand Down Expand Up @@ -214,11 +216,25 @@ public function createView(ChoiceListInterface $list, $preferredChoices = null,
$cache = false;
}

if ($labelTranslationParameters instanceof Cache\ChoiceTranslationParameters) {
$labelTranslationParameters = $labelTranslationParameters->getOption();
} elseif ([] !== $labelTranslationParameters) {
$cache = false;
}

if (!$cache) {
return $this->decoratedFactory->createView($list, $preferredChoices, $label, $index, $groupBy, $attr);
return $this->decoratedFactory->createView(
$list,
$preferredChoices,
$label,
$index,
$groupBy,
$attr,
$labelTranslationParameters
);
}

$hash = self::generateHash([$list, $preferredChoices, $label, $index, $groupBy, $attr]);
$hash = self::generateHash([$list, $preferredChoices, $label, $index, $groupBy, $attr, $labelTranslationParameters]);

if (!isset($this->views[$hash])) {
$this->views[$hash] = $this->decoratedFactory->createView(
Expand All @@ -227,7 +243,8 @@ public function createView(ChoiceListInterface $list, $preferredChoices = null,
$label,
$index,
$groupBy,
$attr
$attr,
$labelTranslationParameters
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,13 @@ public function createListFromLoader(ChoiceLoaderInterface $loader, callable $va
* match the keys of the choices. The values should be arrays of HTML
* attributes that should be added to the respective choice.
*
* @param array|callable|null $preferredChoices The preferred choices
* @param callable|false|null $label The callable generating the choice labels;
* pass false to discard the label
* @param array|callable|null $attr The callable generating the HTML attributes
* @param array|callable|null $preferredChoices The preferred choices
* @param callable|false|null $label The callable generating the choice labels;
* pass false to discard the label
* @param array|callable|null $attr The callable generating the HTML attributes
* @param array|callable $labelTranslationParameters The parameters used to translate the choice labels
*
* @return ChoiceListView The choice list view
*/
public function createView(ChoiceListInterface $list, $preferredChoices = null, $label = null, callable $index = null, callable $groupBy = null, $attr = null);
public function createView(ChoiceListInterface $list, $preferredChoices = null, $label = null, callable $index = null, callable $groupBy = null, $attr = null/*, $labelTranslationParameters = []*/);
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,12 @@ public function createListFromLoader(ChoiceLoaderInterface $loader, callable $va

/**
* {@inheritdoc}
*
* @param array|callable $labelTranslationParameters The parameters used to translate the choice labels
*/
public function createView(ChoiceListInterface $list, $preferredChoices = null, $label = null, callable $index = null, callable $groupBy = null, $attr = null)
public function createView(ChoiceListInterface $list, $preferredChoices = null, $label = null, callable $index = null, callable $groupBy = null, $attr = null/*, $labelTranslationParameters = []*/)
{
$labelTranslationParameters = \func_num_args() > 6 ? func_get_arg(6) : [];
$preferredViews = [];
$preferredViewsOrder = [];
$otherViews = [];
Expand Down Expand Up @@ -109,6 +112,7 @@ public function createView(ChoiceListInterface $list, $preferredChoices = null,
$keys,
$index,
$attr,
$labelTranslationParameters,
$preferredChoices,
$preferredViews,
$preferredViewsOrder,
Expand Down Expand Up @@ -146,6 +150,7 @@ public function createView(ChoiceListInterface $list, $preferredChoices = null,
$keys,
$index,
$attr,
$labelTranslationParameters,
$preferredChoices,
$preferredViews,
$preferredViewsOrder,
Expand All @@ -162,7 +167,7 @@ public function createView(ChoiceListInterface $list, $preferredChoices = null,
return new ChoiceListView($otherViews, $preferredViews);
}

private static function addChoiceView($choice, string $value, $label, array $keys, &$index, $attr, ?callable $isPreferred, array &$preferredViews, array &$preferredViewsOrder, array &$otherViews)
private static function addChoiceView($choice, string $value, $label, array $keys, &$index, $attr, $labelTranslationParameters, ?callable $isPreferred, array &$preferredViews, array &$preferredViewsOrder, array &$otherViews)
{
// $value may be an integer or a string, since it's stored in the array
// keys. We want to guarantee it's a string though.
Expand All @@ -186,7 +191,10 @@ private static function addChoiceView($choice, string $value, $label, array $key
$label,
// The attributes may be a callable or a mapping from choice indices
// to nested arrays
\is_callable($attr) ? $attr($choice, $key, $value) : (isset($attr[$key]) ? $attr[$key] : [])
\is_callable($attr) ? $attr($choice, $key, $value) : ($attr[$key] ?? []),
// The label translation parameters may be a callable or a mapping from choice indices
// to nested arrays
\is_callable($labelTranslationParameters) ? $labelTranslationParameters($choice, $key, $value) : ($labelTranslationParameters[$key] ?? [])
);

// $isPreferred may be null if no choices are preferred
Expand All @@ -198,7 +206,7 @@ private static function addChoiceView($choice, string $value, $label, array $key
$otherViews[$nextIndex] = $view;
}

private static function addChoiceViewsFromStructuredValues(array $values, $label, array $choices, array $keys, &$index, $attr, ?callable $isPreferred, array &$preferredViews, array &$preferredViewsOrder, array &$otherViews)
private static function addChoiceViewsFromStructuredValues(array $values, $label, array $choices, array $keys, &$index, $attr, $labelTranslationParameters, ?callable $isPreferred, array &$preferredViews, array &$preferredViewsOrder, array &$otherViews)
{
foreach ($values as $key => $value) {
if (null === $value) {
Expand All @@ -217,6 +225,7 @@ private static function addChoiceViewsFromStructuredValues(array $values, $label
$keys,
$index,
$attr,
$labelTranslationParameters,
$isPreferred,
$preferredViewsForGroup,
$preferredViewsOrder,
Expand All @@ -242,6 +251,7 @@ private static function addChoiceViewsFromStructuredValues(array $values, $label
$keys,
$index,
$attr,
$labelTranslationParameters,
$isPreferred,
$preferredViews,
$preferredViewsOrder,
Expand All @@ -250,7 +260,7 @@ private static function addChoiceViewsFromStructuredValues(array $values, $label
}
}

private static function addChoiceViewsGroupedByCallable(callable $groupBy, $choice, string $value, $label, array $keys, &$index, $attr, ?callable $isPreferred, array &$preferredViews, array &$preferredViewsOrder, array &$otherViews)
private static function addChoiceViewsGroupedByCallable(callable $groupBy, $choice, string $value, $label, array $keys, &$index, $attr, $labelTranslationParameters, ?callable $isPreferred, array &$preferredViews, array &$preferredViewsOrder, array &$otherViews)
{
$groupLabels = $groupBy($choice, $keys[$value], $value);

Expand All @@ -263,6 +273,7 @@ private static function addChoiceViewsGroupedByCallable(callable $groupBy, $choi
$keys,
$index,
$attr,
$labelTranslationParameters,
$isPreferred,
$preferredViews,
$preferredViewsOrder,
Expand Down Expand Up @@ -292,6 +303,7 @@ private static function addChoiceViewsGroupedByCallable(callable $groupBy, $choi
$keys,
$index,
$attr,
$labelTranslationParameters,
$isPreferred,
$preferredViews[$groupLabel]->choices,
$preferredViewsOrder[$groupLabel],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,16 +145,18 @@ public function createListFromLoader(ChoiceLoaderInterface $loader, $value = nul
/**
* {@inheritdoc}
*
* @param array|callable|string|PropertyPath|null $preferredChoices The preferred choices
* @param callable|string|PropertyPath|null $label The callable or path generating the choice labels
* @param callable|string|PropertyPath|null $index The callable or path generating the view indices
* @param callable|string|PropertyPath|null $groupBy The callable or path generating the group names
* @param array|callable|string|PropertyPath|null $attr The callable or path generating the HTML attributes
* @param array|callable|string|PropertyPath|null $preferredChoices The preferred choices
* @param callable|string|PropertyPath|null $label The callable or path generating the choice labels
* @param callable|string|PropertyPath|null $index The callable or path generating the view indices
* @param callable|string|PropertyPath|null $groupBy The callable or path generating the group names
* @param array|callable|string|PropertyPath|null $attr The callable or path generating the HTML attributes
* @param array|callable|string|PropertyPath $labelTranslationParameters The callable or path generating the parameters used to translate the choice labels
*
* @return ChoiceListView The choice list view
*/
public function createView(ChoiceListInterface $list, $preferredChoices = null, $label = null, $index = null, $groupBy = null, $attr = null)
public function createView(ChoiceListInterface $list, $preferredChoices = null, $label = null, $index = null, $groupBy = null, $attr = null/*, $labelTranslationParameters = []*/)
{
$labelTranslationParameters = \func_num_args() > 6 ? func_get_arg(6) : [];
$accessor = $this->propertyAccessor;

if (\is_string($label)) {
Expand Down Expand Up @@ -217,6 +219,24 @@ public function createView(ChoiceListInterface $list, $preferredChoices = null,
};
}

return $this->decoratedFactory->createView($list, $preferredChoices, $label, $index, $groupBy, $attr);
if (\is_string($labelTranslationParameters)) {
$labelTranslationParameters = new PropertyPath($labelTranslationParameters);
}

if ($labelTranslationParameters instanceof PropertyPath) {
$labelTranslationParameters = static function ($choice) use ($accessor, $labelTranslationParameters) {
return $accessor->getValue($choice, $labelTranslationParameters);
};
}

return $this->decoratedFactory->createView(
$list,
$preferredChoices,
$label,
$index,
$groupBy,
$attr,
$labelTranslationParameters
);
}
}
17 changes: 12 additions & 5 deletions src/Symfony/Component/Form/ChoiceList/View/ChoiceView.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,26 @@ class ChoiceView
*/
public $attr;

/**
* Additional parameters used to translate the label.
*/
public $labelTranslationParameters;

/**
* Creates a new choice view.
*
* @param mixed $data The original choice
* @param string $value The view representation of the choice
* @param string|false $label The label displayed to humans; pass false to discard the label
* @param array $attr Additional attributes for the HTML tag
* @param mixed $data The original choice
* @param string $value The view representation of the choice
* @param string|false $label The label displayed to humans; pass false to discard the label
* @param array $attr Additional attributes for the HTML tag
* @param array $labelTranslationParameters Additional parameters used to translate the label
*/
public function __construct($data, string $value, $label, array $attr = [])
public function __construct($data, string $value, $label, array $attr = [], array $labelTranslationParameters = [])
{
$this->data = $data;
$this->value = $value;
$this->label = $label;
$this->attr = $attr;
$this->labelTranslationParameters = $labelTranslationParameters;
}
}

0 comments on commit 1ce5b03

Please sign in to comment.