Problem/Motivation

I've run into a strange bug where a multi-value field collection field creates multiple revisions of the same field collection entity. I can recreate it on a pretty clean installation (using simplytest.me with the field_collection module and devel only).

To recreate...

1. Create a content type that has a field collection field called "Collection" with "Number of values" set to unlimited.

2. Create a field collection field called "Collection name" that consists of a text field only.

3. Create a new node with three or more field collection items and save it.

Field collection form values

As expected, this creates a node with three field collection entities. The values of the field collection field are:

Correct field collection values

You can see that each has a different entity ID (the value). This is correct.

4. Now, edit the node and delete all three field collection items by clicking each "Remove" button.

5. Before saving the node, enter a value for "Collection name" in the new field collection.

6. Click "Add another item" and enter a value for "Collection name" in the new field collection field.

7. Click "Add another item" again and the value for the "Collection name" text field in the newly-added field collection will be pre-filled with the value from the one above.

8. If you then save the node, the "Collection" field collection will now contain duplicates-- the entity_id (value) will be the same, but the revision IDs are different:

Incorrect field collection values


This is wrong. Deltas 1 and 2 are duplicates of entity ID 10 (revision IDs 14 and 15).

Expected behavior: It should create new distinct field collection entities rather than multiple revisions of the same entity.

Also...

If you click the "Remove" button on all of the existing field collection items, click it once more for the single empty field collection, enter a value in the text field, then click "Add another item", the first newly-added field collection will be pre-filled with the value from the one above (like in step 7 above). So, you'll see the bug with the *first* "add another rather than the second.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

jrb’s picture

Issue summary: View changes
jrb’s picture

Issue summary: View changes
jrb’s picture

Issue summary: View changes
rbrandon’s picture

Good description jrb, I saw this as well with a similar setup.

My suspicion is that the "Remove" callback that field_collections uses is leaving bad data in the form state.

jrb’s picture

I just happened to be looking at the Field Collection AJAX module and found that, when using this module, this problem does not occur. So, this could be a workaround until this bug is fixed.

chokobanana’s picture

I just noticed that I'm having the same problems with beta8. Yesterday beta9 was released. Has this issue been resolved?

jedihe’s picture

This bug will cause an inconsistency between the field_data_ table (for the field_collection field) and the field_collection_item table: they'll only match on value = item_id, but not on revision_id = revision_id.

For anybody wanting to troubleshoot a site, I'm pasting a drush script that will construct a query for all field_collection fields having this data inconsistency. Starting from that, you can check into each separate case to decide what to do next. Please note it's hardcoded only for fields under 'node' entities.


/**
 * @file
 * Helper script to find any value for a field collection field (field_data
 * table) that matches field_collection_item only on item_id but not on
 * revision_id.
 *
 * Usage:
 * Get the entire query to run:
 *   drush scr /path/to/this-script.php
 * Directly run the query via drush:
 *   drush sqlq "$(drush scr /path/to/this-script.php)"
 * If wanted to use mysql cli:
 *   drush scr /path/to/this-script.php > /tmp/full-query.sql
 *   drush sql-cli
 *   source /tmp/full-query.sql
 */

function issue2416237_get_field_query($field_info) {
  $fd_table = _field_sql_storage_tablename($field_info);
  $field_value = _field_sql_storage_columnname($field_info['field_name'], 'value');
  $field_revision_value = _field_sql_storage_columnname($field_info['field_name'], 'revision_id');

  $field_query = "
SELECT
  node.title AS node_title,
  node.nid AS nid,
  node.vid as vid,
  fdt.delta,
  fdt.$field_value fc_value,
  fdt.$field_revision_value fc_revision,
  fci.item_id,
  fci.revision_id,
  fci.field_name
FROM
    node node
        LEFT JOIN
    $fd_table fdt ON node.nid = fdt.entity_id
        AND (fdt.entity_type = 'node'
        AND fdt.deleted = '0')
        INNER JOIN
    field_collection_item fci ON fdt.$field_value = fci.item_id
WHERE
    fci.revision_id != fdt.$field_revision_value
ORDER BY fc_value ASC
  ";

  return $field_query;
}

function issue2416237_get_fc_fields_info() {
  $field_info = field_info_fields();

  $fc_fields = array_filter($field_info, function ($item) { return $item['type'] == 'field_collection'; });

  return $fc_fields;
}

function issue2416237_get_fc_full_query() {
  $fc_fields = issue2416237_get_fc_fields_info();

  $queries = array();
  foreach ($fc_fields as $fc_field_name => $fc_field_info) {
    $queries[$fc_field_name] = "(" . issue2416237_get_field_query($fc_field_info) . ")";
  }

  $query = implode(" UNION ", $queries);

  return $query;
}

echo issue2416237_get_fc_full_query();
darrenwh’s picture

Hi,
I'm also experiencing this issue, has anyone come any closer to a solution?

darrenwh’s picture

Priority: Normal » Major

Escalating

darrenwh’s picture

Version: 7.x-1.0-beta8 » 7.x-1.0-beta10

I'm able to replicate in beta 10, so changed version

Ashley George’s picture

I'm putting forward a patch to fix this.

The problem was in the 'field_collection_remove_submit' function.

The loop that adjusts the field collection item entities was using the wrong thing as an upper limit. The idea was that a dummy item is created whenever a real one was removed. This is presumably so Drupal knows to start the ids from the right point when it actually saves.

Suppose there are 5 items in a field collection. Deleting one in the UI causes remove function to delete a FC item, create a dummy one, and increment down the 'items_count' variable. Now it looks like there are 4 items in the UI, the 'item_count' is 4 but there are 5 actual FC item entities - including the dummy one.

The problem was the loop only went up to the 'item_count' value so in our example, upon deleting another item, the loop only went up to 4, when there were actually 5 items to process. This results in the array going out of whack, and the above symptoms occurring.

darrenwh’s picture

Status: Active » Needs review

Setting to needs review

ray17n’s picture

#11 worked for me. Thank you.

rbrandon’s picture

#11 fixes the issue for me as well. Thanks.

darrenwh’s picture

Status: Needs review » Reviewed & tested by the community

Setting this as Reviewd

jmuzz’s picture

Status: Reviewed & tested by the community » Needs work

Unfortunately the proposed solution does not work when the "Hide blank items" setting is unchecked. I am not sure it is progress either because the form does seem to work without the patch if that setting is unchecked.

The blank items being created are an earlier attempt to fix similar behaviours.

The form does seem to work in 8.x-1.x. You can find very similar code in src/Plugin/Field/FieldWidget/FieldCollectionEmbedWidget.php . I've been looking at it and trying some similar changes on 7.x-1.x based on what's there but so far I haven't gotten it working any better either.

I do notice that the 8.x-1.x version is hiding the blank items by making a change to items_count while the 7.x-1.x version is returning from the field_collection_field_widget_form early and making a change to #max_delta. I think that might be the source of the differing behaviours.

  • Ashley George authored 1ff4fb6 on 7.x-1.x
    Issue #2416237 by Ashley George, jrb: Deleting field collection items...
jmuzz’s picture

Status: Needs work » Fixed

My bad, I had made a mistake when testing.

This is committed and will be in the next dev version.

It probably won't be able to work the same as the 8.x-1.x version unless we implement a custom behaviour for multiple value field collection fields.

Ashley George’s picture

Great news, thanks!

Status: Fixed » Closed (fixed)

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