This is not an issue that comes up often, but it's got the potential to bite.
field_available_languages caches it's set of languages for a given entity type and field, but the static cache is not cleared when a field is updated in field_update_field. This means that even though a field might have had it's 'translatable' setting changed, the available languages won't change.
This leads to interesting things like this, if you had a node with a 'translatable' => FALSE 'body' field.
// Load a node type with a body field, which will cache the languages as array(LANGAUGE_NONE);
$nid = 1;
$node = node_load($nid);
// Change the field language.
$body = field_info_field('body');
$body['translatable'] = 1;
field_update_field($body);
// Move the LANGUAGE_NONE field values to be english values
$node->body['en'] = $node->body[LANGUAGE_NONE];
$node->body[LANGUAGE_NONE] = array();
node_save($node);
At this point, because the list LANGUAGE_NONE was cached as the only language, the body field english values are erased and the field will no longer have any values.
There are a few different places that this could be cleared, and I'm not sure which is best.
* http://api.drupal.org/api/drupal/modules--field--field.crud.inc/function...
* http://api.drupal.org/api/drupal/modules--field--field.module/function/f...
* http://api.drupal.org/api/drupal/modules--field--field.info.inc/function...
This came up when I was reviewing #1279372: Enable bulk field language updates when switching field translatability
Comments
Comment #1
plachGood catch, Logan!
At a first glance I'd say field_info_cache_clear looks like the most appropriate place to fix this.
Comment #2
loganfsmyth CreditAttribution: loganfsmyth commentedHere's an initial shot at this.
The test in entity_query.test was actually resetting this cache all on its own because it doesn't pass otherwise, so I've also fixed it to not clear the cache.
There is one test in field.test that would have caught this, but it was changing the field array to have a different name. I can't think of any good reason that it needs to do that, so I've removed the field name change, and added a proper field_update_field call so that the field_available_languages call will be running on a real field object.
Lets see what the testbot thinks.
Comment #3
plachLooks great!
Comment #4
catchYep. Committed/pushed to 8.x, will need a quick re-roll for D7.
Comment #5
yched CreditAttribution: yched commentedI don't understand that hunk ?
-2 days to next Drupal core point release.
Comment #6
loganfsmyth CreditAttribution: loganfsmyth commented@yched field_available_languages takes a field array as an argument and caches the languages based on the entity_type and field_name values. In the original test the field array's field_name was being changed so no apparent reason. This change means that the next call doesn't read from the cache since the name is different. It also meant that field_available_languages was essentially being passed a fake field array that doesn't exist in the DB, which seems odd.
By removing the name change, and calling field_update_field, I make sure that the field is properly updated before calling field_available_languages.
Does that seem reasonable.
Comment #7
plachExactly. Moreover the field's translatabilty is changed, so the call to field_update_field() makes that "official" :)
Comment #8
aspilicious CreditAttribution: aspilicious commentedReroll :)
Comment #9
plachThanks! can you post also the test only patch?
Comment #10
aspilicious CreditAttribution: aspilicious commentedComment #11
yched CreditAttribution: yched commented@loganfsmyth : ok, makes sense now, thanks !
Comment #13
aspilicious CreditAttribution: aspilicious commentedI think #8 is rtbc
Comment #14
plachYes, RTBC patch in #8.
Comment #15
webchickCommitted and pushed to 7.x. Thanks!
Comment #17
cweagansUpdating tags per http://drupal.org/node/1517250
Comment #18
cweagansUpdating tags per http://drupal.org/node/1517250
Comment #18.0
cweagansUpdated issue summary.