Right, this was quite a tricky issue to track down, but here's the setup that I think should be the simplest way to reproduce this issue:
- A node type (or any other host entity) that has two fields:
- A file field, with the media module as a widget on top of it.
- A link field.
- Add some content to that node, entering some data in the link field, and uploading an image into the file field.
- Now, decide that you want to replace the image, and do so through the file edit page: /file/123/edit, replace the image with one of a different size.
- On submit, you should get a PDO execption on a query similar to the following:
INSERT INTO {field_data_field_link} (entity_type, entity_id, revision_id, bundle, delta, language, field_link_url, field_link_title, field_link_attributes) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3, :db_insert_placeholder_4, :db_insert_placeholder_5, :db_insert_placeholder_6, :db_insert_placeholder_7, )Note that that query is missing the
db_placeholder_8forfield_link_attributes. - Click back, and try changing the file again. It should work this time, but upon checking the node, the contents of your link field should have been wiped out.
(If not, then in my particular case the data loss may occur because the host entity the file field and link field are on is a field collection, on the node. The PDO exception should occur for the node case though too I think.)
As far as I can tell the reason this is happening is because when you replace an image with another of a different size, file_entity module calls _file_entity_update_image_field_dimensions which tries to update data in fields on entities that reference that file. It saves these changes by calling field_attach_update, but we can note that link module actually requires it's field_attach_presave code to have run to serialize the attributes down into a string for inserting into the DB.
This causes the field system to try and write an array into the attributes column in the field storage table, which the DB system doesn't allow, and so the DB query is built missing some data, and PDO throws the exception.
I'm not sure if it's okay just add a call to field_attach_presave into that function?
Comments
Comment #1
steven jones commentedA patch like the following might work? But really am unsure of the consequences of adding the presave in here.
Comment #2
steven jones commentedAnd to prevent some notices we should set the
originalparameter on the entity too.Comment #3
aaron commentedThis works as advertised. Thanks for the great work!
Comment #4
ParisLiakos commentedi have hard time to grasp whats going on there
Comment #5
dave reidWe should actually be setting $entity->original as the object before we unset $entity->revision, otherwise it's not 'truly' the original.
Also wondering if we need to switch to a SQL storage only approach for now rather than calling field_attach_update on each entity. Would be easier to do these in bulk then.
Comment #6
dave reidRevised patch that moves the logic for saving the entity fields to a new function, which also resets the entity cache for those entities.
Comment #7
acbramley commentedI had the same issue, updating to Link 7.x-1.1 seemed to solve it for me as there were some changes to the way the attributes were handled (changed from field_presave to field_update hook among other things).
Comment #8
devin carlson commentedThe patch in #6 applied cleanly and fixed both the issue of
field_attach_presave()not being called and the original property not being set in all cases.Comment #9
devin carlson commentedCommitted to 7.x-2.x.