Problem/Motivation

A module providing a field type can use the TextFormat element type to invoke editor handling. However, doing so will lead to the bug that files embedded vie an editor in the text area will not be registered as used and therefore, if not used elsewhere, by default will be deleted.

This bug occurs for example in the FAQ Field module, see #2744905: Inline images in the answer field are removed during file garbage collection.

The issue arises from the function _editor_get_formatted_text_fields(), which is used to determine whether a given field should be scanned for embedded files. The function uses a hard-coded list of field types:

  // Only return formatted text fields.
  return array_keys(array_filter($field_definitions, function (FieldDefinitionInterface $definition) {
    return in_array($definition->getType(), array('text', 'text_long', 'text_with_summary'), TRUE);
  }));

Proposed resolution

Criteria to consider for a solution

  • Has to support the three existing core field types, 'text', 'text_long', 'text_with_summary'.
  • Supported field types must have a value property, since the processing in _editor_get_file_uuids_by_field(), which calls _editor_get_formatted_text_fields(), consults $field_item->value.

Proposed solution

Examine field types and return those that are a subclass of TextItemBase.

This is an interim improvement pending a fuller solution in #2732429: Add more metadata to field type properties to identify text with a format and separate user provided text from machine names.

Pros:

  • Reduces the hard-coding/special-casing of core field types.
  • Maintains support for the three existing core field types.
  • Encourages other modules providing formatted text field types to extend the existing core ones or a common base, rather than adopting custom solutions.
  • Avoids significant API changes.

Cons:

  • May be difficult for module developers to discover. Would need documentation.
  • Doesn't fully remove special-casing of core field types, since this snippet remains:
          if ($field_item->getFieldDefinition()->getType() == 'text_with_summary') {
            $text .= $field_item->summary;
          }
    

    However, that could be separately addressed (for example, by determining if the given field type plugin has a 'summary' property instead of using a hard-coded field type ID).

Remaining tasks

User interface changes

None.

API changes

Modules providing a field type that includes filtered text should extend TextItemBase or one if its subclasses so that file usage of embedded files will be handled by the Editor module.

An example of such a field type plugin is the Editor Test module's Drupal\editor_test\Plugin\Field\FieldType\EditorTestTextLongItem class.

Data model changes

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

nedjo created an issue. See original summary.

nedjo’s picture

Patch using the first of the approaches in "Proposed resolution".

Status: Needs review » Needs work

The last submitted patch, 2: editor-field-types-2857444-2.patch, failed testing.

nedjo’s picture

Status: Needs work » Needs review
FileSize
928 bytes
nedjo’s picture

Status: Needs review » Needs work

Invoke an alter hook to allow other modules to register their field types as providing formatted text fields.

This doesn't turn out to be a great approach because the code in Editor assumes a 'value' property, which field types may or may not define.

Examine field types and use those that extend TextItemBase.

This might be a better alternative.

nedjo’s picture

Issue summary: View changes
Status: Needs work » Needs review
FileSize
1.34 KB

Testing instead for subclass of TextItemBase.

nedjo’s picture

Issue summary: View changes
jofitz’s picture

Status: Needs review » Needs work
Issue tags: +Needs reroll

No longer applies after https://www.drupal.org/node/2776975.

jofitz’s picture

Status: Needs work » Needs review
Issue tags: -Needs reroll
FileSize
1.33 KB

Re-rolled.

Wim Leers’s picture

The proper solution is #2732429: Add more metadata to field type properties to identify text with a format and separate user provided text from machine names. It may not be a practical solution though.

Also this is not a bug, this is a missing capability.

nedjo’s picture

Title: Modules cannot register formatted text field types for file processing » Editor module fails to track usage of files embedded in non-core fields
Category: Feature request » Bug report

this is not a bug, this is a missing capability.

True of the title I gave the issue, but there is a bug here.

If the editor didn't attach to non-core text fields, or didn't allow files to be embedded in non-core fields, this would not be a core bug. But it does. #2744905: Inline images in the answer field are removed during file garbage collection is a bug, and it results not from misuse of a core API but from using the API as designed.

So changing title to clarify the bug, which is parallel to #2708411: [PP-1] editor.module's editor_file_reference filter not tracking file usage correctly for translations and #2725415: Text Editor module fails to track usage of images uploaded in text_with_summary fields, allows uploaded images to be deleted.

Agreed that #2732429: Add more metadata to field type properties to identify text with a format and separate user provided text from machine names would be a better solution. But given that #2732429 seems far from a resolution, is the limited improvement in this issue worth considering?

Wim Leers’s picture

Status: Needs review » Needs work
Issue tags: +Needs tests

But given that #2732429 seems far from a resolution, is the limited improvement in this issue worth considering?

Absolutely!

On two conditions:

  1. add a @todo explaining that this must be removed as soon as #2732429 lands
  2. test coverage proving this now works for some other field type that subclasses TextItemBase

Then I'd be happy to RTBC this :) This is a totally solid, totally not-BC-nightmare-causing, practical temporary work-around.

(I'm sorry that I implied otherwise — I was just in a hurry.)

gaurav.kapoor’s picture

Added @todo.

nedjo’s picture

I'm sorry that I implied otherwise — I was just in a hurry.

No prob. Thanks for the closer look.

  • Move and refine @todo.
  • Add tests. Previously the page node type and body field were added programmatically, but since we need a new field storage and field I've switched to exported config (simpler).

The last submitted patch, 14: editor-field-types-2857444-14-tests-only.patch, failed testing.

The last submitted patch, 14: editor-field-types-2857444-14.patch, failed testing.

nedjo’s picture

Okay, apparently there's a reason the test module config is added programmatically, so here's a patch that doesn't mess with that ;)

The last submitted patch, 17: editor-field-types-2857444-17-tests-only.patch, failed testing.

nedjo’s picture

Issue summary: View changes

Updating summary with API changes.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

scottsawyer’s picture

I ran into an issue with the markup module that seems to be related, after some period of time ( probably after cron ), inline files uploaded through the editor attached to a Markup field are removed.

I filed this issue in that queue: https://www.drupal.org/project/markup/issues/2943406

I wanted to find out if this patch works in Drupal 8.4, and if the issue I referenced is likely due to the same bug.

If it is the same bug, what, if anything, does changes to that module would need to be made to ensure files uploaded don't get removed?

nedjo’s picture

what, if anything, does changes to that module would need to be made to ensure files uploaded don't get removed?

See the API changes section of the issue summary.

vaccinemedia’s picture

I'm having this exact issue on the simple block module @scottsawyer and there is a related issue here: https://www.drupal.org/project/simple_block/issues/2961654 - and the comment makes sense where they mention exporting the block contents to config wouldn't export the image file.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

FiNeX’s picture

Hi, I'm experiencing the same bug on body fields :-(

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

hgneng’s picture

This is how I fix this issue right now. I detect images in text_format content and add file usage for them after form submit.

https://cto.eguidedog.net/node/997

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

pcambra’s picture

Priority: Normal » Major
Status: Needs review » Reviewed & tested by the community
Issue tags: -Needs tests

I think this has tests now.

I think it could be good to have some sort of property in the custom fields that says "I might have an image, please don't delete it", but I've tested the patch on 9.1.3 and works for my use case, the fields need to inherit from TextItemBase and they need to be able to expose the "value" property. Any other combination will result in mysteriously missing files so that grants, I think a priority bump.

nedjo’s picture

@pcambra thx for picking up this old issue.

Rebased on 9.2.x and made three small changes.

  1. +++ b/core/modules/editor/tests/modules/src/Plugin/Field/FieldType/EditorTestTextLongItem.php
    @@ -0,0 +1,21 @@
    + * Plugin implementation of the 'text_long' field type.
    

    This should be 'editor_test_text_long' rather than 'text_long'.

  2. +++ b/core/modules/editor/editor.module
    @@ -583,8 +586,12 @@ function _editor_get_formatted_text_fields(FieldableEntityInterface $entity) {
    +    return is_subclass_of($plugin_class, 'Drupal\text\Plugin\Field\FieldType\TextItemBase');
    

    The form of the second argument to is_subclass_of() is inconsistent in core. Maybe in general in core we're moving towards a use statement and ClassName::class rather than passing the full class name as a string? Changing in any case.

  3. +++ b/core/modules/editor/tests/src/Kernel/EditorFileUsageTest.php
    @@ -199,6 +218,28 @@ public function testEditorEntityHooks() {
    +      $this->assertIdentical(['editor' => ['node' => [1 => '1']]], $file_usage->listUsage($image_entity), 'The image ' . $image_paths[$key] . ' has 1 usage.');
    

    The other parallel calls in the test have been changed to ::assertSame() so presumably we should do the same.

alexpott’s picture

Version: 9.2.x-dev » 9.1.x-dev

This looks like a sensible fix to a problem the would result in data loss.

Committed and pushed 02388c80eb to 9.2.x and 21af6a87ad to 9.1.x. Thanks!

  • alexpott committed 02388c8 on 9.2.x
    Issue #2857444 by nedjo, jofitz, gaurav.kapoor, Wim Leers: Editor module...

  • alexpott committed 21af6a8 on 9.1.x
    Issue #2857444 by nedjo, jofitz, gaurav.kapoor, Wim Leers: Editor module...
alexpott’s picture

Status: Reviewed & tested by the community » Fixed
alexpott’s picture

Version: 9.1.x-dev » 8.9.x-dev
Status: Fixed » Patch (to be ported)
FileSize
5.82 KB

Discussed with @catch we agreed to backport this to 8.9.x if a patch can be rolled based on #33.

Git can auto-merge this so here's the patch...

$ git cherry-pick -x 02388c80eb
Auto-merging core/modules/editor/tests/src/Kernel/EditorFileUsageTest.php
[2857444-8.9.x 4a4bf83ddd] Issue #2857444 by nedjo, jofitz, gaurav.kapoor, Wim Leers: Editor module fails to track usage of files embedded in non-core fields
 3 files changed, 72 insertions(+), 2 deletions(-)
 create mode 100644 core/modules/editor/tests/modules/src/Plugin/Field/FieldType/EditorTestTextLongItem.php
florianmuellerCH’s picture

We have a custom config form with multiple long text (formatted) fields. When uploading images there and saving, the usage is still not registered with this patch. Any Idea how this could be solved?

alexpott’s picture

@fmueller_previon I think this is because you're saving things in config and not an entity field. This is about entity fields.

florianmuellerCH’s picture

@alexpott that's correct, but in this case we don't have a solution for this yet.

I ended up parsing the text for any file entities and then manually adding a File Usage on a certain Entity (I attached them to the frontpage), just to ensure they won't get deleted. I'm not quite sure if this is "the way to go" for that ;)

alexpott’s picture

Status: Patch (to be ported) » Fixed

As per the discussion with @catch backported to 8.9.x.

Committed 16d35ec and pushed to 8.9.x. Thanks!

@fmueller_previon I think the discussion about config fields deserves it's own issue as currently Drupal core make no attempt to count files used in config.

  • alexpott committed 16d35ec on 8.9.x
    Issue #2857444 by nedjo, alexpott, jofitz, gaurav.kapoor, Wim Leers:...

Status: Fixed » Closed (fixed)

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

hatuhay’s picture

Cannot reopen but this is not fixed on D8.9.15 and patch fail to apply on this version

galactus86’s picture

any update on this?

mashot7’s picture

Having the same issue for 9.3.21

nedjo’s picture

but this is not fixed

Having the same issue

Note that this issue did not in itself fix existing issues in contrib modules. Instead, it provided an API method contrib modules could choose to use, see the API changes section of the issue summary.

If you're seeing a bug like that described in this issue you can look for an existing issue on the contrib module you're using and, if you don't find one, open a new one, referencing this issue.