From bbbdda83845efd6d6e0723db8b3f61c514587e6e Mon Sep 17 00:00:00 2001 From: Jordan Samouh Date: Thu, 23 Mar 2017 23:56:32 +0100 Subject: [PATCH] [Component][Form][ChoiceType] : Add new option to sort group_by value --- .../Factory/CachingFactoryDecorator.php | 5 +-- .../Factory/ChoiceListFactoryInterface.php | 3 +- .../Factory/DefaultChoiceListFactory.php | 8 ++++- .../Factory/PropertyAccessDecorator.php | 5 +-- .../Form/Extension/Core/Type/ChoiceType.php | 5 ++- .../Extension/Core/Type/ChoiceTypeTest.php | 31 +++++++++++++++++++ 6 files changed, 50 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/Form/ChoiceList/Factory/CachingFactoryDecorator.php b/src/Symfony/Component/Form/ChoiceList/Factory/CachingFactoryDecorator.php index 6580e661d4d66..16e2bab33d0fb 100644 --- a/src/Symfony/Component/Form/ChoiceList/Factory/CachingFactoryDecorator.php +++ b/src/Symfony/Component/Form/ChoiceList/Factory/CachingFactoryDecorator.php @@ -152,7 +152,7 @@ public function createListFromLoader(ChoiceLoaderInterface $loader, $value = nul /** * {@inheritdoc} */ - 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, $groupByOrder = null) { // The input is not validated on purpose. This way, the decorated // factory may decide which input to accept and which not. @@ -165,7 +165,8 @@ public function createView(ChoiceListInterface $list, $preferredChoices = null, $label, $index, $groupBy, - $attr + $attr, + $groupByOrder ); } diff --git a/src/Symfony/Component/Form/ChoiceList/Factory/ChoiceListFactoryInterface.php b/src/Symfony/Component/Form/ChoiceList/Factory/ChoiceListFactoryInterface.php index 1c6f24d6986f8..561616ab41af9 100644 --- a/src/Symfony/Component/Form/ChoiceList/Factory/ChoiceListFactoryInterface.php +++ b/src/Symfony/Component/Form/ChoiceList/Factory/ChoiceListFactoryInterface.php @@ -90,8 +90,9 @@ public function createListFromLoader(ChoiceLoaderInterface $loader, $value = nul * group names * @param null|array|callable $attr The callable generating the * HTML attributes + * @param null|array|callable $groupByOrder The group by order * * @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, $groupByOrder = null); } diff --git a/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php b/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php index 3398c98edd742..299093dd16515 100644 --- a/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php +++ b/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php @@ -45,7 +45,7 @@ public function createListFromLoader(ChoiceLoaderInterface $loader, $value = nul /** * {@inheritdoc} */ - 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, $groupByOrder = null) { $preferredViews = array(); $otherViews = array(); @@ -81,6 +81,12 @@ public function createView(ChoiceListInterface $list, $preferredChoices = null, $otherViews ); } + + if ($groupByOrder && is_array($groupByOrder)) { + uksort($otherViews, function ($key1, $key2) use ($groupByOrder) { + return array_search($key1, $groupByOrder) > array_search($key2, $groupByOrder); + }); + } } else { // Otherwise use the original structure of the choices self::addChoiceViewsGroupedBy( diff --git a/src/Symfony/Component/Form/ChoiceList/Factory/PropertyAccessDecorator.php b/src/Symfony/Component/Form/ChoiceList/Factory/PropertyAccessDecorator.php index 0e282f7083da5..61d8be545744a 100644 --- a/src/Symfony/Component/Form/ChoiceList/Factory/PropertyAccessDecorator.php +++ b/src/Symfony/Component/Form/ChoiceList/Factory/PropertyAccessDecorator.php @@ -148,10 +148,11 @@ public function createListFromLoader(ChoiceLoaderInterface $loader, $value = nul * @param null|callable|string|PropertyPath $index The callable or path generating the view indices * @param null|callable|string|PropertyPath $groupBy The callable or path generating the group names * @param null|array|callable|string|PropertyPath $attr The callable or path generating the HTML attributes + * @param null|array|callable|string|PropertyPath $groupByOrder The groupBy order * * @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, $groupByOrder = null) { $accessor = $this->propertyAccessor; @@ -224,6 +225,6 @@ public function createView(ChoiceListInterface $list, $preferredChoices = null, }; } - return $this->decoratedFactory->createView($list, $preferredChoices, $label, $index, $groupBy, $attr); + return $this->decoratedFactory->createView($list, $preferredChoices, $label, $index, $groupBy, $attr, $groupByOrder); } } diff --git a/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php b/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php index b117f70edf265..b6e416e2bf52b 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php @@ -332,6 +332,7 @@ public function configureOptions(OptionsResolver $resolver) 'choice_attr' => null, 'preferred_choices' => array(), 'group_by' => null, + 'group_by_order' => null, 'empty_data' => $emptyData, 'placeholder' => $placeholderDefault, 'error_bubbling' => false, @@ -356,6 +357,7 @@ public function configureOptions(OptionsResolver $resolver) $resolver->setAllowedTypes('choice_attr', array('null', 'array', 'callable', 'string', 'Symfony\Component\PropertyAccess\PropertyPath')); $resolver->setAllowedTypes('preferred_choices', array('array', '\Traversable', 'callable', 'string', 'Symfony\Component\PropertyAccess\PropertyPath')); $resolver->setAllowedTypes('group_by', array('null', 'callable', 'string', 'Symfony\Component\PropertyAccess\PropertyPath')); + $resolver->setAllowedTypes('group_by_order', array('null', 'array', '\Traversable')); } /** @@ -444,7 +446,8 @@ private function createChoiceListView(ChoiceListInterface $choiceList, array $op $options['choice_label'], $options['choice_name'], $options['group_by'], - $options['choice_attr'] + $options['choice_attr'], + $options['group_by_order'] ); } } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php index 8bcd7716dd048..9ddd94195e9bf 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php @@ -1669,6 +1669,37 @@ public function testPassHierarchicalChoicesToView() ), $view->vars['preferred_choices']); } + public function testPassHierarchicalChoicesToViewWithGroupOrder() + { + $view = $this->factory->create(static::TESTED_TYPE, null, array( + 'choices' => $this->choices, + 'preferred_choices' => array('b', 'd'), + 'group_by' => function ($val, $key, $index) { + return (strlen($key) > 4) ? 'LongName' : 'ShortName'; + }, + 'group_by_order' => array('ShortName', 'LongName', 'TestNotMatched'), + )) + ->createView(); + + $this->assertEquals(array( + 'ShortName' => new ChoiceGroupView('ShortName', array( + 2 => new ChoiceView('c', 'c', 'Kris'), + )), + 'LongName' => new ChoiceGroupView('LongName', array( + 0 => new ChoiceView('a', 'a', 'Bernhard'), + 4 => new ChoiceView('e', 'e', 'Roman'), + )), + ), $view->vars['choices']); + $this->assertEquals(array( + 'LongName' => new ChoiceGroupView('LongName', array( + 1 => new ChoiceView('b', 'b', 'Fabien'), + )), + 'ShortName' => new ChoiceGroupView('ShortName', array( + 3 => new ChoiceView('d', 'd', 'Jon'), + )), + ), $view->vars['preferred_choices']); + } + public function testPassChoiceDataToView() { $obj1 = (object) array('value' => 'a', 'label' => 'A');