feature #30985 [Form] Keep preferred choices order in ChoiceType (vudaltsov)
This PR was merged into the 4.3-dev branch.
Discussion
----------
[Form] Keep preferred choices order in ChoiceType
| Q | A
| ------------- | ---
| Branch? | master
| Bug fix? | no
| New feature? | yes
| BC breaks? | no
| Deprecations? | no
| Tests pass? | yes
| Fixed tickets | #5136
| License | MIT
| Doc PR | todo
#EUFOSSA
Commits
-------
340a2fb3f8
Keep preferred_choices order
This commit is contained in:
commit
d4baa71af6
@ -48,13 +48,16 @@ class DefaultChoiceListFactory implements ChoiceListFactoryInterface
|
|||||||
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)
|
||||||
{
|
{
|
||||||
$preferredViews = [];
|
$preferredViews = [];
|
||||||
|
$preferredViewsOrder = [];
|
||||||
$otherViews = [];
|
$otherViews = [];
|
||||||
$choices = $list->getChoices();
|
$choices = $list->getChoices();
|
||||||
$keys = $list->getOriginalKeys();
|
$keys = $list->getOriginalKeys();
|
||||||
|
|
||||||
if (!\is_callable($preferredChoices) && !empty($preferredChoices)) {
|
if (!\is_callable($preferredChoices) && !empty($preferredChoices)) {
|
||||||
$preferredChoices = function ($choice) use ($preferredChoices) {
|
// make sure we have keys that reflect order
|
||||||
return \in_array($choice, $preferredChoices, true);
|
$preferredChoices = array_values($preferredChoices);
|
||||||
|
$preferredChoices = static function ($choice) use ($preferredChoices) {
|
||||||
|
return array_search($choice, $preferredChoices, true);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,6 +83,7 @@ class DefaultChoiceListFactory implements ChoiceListFactoryInterface
|
|||||||
$attr,
|
$attr,
|
||||||
$preferredChoices,
|
$preferredChoices,
|
||||||
$preferredViews,
|
$preferredViews,
|
||||||
|
$preferredViewsOrder,
|
||||||
$otherViews
|
$otherViews
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -108,14 +112,21 @@ class DefaultChoiceListFactory implements ChoiceListFactoryInterface
|
|||||||
$attr,
|
$attr,
|
||||||
$preferredChoices,
|
$preferredChoices,
|
||||||
$preferredViews,
|
$preferredViews,
|
||||||
|
$preferredViewsOrder,
|
||||||
$otherViews
|
$otherViews
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uksort($preferredViews, static function ($a, $b) use ($preferredViewsOrder): int {
|
||||||
|
return isset($preferredViewsOrder[$a], $preferredViewsOrder[$b])
|
||||||
|
? $preferredViewsOrder[$a] <=> $preferredViewsOrder[$b]
|
||||||
|
: 0;
|
||||||
|
});
|
||||||
|
|
||||||
return new ChoiceListView($otherViews, $preferredViews);
|
return new ChoiceListView($otherViews, $preferredViews);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function addChoiceView($choice, $value, $label, $keys, &$index, $attr, $isPreferred, &$preferredViews, &$otherViews)
|
private static function addChoiceView($choice, $value, $label, $keys, &$index, $attr, $isPreferred, &$preferredViews, &$preferredViewsOrder, &$otherViews)
|
||||||
{
|
{
|
||||||
// $value may be an integer or a string, since it's stored in the array
|
// $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.
|
// keys. We want to guarantee it's a string though.
|
||||||
@ -143,14 +154,15 @@ class DefaultChoiceListFactory implements ChoiceListFactoryInterface
|
|||||||
);
|
);
|
||||||
|
|
||||||
// $isPreferred may be null if no choices are preferred
|
// $isPreferred may be null if no choices are preferred
|
||||||
if ($isPreferred && $isPreferred($choice, $key, $value)) {
|
if ($isPreferred && false !== $preferredKey = $isPreferred($choice, $key, $value)) {
|
||||||
$preferredViews[$nextIndex] = $view;
|
$preferredViews[$nextIndex] = $view;
|
||||||
|
$preferredViewsOrder[$nextIndex] = $preferredKey;
|
||||||
} else {
|
} else {
|
||||||
$otherViews[$nextIndex] = $view;
|
$otherViews[$nextIndex] = $view;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function addChoiceViewsFromStructuredValues($values, $label, $choices, $keys, &$index, $attr, $isPreferred, &$preferredViews, &$otherViews)
|
private static function addChoiceViewsFromStructuredValues($values, $label, $choices, $keys, &$index, $attr, $isPreferred, &$preferredViews, &$preferredViewsOrder, &$otherViews)
|
||||||
{
|
{
|
||||||
foreach ($values as $key => $value) {
|
foreach ($values as $key => $value) {
|
||||||
if (null === $value) {
|
if (null === $value) {
|
||||||
@ -171,6 +183,7 @@ class DefaultChoiceListFactory implements ChoiceListFactoryInterface
|
|||||||
$attr,
|
$attr,
|
||||||
$isPreferred,
|
$isPreferred,
|
||||||
$preferredViewsForGroup,
|
$preferredViewsForGroup,
|
||||||
|
$preferredViewsOrder,
|
||||||
$otherViewsForGroup
|
$otherViewsForGroup
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -195,12 +208,13 @@ class DefaultChoiceListFactory implements ChoiceListFactoryInterface
|
|||||||
$attr,
|
$attr,
|
||||||
$isPreferred,
|
$isPreferred,
|
||||||
$preferredViews,
|
$preferredViews,
|
||||||
|
$preferredViewsOrder,
|
||||||
$otherViews
|
$otherViews
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function addChoiceViewsGroupedByCallable($groupBy, $choice, $value, $label, $keys, &$index, $attr, $isPreferred, &$preferredViews, &$otherViews)
|
private static function addChoiceViewsGroupedByCallable($groupBy, $choice, $value, $label, $keys, &$index, $attr, $isPreferred, &$preferredViews, &$preferredViewsOrder, &$otherViews)
|
||||||
{
|
{
|
||||||
$groupLabels = $groupBy($choice, $keys[$value], $value);
|
$groupLabels = $groupBy($choice, $keys[$value], $value);
|
||||||
|
|
||||||
@ -215,6 +229,7 @@ class DefaultChoiceListFactory implements ChoiceListFactoryInterface
|
|||||||
$attr,
|
$attr,
|
||||||
$isPreferred,
|
$isPreferred,
|
||||||
$preferredViews,
|
$preferredViews,
|
||||||
|
$preferredViewsOrder,
|
||||||
$otherViews
|
$otherViews
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -240,6 +255,7 @@ class DefaultChoiceListFactory implements ChoiceListFactoryInterface
|
|||||||
$attr,
|
$attr,
|
||||||
$isPreferred,
|
$isPreferred,
|
||||||
$preferredViews[$groupLabel]->choices,
|
$preferredViews[$groupLabel]->choices,
|
||||||
|
$preferredViewsOrder,
|
||||||
$otherViews[$groupLabel]->choices
|
$otherViews[$groupLabel]->choices
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -234,6 +234,28 @@ class DefaultChoiceListFactoryTest extends TestCase
|
|||||||
$this->assertFlatView($view);
|
$this->assertFlatView($view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testCreateViewFlatPreferredChoicesSameOrder()
|
||||||
|
{
|
||||||
|
$view = $this->factory->createView(
|
||||||
|
$this->list,
|
||||||
|
[$this->obj2, $this->obj1, $this->obj4, $this->obj3]
|
||||||
|
);
|
||||||
|
|
||||||
|
$preferredLabels = array_map(static function (ChoiceView $view): string {
|
||||||
|
return $view->label;
|
||||||
|
}, $view->preferredChoices);
|
||||||
|
|
||||||
|
$this->assertSame(
|
||||||
|
[
|
||||||
|
1 => 'B',
|
||||||
|
0 => 'A',
|
||||||
|
3 => 'D',
|
||||||
|
2 => 'C',
|
||||||
|
],
|
||||||
|
$preferredLabels
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function testCreateViewFlatPreferredChoicesEmptyArray()
|
public function testCreateViewFlatPreferredChoicesEmptyArray()
|
||||||
{
|
{
|
||||||
$view = $this->factory->createView(
|
$view = $this->factory->createView(
|
||||||
|
Reference in New Issue
Block a user