Hello,
Stumbled upon an issue with field_attach_form and field_sql_storage_field_storage_write.
The problem:
- Define a select/option field on a entity type (in my example it was the user object).
- The allowed key|value pairs are such that keys exceed two characters in length.
- Embed the fields in another content type or on a different form using field_attach_form.
- Select a value from the allowed list (doesn't matter if it is a multiple value field or single value field), so that the key is longer than 2 chars
- submit the form
=> the selected value(s) are not stored correctly. field_sql_storage_field_storage_write only stores the first character from the key.
The problem arises because the structure of the submitted field_value array doesn't conform to the expectations of field_sql_storage_field_storage_write.
E.g. the value is submitted as :
[<field_id>] => Array
(
[und] => Array
(
[0] => <our value>
)
)
but should be:
[field_div_id] => Array
(
[und] => Array
(
[0] => Array
(
[value] => <our value>
)
)
)
This leads to the wrong result when the following is executed:
foreach ($field['columns'] as $column => $attributes) {
$record[_field_sql_storage_columnname($field_name, $column)] = isset($item[$column]) ? $item[$column] : NULL;
}
(lines 435-437 in field_sql_storage.module). Here we are up against everyones favorite php feature, i.e. using a string to refer individual characters in a string :)
I've done some quick code research and it seems to me that this problem is still in Drupal 8. (Although I haven't verified it/tested it)
This is perhaps better described as a problem of field_attach_form, but I haven't debugged that part of the problem.
To recreate the issue:
- define a select/option field on the user object.
- in the allowed values list specify, for example:
23|Test1
24|Test2
25|Test3
- Create a user and select a value from the list and store the user
- Create a simple module for testing purposes:
function test_module_menu() {
$items = array();
$items['user_test'] = array(
'title' => 'bug test',
'page callback' => 'drupal_get_form',
'page arguments' => array('test_module_user_edit_form'),
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
);
return $items;
}
function test_module_user_edit_form($form,&$form_state) {
$account = user_load(<some user-id>); // <<< supply a value or send as parameter
field_attach_form('user',$account,$form,$form_state);
$form['#account'] = $account;
$form['op'] = array(
'#type' => 'submit',
'#value' => 'Geyma'
);
return $form;
}
function test_module_user_edit_form_submit($form,&$form_state) {
field_attach_submit("user", $form['#account'], $form, $form_state);
user_save($form['#account'],$form_state['input']);
drupal_set_message("info updated");
$form_state['submitted'] = TRUE;
}
The easy, but ugly workaround is to add the following snippet just before field_attach_submit call in the submit handler:
$save_div_id = $form_state['input']['field_div_id']['und']; // ugly BUG-FIX for the save process
$form_state['input']['field_div_id']['und'] = array(
0 => array(
'value' => $save_div_id
)
);
Cheers,
skari