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:
    1. A file field, with the media module as a widget on top of it.
    2. 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_8 for field_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

steven jones’s picture

Status: Active » Needs review
StatusFileSize
new461 bytes

A patch like the following might work? But really am unsure of the consequences of adding the presave in here.

steven jones’s picture

And to prevent some notices we should set the original parameter on the entity too.

aaron’s picture

Status: Needs review » Reviewed & tested by the community

This works as advertised. Thanks for the great work!

ParisLiakos’s picture

Assigned: Unassigned » dave reid

i have hard time to grasp whats going on there

dave reid’s picture

Priority: Critical » Major
Status: Reviewed & tested by the community » Needs review
Issue tags: +7.x-2.0 alpha blocker

We 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.

dave reid’s picture

Revised patch that moves the logic for saving the entity fields to a new function, which also resets the entity cache for those entities.

acbramley’s picture

I 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).

devin carlson’s picture

Status: Needs review » Reviewed & tested by the community

The 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.

devin carlson’s picture

Status: Reviewed & tested by the community » Fixed

Committed to 7.x-2.x.

Automatically closed -- issue fixed for 2 weeks with no activity.