Skip to content

Commit aa9c3cc

Browse files
committed
[Form] add choice_label_attr option to ChoiceType
1 parent a2a20eb commit aa9c3cc

File tree

10 files changed

+457
-24
lines changed

10 files changed

+457
-24
lines changed

src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3HorizontalLayoutTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class FormExtensionBootstrap3HorizontalLayoutTest extends AbstractBootstrap3Hori
2626

2727
protected $testableFeatures = array(
2828
'choice_attr',
29+
'choice_label_attr',
2930
);
3031

3132
private $renderer;

src/Symfony/Component/Form/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ CHANGELOG
88
* implemented `ChoiceLoaderInterface` in children of `ChoiceType`
99
* deprecated `choice_attr` option as array of nested arrays mapped by indexes
1010
* deprecated `choice_attr` option as string or `PropertyPath` instance
11+
* added `choice_label_attr` option to `ChoiceType` to use when expanded
1112

1213
3.1.0
1314
-----

src/Symfony/Component/Form/ChoiceList/Factory/CachingFactoryDecorator.php

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
*
2121
* @author Bernhard Schussek <bschussek@gmail.com>
2222
*/
23-
class CachingFactoryDecorator implements ChoiceListFactoryInterface
23+
class CachingFactoryDecorator implements ExpandedChoiceListFactoryInterface
2424
{
2525
/**
2626
* @var ChoiceListFactoryInterface
@@ -153,20 +153,42 @@ public function createListFromLoader(ChoiceLoaderInterface $loader, $value = nul
153153
* {@inheritdoc}
154154
*/
155155
public function createView(ChoiceListInterface $list, $preferredChoices = null, $label = null, $index = null, $groupBy = null, $attr = null)
156+
{
157+
return $this->createExpandedView($list, $preferredChoices, $label, $index, $groupBy, $attr);
158+
}
159+
160+
/**
161+
* {@inheritdoc}
162+
*/
163+
public function createExpandedView(ChoiceListInterface $list, $preferredChoices = null, $label = null, $index = null, $groupBy = null, $attr = null, $labelAttr = null)
156164
{
157165
// The input is not validated on purpose. This way, the decorated
158166
// factory may decide which input to accept and which not.
159167
$hash = self::generateHash(array($list, $preferredChoices, $label, $index, $groupBy, $attr));
160168

161169
if (!isset($this->views[$hash])) {
162-
$this->views[$hash] = $this->decoratedFactory->createView(
163-
$list,
164-
$preferredChoices,
165-
$label,
166-
$index,
167-
$groupBy,
168-
$attr
169-
);
170+
// BC layer
171+
if ($this->decoratedFactory instanceof ExpandedChoiceListFactoryInterface) {
172+
$choiceView = $this->decoratedFactory->createExpandedView(
173+
$list,
174+
$preferredChoices,
175+
$label,
176+
$index,
177+
$groupBy,
178+
$attr,
179+
$labelAttr
180+
);
181+
} else {
182+
$choiceView = $this->decoratedFactory->createView(
183+
$list,
184+
$preferredChoices,
185+
$label,
186+
$index,
187+
$groupBy,
188+
$attr
189+
);
190+
}
191+
$this->views[$hash] = $choiceView;
170192
}
171193

172194
return $this->views[$hash];

src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
*
2525
* @author Bernhard Schussek <bschussek@gmail.com>
2626
*/
27-
class DefaultChoiceListFactory implements ChoiceListFactoryInterface
27+
class DefaultChoiceListFactory implements ExpandedChoiceListFactoryInterface
2828
{
2929
/**
3030
* {@inheritdoc}
@@ -46,6 +46,14 @@ public function createListFromLoader(ChoiceLoaderInterface $loader, $value = nul
4646
* {@inheritdoc}
4747
*/
4848
public function createView(ChoiceListInterface $list, $preferredChoices = null, $label = null, $index = null, $groupBy = null, $attr = null)
49+
{
50+
return $this->createExpandedView($list, $preferredChoices, $label, $index, $groupBy, $attr);
51+
}
52+
53+
/**
54+
* {@inheritdoc}
55+
*/
56+
public function createExpandedView(ChoiceListInterface $list, $preferredChoices = null, $label = null, $index = null, $groupBy = null, $attr = null, $labelAttr = null)
4957
{
5058
$preferredViews = array();
5159
$otherViews = array();
@@ -76,6 +84,7 @@ public function createView(ChoiceListInterface $list, $preferredChoices = null,
7684
$keys,
7785
$index,
7886
$attr,
87+
$labelAttr,
7988
$preferredChoices,
8089
$preferredViews,
8190
$otherViews
@@ -90,6 +99,7 @@ public function createView(ChoiceListInterface $list, $preferredChoices = null,
9099
$keys,
91100
$index,
92101
$attr,
102+
$labelAttr,
93103
$preferredChoices,
94104
$preferredViews,
95105
$otherViews
@@ -113,7 +123,7 @@ public function createView(ChoiceListInterface $list, $preferredChoices = null,
113123
return new ChoiceListView($otherViews, $preferredViews);
114124
}
115125

116-
private static function addChoiceView($choice, $value, $label, $keys, &$index, $attr, $isPreferred, &$preferredViews, &$otherViews)
126+
private static function addChoiceView($choice, $value, $label, $keys, &$index, $attr, $labelAttr, $isPreferred, &$preferredViews, &$otherViews)
117127
{
118128
// $value may be an integer or a string, since it's stored in the array
119129
// keys. We want to guarantee it's a string though.
@@ -139,8 +149,11 @@ private static function addChoiceView($choice, $value, $label, $keys, &$index, $
139149
} else {
140150
foreach ($attr as $a) {
141151
if (is_array($a)) {
142-
// When $attr[$key] is not set we need to prevent
143-
// using an HTML attribute as an array for BC
152+
// For BC
153+
// Using the deprecated way of choice keys as keys
154+
// allows to not define all choices.
155+
// When $attr[$key] is not set for this one but is for
156+
// another we need to prevent using an array as HTML
144157
$attr = array();
145158

146159
break;
@@ -154,7 +167,8 @@ private static function addChoiceView($choice, $value, $label, $keys, &$index, $
154167
$value,
155168
$label,
156169
// The attributes may be a callable or an array
157-
is_callable($attr) ? call_user_func($attr, $choice, $key, $value) : (null !== $attr ? $attr : array())
170+
is_callable($attr) ? call_user_func($attr, $choice, $key, $value) : (null !== $attr ? $attr : array()),
171+
is_callable($labelAttr) ? call_user_func($labelAttr, $choice, $key, $value) : (null !== $labelAttr ? $labelAttr : array())
158172
);
159173

160174
// $isPreferred may be null if no choices are preferred
@@ -165,7 +179,7 @@ private static function addChoiceView($choice, $value, $label, $keys, &$index, $
165179
}
166180
}
167181

168-
private static function addChoiceViewsGroupedBy($groupBy, $label, $choices, $keys, &$index, $attr, $isPreferred, &$preferredViews, &$otherViews)
182+
private static function addChoiceViewsGroupedBy($groupBy, $label, $choices, $keys, &$index, $attr, $labelAttr, $isPreferred, &$preferredViews, &$otherViews)
169183
{
170184
foreach ($groupBy as $key => $value) {
171185
if (null === $value) {
@@ -184,6 +198,7 @@ private static function addChoiceViewsGroupedBy($groupBy, $label, $choices, $key
184198
$keys,
185199
$index,
186200
$attr,
201+
$labelAttr,
187202
$isPreferred,
188203
$preferredViewsForGroup,
189204
$otherViewsForGroup
@@ -208,14 +223,15 @@ private static function addChoiceViewsGroupedBy($groupBy, $label, $choices, $key
208223
$keys,
209224
$index,
210225
$attr,
226+
$labelAttr,
211227
$isPreferred,
212228
$preferredViews,
213229
$otherViews
214230
);
215231
}
216232
}
217233

218-
private static function addChoiceViewGroupedBy($groupBy, $choice, $value, $label, $keys, &$index, $attr, $isPreferred, &$preferredViews, &$otherViews)
234+
private static function addChoiceViewGroupedBy($groupBy, $choice, $value, $label, $keys, &$index, $attr, $labelAttr, $isPreferred, &$preferredViews, &$otherViews)
219235
{
220236
$groupLabel = call_user_func($groupBy, $choice, $keys[$value], $value);
221237

@@ -228,6 +244,7 @@ private static function addChoiceViewGroupedBy($groupBy, $choice, $value, $label
228244
$keys,
229245
$index,
230246
$attr,
247+
$labelAttr,
231248
$isPreferred,
232249
$preferredViews,
233250
$otherViews
@@ -252,6 +269,7 @@ private static function addChoiceViewGroupedBy($groupBy, $choice, $value, $label
252269
$keys,
253270
$index,
254271
$attr,
272+
$labelAttr,
255273
$isPreferred,
256274
$preferredViews[$groupLabel]->choices,
257275
$otherViews[$groupLabel]->choices
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Form\ChoiceList\Factory;
13+
14+
use Symfony\Component\Form\ChoiceList\ChoiceListInterface;
15+
use Symfony\Component\Form\ChoiceList\View\ChoiceListView;
16+
17+
/**
18+
* Creates {@link ChoiceListInterface} instances.
19+
*
20+
* Provides a BC layer for 3.x.
21+
*
22+
* To be deprecated in 3.4 and removed in 4.0, in favor of {@link ChoiceListFactoryInterface::createview()}
23+
*
24+
* @author Bernhard Schussek <bschussek@gmail.com>
25+
* @author Jules Pietri <jules@heahprod.com>
26+
*/
27+
interface ExpandedChoiceListFactoryInterface extends ChoiceListFactoryInterface
28+
{
29+
/**
30+
* Creates a view for the given choice list.
31+
*
32+
* Callables may be passed for all optional arguments. The callables receive
33+
* the choice as first and the array key as the second argument.
34+
*
35+
* * The callable for the label and the name should return the generated
36+
* label/choice name.
37+
* * The callable for the preferred choices should return true or false,
38+
* depending on whether the choice should be preferred or not.
39+
* * The callable for the grouping should return the group name or null if
40+
* a choice should not be grouped.
41+
* * The callable for the attributes should return an array of HTML
42+
* attributes that will be inserted in the tag of the choice.
43+
* * The callable for the label attributes should return an array of HTML
44+
* attributes that will be inserted in the tag of the choice.
45+
*
46+
* If no callable is passed, the labels will be generated from the choice
47+
* keys. The view indices will be generated using an incrementing integer
48+
* by default.
49+
*
50+
* The preferred choices can also be passed as array. Each choice that is
51+
* contained in that array will be marked as preferred.
52+
*
53+
* The attributes can be passed as multi-dimensional array. The keys should
54+
* match the keys of the choices. The values should be arrays of HTML
55+
* attributes that should be added to the respective choice.
56+
*
57+
* The label attributes can be passed as an array. It will be used for
58+
* each choice.
59+
*
60+
* @param ChoiceListInterface $list The choice list
61+
* @param null|array|callable $preferredChoices The preferred choices
62+
* @param null|callable $label The callable generating the
63+
* choice labels
64+
* @param null|callable $index The callable generating the
65+
* view indices
66+
* @param null|callable $groupBy The callable generating the
67+
* group names
68+
* @param null|array|callable $attr The callable generating the
69+
* HTML attributes
70+
* @param null|array|callable $labelAttr The callable generating the
71+
* HTML attributes
72+
*
73+
* @return ChoiceListView The choice list view
74+
*/
75+
public function createExpandedView(ChoiceListInterface $list, $preferredChoices = null, $label = null, $index = null, $groupBy = null, $attr = null, $labelAttr = null);
76+
}

src/Symfony/Component/Form/ChoiceList/Factory/PropertyAccessDecorator.php

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
*
4040
* @author Bernhard Schussek <bschussek@gmail.com>
4141
*/
42-
class PropertyAccessDecorator implements ChoiceListFactoryInterface
42+
class PropertyAccessDecorator implements ExpandedChoiceListFactoryInterface
4343
{
4444
/**
4545
* @var ChoiceListFactoryInterface
@@ -139,6 +139,11 @@ public function createListFromLoader(ChoiceLoaderInterface $loader, $value = nul
139139
return $this->decoratedFactory->createListFromLoader($loader, $value);
140140
}
141141

142+
public function createView(ChoiceListInterface $list, $preferredChoices = null, $label = null, $index = null, $groupBy = null, $attr = null)
143+
{
144+
return $this->createExpandedView($list, $preferredChoices, $label, $index, $groupBy, $attr);
145+
}
146+
142147
/**
143148
* {@inheritdoc}
144149
*
@@ -148,10 +153,11 @@ public function createListFromLoader(ChoiceLoaderInterface $loader, $value = nul
148153
* @param null|callable|string|PropertyPath $index The callable or path generating the view indices
149154
* @param null|callable|string|PropertyPath $groupBy The callable or path generating the group names
150155
* @param null|array|callable|string|PropertyPath $attr The callable or path generating the HTML attributes
156+
* @param null|array|callable $labelAttr The array or callable generating the label HTML attributes
151157
*
152158
* @return ChoiceListView The choice list view
153159
*/
154-
public function createView(ChoiceListInterface $list, $preferredChoices = null, $label = null, $index = null, $groupBy = null, $attr = null)
160+
public function createExpandedView(ChoiceListInterface $list, $preferredChoices = null, $label = null, $index = null, $groupBy = null, $attr = null, $labelAttr = null)
155161
{
156162
$accessor = $this->propertyAccessor;
157163

@@ -225,6 +231,13 @@ public function createView(ChoiceListInterface $list, $preferredChoices = null,
225231
};
226232
}
227233

228-
return $this->decoratedFactory->createView($list, $preferredChoices, $label, $index, $groupBy, $attr);
234+
// BC Layer
235+
if ($this->decoratedFactory instanceof ExpandedChoiceListFactoryInterface) {
236+
$choiceView = $this->decoratedFactory->createExpandedView($list, $preferredChoices, $label, $index, $groupBy, $attr, $labelAttr);
237+
} else {
238+
$choiceView = $this->decoratedFactory->createView($list, $preferredChoices, $label, $index, $groupBy, $attr);
239+
}
240+
241+
return $choiceView;
229242
}
230243
}

src/Symfony/Component/Form/ChoiceList/View/ChoiceView.php

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,19 +46,28 @@ class ChoiceView
4646
*/
4747
public $attr;
4848

49+
/**
50+
* Additional label attributes for the HTML tag.
51+
*
52+
* @var array
53+
*/
54+
public $labelAttr;
55+
4956
/**
5057
* Creates a new choice view.
5158
*
52-
* @param mixed $data The original choice
53-
* @param string $value The view representation of the choice
54-
* @param string $label The label displayed to humans
55-
* @param array $attr Additional attributes for the HTML tag
59+
* @param mixed $data The original choice
60+
* @param string $value The view representation of the choice
61+
* @param string $label The label displayed to humans
62+
* @param array $attr Additional attributes for the HTML tag
63+
* @param array $labelAttr Additional label attributes for the HTML tag
5664
*/
57-
public function __construct($data, $value, $label, array $attr = array())
65+
public function __construct($data, $value, $label, array $attr = array(), array $labelAttr = array())
5866
{
5967
$this->data = $data;
6068
$this->value = $value;
6169
$this->label = $label;
6270
$this->attr = $attr;
71+
$this->labelAttr = $labelAttr;
6372
}
6473
}

0 commit comments

Comments
 (0)