$entity->isDefaultTranslation() behaves incorrectly when changing default translation, causing file/image field usage to be set to zero, causing files to be deleted

Created on 3 October 2016, about 8 years ago
Updated 17 October 2023, about 1 year ago

Problem/Motivation

Images uploaded to an image field are lost when the node language is changed (because file usage incorrectly drops down to zero, causing the permanent file to be marked temporary, and then eventually being deleted — after 6 hours by default).

Same for files uploaded to a file field.

Steps to reproduce

  1. create a content type with an image field
  2. enable >=2 languages in site
  3. set the content translatable (tested setting the file translatable or not)
  4. create a node with an image and save it
  5. verify that the uploaded file has its status column in the file_managed table set to 1,
    and it has 1 usage in the file_usage table
  6. edit the node and change the language
    • expected result: the uploaded file still has its status column in the file_managed table set to 1, and it has 1 usage in the file_usage table
    • actual result: the uploaded file now has its status column in the file_managed table set to 0, and it has 0 usage in the file_usage table
  7. run cron 6 hours later (this is the default value of the temporary_maximum_age setting in system.file)
    • expected result: the uploaded file is still present (because usage > 0)
    • actual result: the uploaded file is absent (because usage = 0)

Note: see #40, where it is explained how this same problem is even reproducible on sites without content_translation are affected by this, merely having the language () module installed and having >1 interface language enabled is sufficient to reproduce this problem for image/file fields on User entities!

Proposed resolution

Root cause analysis:

  • \Drupal\file\Plugin\Field\FieldType\FileFieldItemList::delete() removing file usages:
      public function delete() {
        parent::delete();
        $entity = $this->getEntity();
    
        // If a translation is deleted only decrement the file usage by one. If the
        // default translation is deleted remove all file usages within this entity.
        $count = $entity->isDefaultTranslation() ? 0 : 1;
        foreach ($this->referencedEntities() as $file) {
          \Drupal::service('file.usage')->delete($file, 'file', $entity->getEntityTypeId(), $entity->id(), $count);
        }
      }
    
  • to delete file usages, it relies on $entity->isDefaultTranslation() (i.e. \Drupal\Core\TypedData\TranslatableInterface::isDefaultTranslation()) to determine whether a translation is being deleted or not
  • $entity->isDefaultTranslation() behaves incorrectly when the default translation is being changed

Therefore the solution is: fix \Drupal\Core\Entity\ContentEntityBase::isDefaultTranslation().

Remaining tasks

TBD

User interface changes

None.

API changes

None.

Data model changes

None.

🐛 Bug report
Status

Fixed

Version

10.2

Component
Entity 

Last updated about 23 hours ago

Created by

🇪🇸Spain quiron Barcelona

Live updates comments and jobs are added and updated live.
  • Triaged core critical

    There is consensus among core committers that this is a critical issue. Only core committers should add this tag.

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.71.5 2024