Hi,
I have a text-list field which already contain values. I would very much like to remove 3 options from the text-list.
But when I try to remove the options, I got:

Allowed values list: some values are being removed while currently in use.

The field TAB says:

There is data for this field in the database. The field settings can no longer be changed.
These settings apply to the check field everywhere it is used. These settings impact the way that data is stored in the database and cannot be changed once data has been created.

But if I really know what I am doing and want to remove 2 items of the list. How would I proceed please?
I can't alter it within the database, because it is a BLOB-field. Is there a module in which you can override regular behaviour and change the options in a field.

thanks a lot in advance for your reply!

Greetings,
Martijn

Comments

vm’s picture

make a view of the content which uses the values
use views bulk operations to update that content to use values you aren't trying to remove

test removal of the obsolete values

jasonflaherty’s picture

thanks for this answer. I use VBO for other things... quick and easy here also.

good stuff.

megachriz’s picture

If you don't care about invalid values in your database (for example when the values are used in test data only that you want to remove later anyway), then the following "patch" disables the check for actual data.

Remember to reverse the patch when you made your changes.

diff --git a/modules/field/modules/list/list.module b/modules/field/modules/list/list.module
index 634c134..9c189de 100644
--- a/modules/field/modules/list/list.module
+++ b/modules/field/modules/list/list.module
@@ -186,7 +186,7 @@ function list_allowed_values_setting_validate($element, &$form_state) {
     }
 
     // Prevent removing values currently in use.
-    if ($has_data) {
+    if ($has_data && 0) {
       $lost_keys = array_diff(array_keys($field['settings']['allowed_values']), array_keys($values));
       if (_list_values_in_use($field, $lost_keys)) {
         form_error($element, t('Allowed values list: some values are being removed while currently in use.'));
@@ -356,7 +356,7 @@ function list_allowed_values_string($values) {
  * Implements hook_field_update_forbid().
  */
 function list_field_update_forbid($field, $prior_field, $has_data) {
-  if ($field['module'] == 'list' && $has_data) {
+  if ($field['module'] == 'list' && $has_data && 0) {
     // Forbid any update that removes allowed values with actual data.
     $lost_keys = array_diff(array_keys($prior_field['settings']['allowed_values']), array_keys($field['settings']['allowed_values']));
     if (_list_values_in_use($field, $lost_keys)) {

The patch simply adds a zero when checking for existing data, which will always evaluate to FALSE.

Mohva’s picture

Thank you for this post. :-)

mayuri_02’s picture

Hey,

It is working perfectly fine , i have checked in my project.

thanks
mayuri

benarobinson’s picture

You can do this without modifying core by overriding the list_field_update_forbid() hook. The warning above still applies, though... do this only if you're not that concerned about potentially having 'dead' list field values in the database that you'll have to clean up. (In other words, your `field_data_field_mylistfield` and `field_revision_field_mylistfield` tables will have the old, invalid values in the `field_mylistfield_value` column.

Also, since the original does nothing unless the field module is 'list' and it has data, you can just not not do anything in your replacement function...

/**
 * Implements hook_field_update_forbid()
 * Reference: https://api.drupal.org/api/drupal/modules!field!field.api.php/function/hook_field_update_forbid/7.x 
 *
 * Don't forbid update to list field when a value is in use.
 */
function yourmodule_field_update_forbid($field, $prior_field, $has_data) {
  // Do nothing, or log an error without actually stopping anything.
  // Whatever you want.
}

/**
 * Implements hook_module_implements_alter()
 * Reference: https://api.drupal.org/api/drupal/modules%21system%21system.api.php/function/hook_module_implements_alter/7.x. 
 *
 * Unset the list implementation of hook_field_update_forbid in favor of the above.
 */
function yourmodule_module_implements_alter(&$implementations, $hook) {
  if ($hook == 'field_update_forbid') {
    unset($implementations['list']);
  }
}
tunprog’s picture

Thank you so much this works. It lets you save the form and also revert the feature that contains the fields but I think it is better to update the database directly using a hook_update_N.

Edit: Updating the fields in the database directly won't work without the patch above. The best solution is to delete old fields and create new ones to replace them.

aaronbauman’s picture

LTech’s picture

I would like to add some values to the select list. I've added them in the array under 'Allowed values PHP code' and it is showing in the BLOB file under file under the 'field_config' table, but the options are not showing when I try and 'add content'.
Why is this? How do I add values to the select list?

katin’s picture

This one had me going in circles... it seems that one value-item check is case sensitive, while another is case insensitive.
I wanted to change one option "Bacs" to "BACS".

When I changed the item in the "Allowed values list" from:
Bacs|Bacs to BACS|BACS, it gave the error message:

Allowed values list: some values are being removed while currently in use.

So, I added BACS|BACS as an additional option so both were in there. Then I changed every node that had "Bacs" selected to "BACS".

Now, at this point, if the words had been different, it would work to simply delete the old value from the Allowed values list. I know that because I had just done it with a different value in the same field, same list. However, when I removed "Bacs|Bacs" from the Allowed values list, it again gave the error message:

Allowed values list: some values are being removed while currently in use.

I verified using database tools that there were no fields nor nodes nor views using the 'Bacs" value. I had to remove or change every "BACS" value in any node to something completely different (e.g., "Paypal"), then it allowed the Save settings on the change to remove "Bacs" from the Allowed values list.

If you're going 'round in circles due to this error message, check case sensitivity. Might need to do a 3-stage change to your values,

LasVegasFIT’s picture

To anyone that experiences this issue where you can't change the drop-down list field, I've made a video on how to fix this issue:
https://www.youtube.com/watch?v=17dXSVDTlBM

davidebru’s picture

Usually, I use this script to update the options of fields, that already contains data in the db:

  $field_name = 'field_example';
  // Get the field info
  $info = field_info_field($field_name);
  // Get a reference to the values
  $values = &$info['settings']['allowed_values'];
  //$values = &$info['settings']['allowed_values_function'] = '_custom_options_list';
  // Manipulate the values in some way, e.g.
  $options = [
    'example' => 'Example',
    'example_1' => 'Example 1',
    'example_2' => 'Example 2',
  ];

  $values = array_merge($values, $options);
  // Save the field
  field_update_field($info);
rblackmore’s picture

I ran this script on a "select list" field and it choked:

FieldUpdateForbiddenException: A list field (field_travel_purpose) with existing data cannot have its keys changed. in list_field_update_forbid() (line 363 of modules/field/modules/list/list.module).

jakubmroz’s picture

Just Truncate the field_data and field_revision table for specific field.

qqboy’s picture

option1 use taxonomy
option2 select field_data_field_name to updated allowed value list