Reverting to revisions prior to addition of field translations is broken

Created on 10 May 2013, about 11 years ago
Updated 30 April 2022, about 2 years ago

Problem/Motivation

field_sql_storage_field_storage_write() does a DELETE ... INSERT.

The DELETE is restricted by field language:

      // Delete languages present in the incoming $entity->$field_name.
      // Delete all languages if $entity->$field_name is empty.
      $languages = !empty($entity->$field_name) ? $field_languages : $all_languages;

This causes a problem in the following situation:

1. Create a new node

2. Add a translation in a new revision.

3. Revert back to the original revision.

The original revision will have values set for $entity->field_name but only in the language of the original revision.

This means that the DELETE query only deletes values from {field_data_FIELD_NAME} WHERE language = the original language.

The result is that the field values for the translations remain in the {field_data_FIELD_NAME} table, albeit within incorrect revision IDs (they point to the middle revision, not the new reverted revision).

Further to this, if you then load the node, because field_sql_storage just loads whatever's in the {field_data_*} table, it will happily load those field values back into the $node object - since they're there in the table ready to be loaded.

Major for two reasons:

1. if you had open translation permissions and someone added something to a translation which was the cause of the revert, the revert will fail. The only way to remove that content would be direct database queries or manually deleting then recreating the entire node, or saving a new revision with different translated values instead of reverting. Additionally if you do something like revert then edit, the edit operation will completely resurrect the translations including with the correct revision ID (I think).

2. The bug leaves the database in an inconsistent state - the field_data_* tables are supposed to store data for the current revision, not the current revision and any random multilingual data from previous revisions.

Proposed resolution

I'm uploading a patch but I don't think it's committable - this just removes the language check altogether. This removes support for saving an entity with only translations in some languages populated - since anything else will be deleted but not re-inserted.

This is similar-ish to #1126000: [meta] hook_field_*() called on fields not set in the $entity object (partial updates) in the sense that partial entity updates are broken.

Remaining tasks

Test whether the bug exists in 8.x, and fix the patch for 7.x.

🐛 Bug report
Status

RTBC

Version

7.0 ⚰️

Component
Field 

Last updated about 6 hours ago

Created by

🇬🇧United Kingdom catch

Live updates comments and jobs are added and updated live.
  • Needs issue summary update

    Issue summaries save everyone time if they are kept up-to-date. See Update issue summary task instructions.

  • Needs subsystem maintainer review

    It is used to alert the maintainer(s) of a particular core subsystem that an issue significantly impacts their subsystem, and their signoff is needed (see the governance policy draft for more information). Also, if you use this tag, make sure the issue component is set to the correct subsystem. If an issue significantly impacts more than one subsystem, use needs framework manager review instead.

  • Needs tests

    The change is currently missing an automated test that fails when run with the original code, and succeeds when the bug has been fixed.

Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

Production build 0.69.0 2024