Index: ./drupal/modules/field/modules/list/list.module =================================================================== RCS file: /cvs/drupal/drupal/modules/field/modules/list/list.module,v retrieving revision 1.35 diff -u -p -r1.35 list.module --- ./drupal/modules/field/modules/list/list.module 11 Oct 2010 19:57:00 -0000 1.35 +++ ./drupal/modules/field/modules/list/list.module 14 Oct 2010 21:48:22 -0000 @@ -139,6 +139,33 @@ function list_field_settings_form($field } /** + * Implementation of hook_field_update_forbid( + */ +function list_field_update_forbid($field, $prior_field, $has_data) { + + // A 'list' field stores integer keys mapped to display values. If + // the new field has abandoned keys and data data exists for the + // abandoned keys, the field will have no way to display them. So, + // forbid such an update. + $prior_field_allowed = list_extract_allowed_values($prior_field['settings']['allowed_values'], $prior_field['type'] == 'list'); + $field_allowed = list_extract_allowed_values($field['settings']['allowed_values'], $field['type'] == 'list'); + + if ($has_data && $lost_keys = array_diff(array_keys($prior_field_allowed), array_keys($field_allowed))) { + // If any data exist for those keys, forbid the update. + $query = new EntityFieldQuery(); + $found = $query + ->fieldCondition($prior_field['field_name'], 'value', $lost_keys) + ->range(0, 1) + ->execute(); + if ($found) { + throw new FieldUpdateForbiddenException("Cannot update a list field to remove keys that have existing data"); + } + } +} + + + +/** * Element validate callback; check that the entered values are valid. */ function list_allowed_values_setting_validate($element, &$form_state) { @@ -160,6 +187,35 @@ function list_allowed_values_setting_val break; } } + + if (!empty($form_state['values']['field']['field_name'])) { + // via manage fields tab + $field_name = $form_state['values']['field']['field_name']; + } + else { + // via edit tab + $field_name = $form_state['values']['instance']['field_name']; + } + + $prior_field = field_info_field($field_name); + + if (!empty($form_state['values']['field']['type'])) { + // via manage fields tab + $new_field = $form_state['values']['field']; + } + else { + // via edit tab + $new_field = $prior_field; + $new_field['settings']['allowed_values'] = $form_state['values']['field']['settings']['allowed_values']; + } + + try { + list_field_update_forbid($new_field, $prior_field, field_has_data($prior_field)); + } + catch (FieldUpdateForbiddenException $e) { + form_error($element, $e->getMessage()); + } + } /** @@ -242,7 +298,7 @@ function list_extract_allowed_values($st } // Otherwise see if we need to use the value as the key. The "list" type // will automatically convert non-keyed lines to integers. - elseif (!$position_keys) { + elseif ($position_keys) { $key = $value; } $values[$key] = (isset($value) && $value !== '') ? $value : $key;