8000 [Form] Simplified choice list API · symfony/symfony@2e07256 · GitHub
[go: up one dir, main page]

Skip to content

Commit 2e07256

Browse files
committed
[Form] Simplified choice list API
1 parent 2645120 commit 2e07256

21 files changed

+106
-302
lines changed

UPGRADE-2.1.md

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -158,14 +158,11 @@ UPGRADE FROM 2.0 to 2.1
158158
`getChoices()` and `getChoicesByValues()`. For the latter two, no
159159
replacement exists.
160160
161-
* The strategy for generating the `id` and `name` HTML attributes for choices
162-
in a choice field has changed.
161+
* The strategy for generating the `id` and `name` HTML attributes for
162+
checkboxes and radio buttons in a choice field has changed.
163163
164164
Instead of appending the choice value, a generated integer is now appended
165-
by default. Take care if your JavaScript relies on the old behavior. If you
166-
can guarantee that your choice values only contain ASCII letters, digits,
167-
colons and underscores, you can restore the old behavior by setting the
168-
`index_strategy` choice field option to `ChoiceList::COPY_CHOICE`.
165+
by default. Take care if your JavaScript relies on that.
169166
170167
* In the choice field type's template, the structure of the `choices` variable
171168
has changed.

src/Symfony/Bridge/Doctrine/Form/ChoiceList/EntityChoiceList.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ protected function createIndex($entity)
319319
protected function createValue($entity)
320320
{
321321
if (count($this->identifier) === 1) {
322-
return current($this->getIdentifierValues($entity));
322+
return (string) current($this->getIdentifierValues($entity));
323323
}
324324

325325
return parent::createValue($entity);

src/Symfony/Bridge/Propel1/Form/ChoiceList/ModelChoiceList.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ protected function createIndex($model)
304304
protected function createValue($model)
305305
{
306306
if (1 === count($this->identifier)) {
307-
return current($this->getIdentifierValues($model));
307+
return (string) current($this->getIdentifierValues($model));
308308
}
309309

310310
return parent::createValue($model);

src/Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceList.php

Lines changed: 9 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -32,29 +32,6 @@
3232
*/
3333
class ChoiceList implements ChoiceListInterface
3434
{
35-
/**
36-
* Strategy creating new indices/values by creating a copy of the choice.
37-
*
38-
* This strategy can only be used for index creation if choices are
39-
* guaranteed to only contain ASCII letters, digits and underscores.
40-
*
41-
* It can be used for value creation if choices can safely be cast into
42-
* a (unique) string.
43-
*
44-
* @var integer
45-
*/
46-
const COPY_CHOICE = 0;
47-
48-
/**
49-
* Strategy creating new indices/values by generating a new integer.
50-
*
51 10000 -
* This strategy can always be applied, but leads to loss of information
52-
* in the HTML source code.
53-
*
54-
* @var integer
55-
*/
56-
const GENERATE = 1;
57-
5835
/**
5936
* The choices with their indices as keys.
6037
*
@@ -85,24 +62,6 @@ class ChoiceList implements ChoiceListInterface
8562
*/
8663
private $remainingViews = array();
8764

88-
/**
89-
* The strategy used for creating choice indices.
90-
*
91-
* @var integer
92-
* @see COPY_CHOICE
93-
* @see GENERATE
94-
*/
95-
private $indexStrategy;
96-
97-
/**
98-
* The strategy used for creating choice values.
99-
*
100-
* @var integer
101-
* @see COPY_CHOICE
102-
* @see GENERATE
103-
*/
104-
private $valueStrategy;
105-
10665
/**
10766
* Creates a new choice list.
10867
*
@@ -115,16 +74,9 @@ class ChoiceList implements ChoiceListInterface
11574
* should match the structure of $choices.
11675
* @param array $preferredChoices A flat array of choices that should be
11776
* presented to the user with priority.
118-
* @param integer $valueStrategy The strategy used to create choice values.
119-
* One of COPY_CHOICE and GENERATE.
120-
* @param integer $indexStrategy The strategy used to create choice indices.
121-
* One of COPY_CHOICE and GENERATE.
12277
*/
123-
public function __construct($choices, array $labels, array $preferredChoices = array(), $valueStrategy = self::GENERATE, $indexStrategy = self::GENERATE)
78+
public function __construct($choices, array $labels, array $preferredChoices = array())
12479
{
125-
$this->valueStrategy = $valueStrategy;
126-
$this->indexStrategy = $indexStrategy;
127-
12880
$this->initialize($choices, $labels, $preferredChoices);
12981
}
13082

@@ -191,13 +143,6 @@ public function getRemainingViews()
191143
public function getChoicesForValues(array $values)
192144
{
193145
$values = $this->fixValues($values);
194-
195-
// If the values are identical to the choices, we can just return them
196-
// to improve performance a little bit
197-
if (self::COPY_CHOICE === $this->valueStrategy) {
198-
return $this->fixChoices(array_intersect($values, $this->values));
199-
}
200-
201146
$choices = array();
202147

203148
foreach ($values as $j => $givenValue) {
@@ -222,13 +167,6 @@ public function getChoicesForValues(array $values)
222167
public function getValuesForChoices(array $choices)
223168
{
224169
$choices = $this->fixChoices($choices);
225-
226-
// If the values are identical to the choices, we can just return them
227-
// to improve performance a little bit
228-
if (self::COPY_CHOICE === $this->valueStrategy) {
229-
return $this->fixValues(array_intersect($choices, $this->choices));
230-
}
231-
232170
$values = array();
233171

234172
foreach ($this->choices as $i => $choice) {
@@ -398,17 +336,15 @@ protected function addChoice(&$bucketForPreferred, &$bucketForRemaining, $choice
398336
$index = $this->createIndex($choice);
399337

400338
if ('' === $index || null === $index || !Form::isValidName((string)$index)) {
401-
throw new InvalidConfigurationException('The choice list index "' . $index . '" is invalid. Please set the choice field option "index_generation" to ChoiceList::GENERATE.');
339+
throw new InvalidConfigurationException('The index "' . $index . '" created by the choice list is invalid. It should be a valid, non-empty Form name.');
402340
}
403341

404342
$value = $this->createValue($choice);
405343

406-
if (!is_scalar($value)) {
407-
throw new InvalidConfigurationException('The choice list value of type "' . gettype($value) . '" should be a scalar. Please set the choice field option "value_generation" to ChoiceList::GENERATE.');
344+
if (!is_string($value)) {
345+
throw new InvalidConfigurationException('The value created by the choice list is of type "' . gettype($value) . '", but should be a string.');
408346
}
409347

410-
// Always store values as strings to facilitate comparisons
411-
$value = $this->fixValue($value);
412348
$view = new ChoiceView($value, $label);
413349

414350
$this->choices[$index] = $this->fixChoice($choice);
@@ -448,29 +384,23 @@ protected function isPreferred($choice, $preferredChoices)
448384
*/
449385
protected function createIndex($choice)
450386
{
451-
if (self::COPY_CHOICE === $this->indexStrategy) {
452-
return $choice;
453-
}
454-
455387
return count($this->choices);
456388
}
457389

458390
/**
459391
* Creates a new unique value for this choice.
460392
*
461-
* Extension point to change the value strategy.
393+
* By default, an integer is generated since it cannot be guaranteed that
394+
* all values in the list are convertible to (unique) strings. Subclasses
395+
* can override this behaviour if they can guarantee this property.
462396
*
463397
* @param mixed $choice The choice to create a value for
464398
*
465-
* @return integer|string A unique value without character limitations.
399+
* @return string A unique string.
466400
*/
467401
protected function createValue($choice)
468402
{
469-
if (self::COPY_CHOICE === $this->valueStrategy) {
470-
return $choice;
471-
}
472-
473-
return count($this->values);
403+
return (string) count($this->values);
474404
}
475405

476406
/**

src/Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceListInterface.php

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,12 @@
1414
/**
1515
* Contains choices that can be selected in a form field.
1616
*
17-
* Each choice has four different properties:
17+
* Each choice has three different properties:
1818
*
1919
* - Choice: The choice that should be returned to the application by the
2020
* choice field. Can be any scalar value or an object, but no
2121
* array.
2222
* - Label: A text representing the choice that is displayed to the user.
23-
* - Index: A uniquely identifying index that should only contain ASCII
24-
* characters, digits and underscores. This index is used to
25-
* identify the choice in the HTML "id" and "name" attributes.
26-
* It is also used as index of the arrays returned by the various
27-
* getters of this class.
2823
* - Value: A uniquely identifying value that can contain arbitrary
2924
* characters, but no arrays or objects. This value is displayed
3025
* in the HTML "value" attribute.

src/Symfony/Component/Form/Extension/Core/ChoiceList/ObjectChoiceList.php

Lines changed: 5 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
/**
2020
* A choice list for object choices.
2121
*
22-
* Supports generation of choice labels, choice groups, choice values and
23-
* choice indices by calling getters of the object (or associated objects).
22+
* Supports generation of choice labels, choice groups and choice values
23+
* by calling getters of the object (or associated objects).
2424
*
2525
* <code>
2626
* $choices = array($user1, $user2);
@@ -54,13 +54,6 @@ class ObjectChoiceList extends ChoiceList
5454
*/
5555
private $valuePath;
5656

57-
/**
58-
* The property path used to obtain the choice index.
59-
*
60-
* @var PropertyPath
61-
*/
62-
private $indexPath;
63-
6457
/**
6558
* Creates a new object choice list.
6659
*
@@ -82,18 +75,14 @@ class ObjectChoiceList extends ChoiceList
8275
* @param string $valuePath A property path pointing to the property used
8376
* for the choice values. If not given, integers
8477
* are generated instead.
85-
* @param string $indexPath A property path pointing to the property used
86-
* for the choice indices. If not given, integers
87-
* are generated instead.
8878
*/
89-
public function __construct($choices, $labelPath = null, array $preferredChoices = array(), $groupPath = null, $valuePath = null, $indexPath = null)
79+
public function __construct($choices, $labelPath = null, array $preferredChoices = array(), $groupPath = null, $valuePath = null)
9080
{
9181
$this->labelPath = $labelPath ? new PropertyPath($labelPath) : null;
9282
$this->groupPath = $groupPath ? new PropertyPath($groupPath) : null;
9383
$this->valuePath = $valuePath ? new PropertyPath($valuePath) : null;
94-
$this->indexPath = $indexPath ? new PropertyPath($indexPath) : null;
9584

96-
parent::__construct($choices, array(), $preferredChoices, self::GENERATE, self::GENERATE);
85+
parent::__construct($choices, array(), $preferredChoices);
9786
}
9887

9988
/**
@@ -148,27 +137,6 @@ protected function initialize($choices, array $labels, array $preferredChoices)
148137
parent::initialize($choices, $labels, $preferredChoices);
149138
}
150139

151-
/**
152-
* Creates a new unique index for this choice.
153-
*
154-
* If a property path for the index was given at object creation,
155-
* the getter behind that path is now called to obtain a new value.
156-
*
157-
* Otherwise a new integer is generated.
158-
*
159-
* @param mixed $choice The choice to create an index for
160-
* @return integer|string A unique index containing only ASCII letters,
161-
* digits and underscores.
162-
*/
163-
protected function createIndex($choice)
164-
{
165-
if ($this->indexPath) {
166-
return $this->indexPath->getValue($choice);
167-
}
168-
169-
return parent::createIndex($choice);
170-
}
171-
172140
/**
173141
* Creates a new unique value for this choice.
174142
*
@@ -183,7 +151,7 @@ protected function createIndex($choice)
183151
protected function createValue($choice)
184152
{
185153
if ($this->valuePath) {
186-
return $this->valuePath->getValue($choice);
154+
return (string) $this->valuePath->getValue($choice);
187155
}
188156

189157
return parent::createValue($choice);

src/Symfony/Component/Form/Extension/Core/ChoiceList/SimpleChoiceList.php

Lines changed: 37 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -28,27 +28,6 @@
2828
* ));
2929
* </code>
3030
*
31-
* The default value generation strategy is `ChoiceList::COPY_CHOICE`, because
32-
* choice values must be scalar, and the choices passed to this choice list
33-
* are guaranteed to be scalar.
34-
*
35-
* The default index generation strategy is `ChoiceList::GENERATE`, so that
36-
* your choices can also contain values that are illegal as indices. If your
37-
* choices are guaranteed to start with a letter, digit or underscore and only
38-
* contain letters, digits, underscores, hyphens and colons, you can set the
39-
* strategy to `ChoiceList::COPY_CHOICE` instead.
40-
*
41-
* <code>
42-
* $choices = array(
43-
* 'creditcard' => 'Credit card payment',
44-
* 'cash' => 'Cash payment',
45-
* );
46-
*
47-
* // value generation: COPY_CHOICE (the default)
48-
* // index generation: COPY_CHOICE (custom)
49-
* $choiceList = new SimpleChoiceList($choices, array(), ChoiceList::COPY_CHOICE, ChoiceList::COPY_CHOICE);
50-
* </code>
51-
*
5231
* @author Bernhard Schussek <bschussek@gmail.com>
5332
*/
5433
class SimpleChoiceList extends ChoiceList
@@ -64,15 +43,35 @@ class SimpleChoiceList extends ChoiceList
6443
* key pointing to the nested array.
6544
* @param array $preferredChoices A flat array of choices that should be
6645
* presented to the user with priority.
67-
* @param integer $valueStrategy The strategy used to create choice values.
68-
* One of COPY_CHOICE and GENERATE.
69-
* @param integer $indexStrategy The strategy used to create choice indices.
70-
* One of COPY_CHOICE and GENERATE.
7146
*/
72-
public function __construct(array $choices, array $preferredChoices = array(), $valueStrategy = self::COPY_CHOICE, $indexStrategy = self::GENERATE)
47+
public function __construct(array $choices, array $preferredChoices = array())
7348
{
7449
// Flip preferred choices to speed up lookup
75-
parent::__construct($choices, $choices, array_flip($preferredChoices), $valueStrategy, $indexStrategy);
50+
parent::__construct($choices, $choices, array_flip($preferredChoices));
51+
}
52+
53+
/**
54+
* {@inheritdoc}
55+
*/
56+
public function getChoicesForValues(array $values)
57+
{
58+
$values = $this->fixValues($values);
59+
60+
// The values are identical to the choices, so we can just return them
61+
// to improve performance a little bit
62+
return $this->fixChoices(array_intersect($values, $this->getValues()));
63+
}
64+
65+
/**
66+
* {@inheritdoc}
67+
*/
68+
public function getValuesForChoices(array $choices)
69+
{
70+
$choices = $this->fixChoices($choices);
71+
72+
// The choices are identical to the values, so we can just return them
73+
// to improve performance a little bit
74+
return $this->fixValues(array_intersect($choices, $this->getValues()));
7675
}
7776

7877
/**
@@ -147,16 +146,21 @@ protected function fixChoice($choice)
147146
return $this->fixIndex($choice);
148147
}
149148

150-
151149
/**
152-
* Converts the choices to valid PHP array keys.
153-
*
154-
* @param array $choices The choices.
155-
*
156-
* @return array Valid PHP array keys.
150+
* {@inheritdoc}
157151
*/
158152
protected function fixChoices(array $choices)
159153
{
160154
return $this->fixIndices($choices);
161155
}
156+
157+
/**
158+
* {@inheritdoc}
159+
*/
160+
protected function createValue($choice)
161+
{
162+
// Choices are guaranteed to be unique and scalar, so we can simply
163+
// convert them to strings
164+
return (string) $choice;
165+
}
162166
}

0 commit comments

Comments
 (0)
0