diff --git a/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php b/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php index c4681fe20baa8..e7100d22374c5 100644 --- a/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php +++ b/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php @@ -48,13 +48,16 @@ public function createListFromLoader(ChoiceLoaderInterface $loader, $value = nul public function createView(ChoiceListInterface $list, $preferredChoices = null, $label = null, $index = null, $groupBy = null, $attr = null) { $preferredViews = []; + $preferredViewsOrder = []; $otherViews = []; $choices = $list->getChoices(); $keys = $list->getOriginalKeys(); if (!\is_callable($preferredChoices) && !empty($preferredChoices)) { - $preferredChoices = function ($choice) use ($preferredChoices) { - return \in_array($choice, $preferredChoices, true); + // make sure we have keys that reflect order + $preferredChoices = array_values($preferredChoices); + $preferredChoices = static function ($choice) use ($preferredChoices) { + return array_search($choice, $preferredChoices, true); }; } @@ -80,6 +83,7 @@ public function createView(ChoiceListInterface $list, $preferredChoices = null, $attr, $preferredChoices, $preferredViews, + $preferredViewsOrder, $otherViews ); } @@ -108,14 +112,21 @@ public function createView(ChoiceListInterface $list, $preferredChoices = null, $attr, $preferredChoices, $preferredViews, + $preferredViewsOrder, $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); } - 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 // keys. We want to guarantee it's a string though. @@ -143,14 +154,15 @@ private static function addChoiceView($choice, $value, $label, $keys, &$index, $ ); // $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; + $preferredViewsOrder[$nextIndex] = $preferredKey; } else { $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) { if (null === $value) { @@ -171,6 +183,7 @@ private static function addChoiceViewsFromStructuredValues($values, $label, $cho $attr, $isPreferred, $preferredViewsForGroup, + $preferredViewsOrder, $otherViewsForGroup ); @@ -195,12 +208,13 @@ private static function addChoiceViewsFromStructuredValues($values, $label, $cho $attr, $isPreferred, $preferredViews, + $preferredViewsOrder, $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); @@ -215,6 +229,7 @@ private static function addChoiceViewsGroupedByCallable($groupBy, $choice, $valu $attr, $isPreferred, $preferredViews, + $preferredViewsOrder, $otherViews ); @@ -240,6 +255,7 @@ private static function addChoiceViewsGroupedByCallable($groupBy, $choice, $valu $attr, $isPreferred, $preferredViews[$groupLabel]->choices, + $preferredViewsOrder, $otherViews[$groupLabel]->choices ); } diff --git a/src/Symfony/Component/Form/Tests/ChoiceList/Factory/DefaultChoiceListFactoryTest.php b/src/Symfony/Component/Form/Tests/ChoiceList/Factory/DefaultChoiceListFactoryTest.php index 79118d93b0792..b065718054112 100644 --- a/src/Symfony/Component/Form/Tests/ChoiceList/Factory/DefaultChoiceListFactoryTest.php +++ b/src/Symfony/Component/Form/Tests/ChoiceList/Factory/DefaultChoiceListFactoryTest.php @@ -234,6 +234,28 @@ public function testCreateViewFlatPreferredChoices() $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() { $view = $this->factory->createView(
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: