Updated: Comment #0
Problem/Motivation
Because drupal_array_merge_deep() has no option for preserving integer keys, the call in line 294 of options_element.module can corrupt the #options
key of the options element.
Steps to reproduce
- Add a list field to a content type with integer keys for the allowed values, that do not represent the natural array order, i.e. use 10, 100, 1000, instead of 0, 1, 2, ...
- Add a node of that content type and fill out the field
- Go back to the edit page of the field
- Without changing anything, submit the form
- Expected result
- The form submission is successful
- Actual result
- You get a validation error saying
Allowed values list: some values are being removed while currently in use.
- To investigate the problem, look closer now at the keys that the options element is presenting.
- Expected result
- 10, 100, 100
- Actual result
- 0, 1, 2
Proposed resolution
It would be nice if drupal_array_merge_deep_array() had an option for preserving integer keys, just like the equivalent method in D8 has. I re-opened #1825466: Allow NestedArray::mergeDeepArray() to preserve integer keys for the purpose of backporting, but I don't think we need to wait for that.
The problem occurs only, because in _options_element_add_allowed_values_element() $default_element
declares the #options
key as an empty array. This causes drupal_array_merge_deep(_array)() to merge array()
with the passed-in $element['#options']
, if that exists. In all 2 cases where the function is called, however $element['#options']
is set. So we can just remove the default empty array and get rid of this problem.
This is an behavioral change in the _options_element_add_allowed_values_element() function, but since that is marked private by the leading underscore I'm not sure that should be considered an API change. One could, of course, also find 100%-BC-compatible solutions to this problem.
Remaining tasks
Review patch.
User interface changes
-
API changes
- (Maybe, see above)
Comment | File | Size | Author |
---|---|---|---|
#1 | 2205823-1-options-element-integer-keys.patch | 704 bytes | tstoeckler |
Comments
Comment #1
tstoecklerHere's the patch.
Tested this locally and it works as expected.
Comment #2
quicksketchThis works for me. We don't really need to provide #options anyway, since it'll be provided by hook_element_info() if needed to prevent notices. Committed to 7.x-1.x.